본문 바로가기

Windows/MFC

CImageLoader

[code]
<?xml version="1.0"?>
<image>
    <normal>
        <left>normal_left.bmp</left>
        <center>normal_cen.bmp</center>
        <right>normal_right.bmp</right>
    </normal>
    <over>
        <left>over_left.bmp</left>
        <center>over_cen.bmp</center>
        <right>over_right.bmp</right>
    </over>
    <active>
        <left>active_left.bmp</left>
        <center>active_cen.bmp</center>
        <right>active_right.bmp</right>
    </active>
    <btnOneImage>
        <normal>btn_save_blue.bmp</normal>
        <over>btn_save_cyan.bmp</over>
        <active>btn_save_magenta.bmp</active>
    </btnOneImage>
    <blockImage>btn_save_blue.bmp</blockImage>
    <buttonIcon>btnIcon.bmp</buttonIcon>    
</image>
[/code]

[code]
CImageLoader g_img;
g_img.LoadXML(L"./Images", L"ImagesInfo.xml");
[/code]

[code]
CPaintDC dc(this);

CDC mDC;
mDC.CreateCompatibleDC(&dc);
mDC.SelectObject(g_img.FindBitmap(L"buttonIcon"));
dc.BitBlt(0, 0, 300, 300, &mDC, 0, 0, SRCCOPY);

CBitmap* p = g_img.FindBitmap(L"normal");
mDC.SelectObject(p++);
dc.BitBlt(80, 0, 300, 300, &mDC, 0, 0, SRCCOPY);

mDC.SelectObject(p++);
dc.BitBlt(90, 0, 300, 300, &mDC, 0, 0, SRCCOPY);

mDC.SelectObject(p);
dc.BitBlt(100, 0, 300, 300, &mDC, 0, 0, SRCCOPY);
[/code]



[code]
// DATE        : February 22, 2007
// CODER    : aucd29 (ccd@apsat.co.kr)
//
//
//

// Require
// --------------------------------------------------------
// CParserXML
// http://www.sarangnamu.net/basic/basic_view.php?no=2825
//

// NOTE    : February 22, 2007
// --------------------------------------------------------
// * 이미지를 손쉽게 로딩할 수 있게 하자.
// 기존에 RESOURCE 부분에 넣고 수정하고 그러는거 너무
// 불편하니깐...
//
// * GDI, GDI+ 모두 지원
//
// BUGFIX : February 27, 2007
// --------------------------------------------------------
// * LENGTH 값 안넣은거 수정
// * GDI+ 에 메모리 해제 관련 수정
//
// BUGFIX : March 5, 2007
// --------------------------------------------------------
// * Memory leak 수정
// * 잘못된 방식의 메모리 할당 수정
//

#include "StdAfx.h"
#include "ImageLoader.h"

CImageLoader::CImageLoader(void)
: m_bGdiPlus(false)
{
}

CImageLoader::~CImageLoader(void)
{
    if (m_bGdiPlus)
    {
#ifdef _GDIPLUS_H
        DeleteImagesGdiplus();
#endif;
    }
    else
    {
        DeleteImages();
    }
}

void CImageLoader::LoadXML(CString szDir, CString szFile, bool bGdiPlus)
{
    // XML 파일일 로드한다.
    m_szDir     = szDir;
    m_bGdiPlus = bGdiPlus;
    Load(szDir + L"/" + szFile);
    ReadData();
}

void CImageLoader::ReadData(void)
{
    BSTR nodeName;

    m_hr = m_pDocument->get_documentElement(&m_pElement);
    if (FAILED(m_hr) || m_pElement == NULL)
    {
        AfxMessageBox(L"Empty document!");
    }

    // ROOT 노드에 이름을 알아오자
    m_pElement->get_nodeName(&nodeName);
    TRACE(L"------------------------------------------\n");
    TRACE(L"ROOT NODE : %s\n", CString(nodeName));
    TRACE(L"------------------------------------------\n");

    // CHILD 를 위해서 준비중
    MSXML::IXMLDOMNode* pChild = NULL;
    m_hr = m_pElement->get_firstChild(&pChild);

    if (!m_bGdiPlus)
    {
        FindChildNode(pChild);
    }
    else
    {
#ifdef _GDIPLUS_H
        FindChildNodeGdiPlus(pChild);
#endif;
    }

    SysFreeString(nodeName);
}

void CImageLoader::LoadImages(CImageData* pImg, int nIndex, CString szPath)
{
    if (szPath.GetLength() == 0)
    {
        // 파일명이 없으면NULL을 입력해두자.        
        return;
    }

    // 파일이 존재하면 해당 파일을 읽어 들이자.
    // 이곳에서 첫 splash window 와 연동하여 로딩 파일을
    // 보여주면 좋을 것 같기도 하다! 추가적으로 구현해야할 부분이겠지
    //
    if (!pImg->m_pBmp[nIndex].Attach((HBITMAP)LoadImage(NULL,m_szDir + L"/" + szPath,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)))
    {
        CString szError;

        szError.Format(L"Error : File Not Found (%s) <ImageLoader>", m_szDir + L"/" + szPath);
        AfxMessageBox(szError);
        exit(1);
    }
}

CBitmap* CImageLoader::FindBitmap(CString szName)
{
    // 원하는 것 찾고 리턴하기
    POSITION pos = m_list.GetHeadPosition();
    CImageData* pImg;

    while (pos)
    {
        pImg = &m_list.GetNext(pos);
        
        if (pImg->m_szName == szName)
        {
            return pImg->m_pBmp;
        }
    }

    CString szError;
    szError.Format(L"Element Not Found (%s) <ImageLoader>", szName);
    AfxMessageBox(szError);

    return NULL;
}

void CImageLoader::DeleteImages(void)
{
    POSITION pos = m_list.GetHeadPosition();
    CImageData* pImg;

    // 동적 할당한 이미지를 찾아서 지우고
    while (pos)
    {
        pImg = &m_list.GetNext(pos);

        if (pImg->m_nLength == 1)
        {
            DeleteObject(pImg->m_pBmp);
            delete pImg->m_pBmp;
        }
        else
        {
            delete[] pImg->m_pBmp;
        }
    }

    // 링크드리스트 지우자.
    m_list.RemoveAll();
}

void CImageLoader::FindChildNode(MSXML::IXMLDOMNode* pChild)
{
    BSTR nodeType, nodeChildName;

    while (true)
    {
        pChild->get_nodeTypeString(&nodeType);

        if (!wcscmp(nodeType, L"element"))
        {
            TRACE(L"ELEMENT ");
            pChild->get_nodeName(&nodeChildName);

            // 이미지의 이름을 설정하고
            CImageData img;
            img.m_szName = CString(nodeChildName);

            // 해당 노드에 자식 노드를 검사해서 갯수 체크하고
            MSXML::IXMLDOMNodeList* nodeChild2;
            MSXML::IXMLDOMNode* listItem = NULL;
            m_hr = pChild->get_childNodes(&nodeChild2);

            if (SUCCEEDED(m_hr) && nodeChild2 != NULL)
            {
                long nLength = 0;
                nodeChild2->get_length(&nLength);
                TRACE(L"NAME %s, LENGTH :%ld\n", img.m_szName, nLength);

                // 해당 노드에 비트맵 수를 체크한 뒤에
                // 메모리를 할당한다.
                if (nLength == 1)
                {
                    img.m_pBmp = new CBitmap;
                }
                else
                {
                    img.m_pBmp = new CBitmap[nLength];
                }
                img.m_nLength = nLength;

                CString szNodeText;
                BSTR nodeText;

                // 노드에 값인 이미지 경로를 가져와서 불러들이자.
                int i;
                TRACE(L"------------------------------------------\n");
                for (i=0; i<nLength; ++i)
                {
                    listItem = NULL;
                    m_hr = nodeChild2->get_item(i, &listItem);
                    listItem->get_text(&nodeText);
                    szNodeText = CString(nodeText);
                    TRACE(L"NODE TEXT : %d : %s\n", i+1, szNodeText);

                    // 이미지를 로딩 하자.
                    LoadImages(&img, i, szNodeText);
                }
                TRACE(L"------------------------------------------\n");

                m_list.AddTail(img);
                SysFreeString(nodeText);
            }
        }
        /*else if (!wcscmp(nodeType, L"text"))
        {
        TRACE(L"text\n");
        }
        else if (!wcscmp(nodeType, L"comment"))
        {
        TRACE(L"comment\n");
        }
        else
        {
        TRACE(L"others\n");
        }*/

        m_hr = pChild->get_nextSibling(&pChild);

        if (FAILED(m_hr) || pChild == NULL)
        {
            break;
        }
    }

    SysFreeString(nodeType);
    SysFreeString(nodeChildName);
}

int CImageLoader::GetCount(void)
{
    return static_cast<int>(m_list.GetCount());
}

int CImageLoader::GetTargetCount(CString szName)
{
    POSITION pos = m_list.GetHeadPosition();
    CImageData* pImg;

    while (pos)
    {
        pImg = &m_list.GetNext(pos);

        if (pImg->m_szName == szName)
        {
            return pImg->m_nLength;
        }
    }

    return 0;
}

CPoint CImageLoader::GetImageInfo(CBitmap* pBmp)
{
    BITMAP bm;
    pBmp->GetObject(sizeof(BITMAP), &bm);

    return CPoint(bm.bmWidth, bm.bmHeight);
}

CImageData* CImageLoader::FindImageData(CString szName)
{
    POSITION pos = m_list.GetHeadPosition();
    CImageData* pImg;

    while (pos)
    {
        pImg = &m_list.GetNext(pos);

        if (pImg->m_szName == szName)
        {
            return pImg;
        }
    }

    CString szError;
    szError.Format(L"Element Not Found (%s) <ImageLoader>", szName);
    AfxMessageBox(szError);
    exit(1);

    return NULL;
}

#ifdef _GDIPLUS_H
Image** CImageLoader::FindImages(CString szName)
{
    // 원하는 것 찾고 리턴하기
    POSITION pos = m_list.GetHeadPosition();
    CImageData* pImg;

    while (pos)
    {
        pImg = &m_list.GetNext(pos);

        if (pImg->m_szName == szName)
        {
        //    TRACE("width %d, height:%d\n", pImg->m_pImg[0]->GetWidth(), pImg->m_pImg[0]->GetHeight());
            return pImg->m_pImg;
        }
    }

    CString szError;
    szError.Format(L"Element Not Found (%s) <ImageLoader>", szName);
    AfxMessageBox(szError);

    return NULL;
}

void CImageLoader::LoadImagesGdiplus(CImageData* pImg, int nIndex, CString szPath)
{
    if (szPath.GetLength() == 0)
    {
        // 파일명이 없으면NULL을 입력해두자.        
        return;
    }

    pImg->m_pImg[nIndex] = NULL;
    pImg->m_pImg[nIndex] = Image::FromFile(m_szDir + L"/" + szPath);
    if (pImg->m_pImg[nIndex] == NULL)
    {
        CString szError;

        szError.Format(L"Error : File Not Found (%s) <ImageLoader plus>", m_szDir + L"/" + szPath);
        AfxMessageBox(szError);
        exit(1);
    }
}

void CImageLoader::FindChildNodeGdiPlus(MSXML::IXMLDOMNode* pChild)
{
    BSTR nodeType, nodeChildName;

    while (true)
    {
        pChild->get_nodeTypeString(&nodeType);

        if (!wcscmp(nodeType, L"element"))
        {
            TRACE(L"ELEMENT ");
            pChild->get_nodeName(&nodeChildName);

            // 이미지의 이름을 설정하고
            CImageData img;
            img.m_szName = CString(nodeChildName);

            // 해당 노드에 자식 노드를 검사해서 갯수 체크하고
            MSXML::IXMLDOMNodeList* nodeChild2;
            MSXML::IXMLDOMNode* listItem = NULL;
            m_hr = pChild->get_childNodes(&nodeChild2);

            if (SUCCEEDED(m_hr) && nodeChild2 != NULL)
            {
                long nLength = 0;
                nodeChild2->get_length(&nLength);
                TRACE(L"NAME %s, LENGTH :%ld\n", img.m_szName, nLength);

                // 해당 노드에 비트맵 수를 체크한 뒤에
                // 메모리를 할당한다.
                if (nLength == 1)
                {
                    img.m_pImg = new Image*;
                }
                else
                {
                    img.m_pImg = new Image* [nLength];
                }
                img.m_nLength = nLength;

                CString szNodeText;
                BSTR nodeText;

                // 노드에 값인 이미지 경로를 가져와서 불러들이자.
                int i;
                TRACE(L"------------------------------------------\n");
                for (i=0; i<nLength; ++i)
                {
                    listItem = NULL;
                    m_hr     = nodeChild2->get_item(i, &listItem);
                    listItem->get_text(&nodeText);
                    szNodeText = CString(nodeText);
                    TRACE(L"NODE TEXT(%d) : %s\n", i+1, szNodeText);

                    // 이미지를 로딩 하자.
                    LoadImagesGdiplus(&img, i, szNodeText);
                }
                TRACE(L"------------------------------------------\n");

                m_list.AddTail(img);
                SysFreeString(nodeText);
            }
        }

        m_hr = pChild->get_nextSibling(&pChild);
        if (FAILED(m_hr) || pChild == NULL)
        {
            break;
        }
    }

    SysFreeString(nodeType);
    SysFreeString(nodeChildName);
}

void CImageLoader::DeleteImagesGdiplus(void)
{
    POSITION pos = m_list.GetHeadPosition();
    CImageData* pImg;

    // 동적 할당한 이미지를 찾아서 지우고
    while (pos)
    {
        pImg = &m_list.GetNext(pos);

        TRACE(L"DELETE : %s %d\n", pImg->m_szName, pImg->m_nLength);
        
        if (pImg->m_nLength == 1)
        {
            delete pImg->m_pImg;
        }
        else
        {
            delete[] pImg->m_pImg;
        }
    }

    // 링크드리스트 지우자.
    m_list.RemoveAll();
}

#endif;
[/code]

[code]
#pragma once

#include "parserxml.h"
#include <afxtempl.h>

class CImageData
{
public:
    CString m_szName;
    CBitmap* m_pBmp;
    int m_nLength;

    // GDI PLUS를 셋팅 했을 때에만 적용된다.
#ifdef _GDIPLUS_H
    Image** m_pImg;
#endif;
};

class CImageLoader :
    public CParserXML
{
protected:
    CString m_szDir;
    void ReadData(void);
    void LoadImages(CImageData* pImg, int nIndex, CString szPath);
    void DeleteImages(void);
#ifdef _GDIPLUS_H
    void DeleteImagesGdiplus(void);
    void LoadImagesGdiplus(CImageData* pImg, int nIndex, CString szPath);
#endif;
    bool m_bGdiPlus;
    
public:
    CImageLoader(void);
    ~CImageLoader(void);
    CList<CImageData, CImageData&> m_list;
    void LoadXML(CString szDir, CString szFile, bool bGdiPlus = false);
    CBitmap* FindBitmap(CString szName);
#ifdef _GDIPLUS_H
    Image** FindImages(CString szName);
    void FindChildNodeGdiPlus(MSXML::IXMLDOMNode* pChild);
#endif;
    void FindChildNode(MSXML::IXMLDOMNode* pChild);
    int GetCount(void);
    int GetTargetCount(CString szName);
    CPoint GetImageInfo(CBitmap* pBmp);
    CImageData* FindImageData(CString szName);
};
[/code]

'Windows > MFC' 카테고리의 다른 글

CDC::GetTextExtent (문자열폭 알기 text width)  (0) 2013.10.02
TEXTMETRIC (문자 높이)  (0) 2013.10.02
부모 윈도우에 DC를 이용 메모리 DC생성하기  (0) 2013.10.02
DrawGradient  (0) 2013.10.02
DRAWITEMSTRUCT, LPDRAWITEMSTRUCT  (0) 2013.10.02