본문 바로가기

Windows/MFC

CButtonEx

[code]
* GDI+ 를 지원하므로 JPEG, BMP, PNG 안가리고 모두 읽어 들일 수 있다.
* 우선은 XML로 수동적으로 읽어들이고 있으나 추후에는 링크드 리스트를 이용해서 주욱 긁어 오게 하면 되고...
* 이미지 9개로 거의 모든 버튼에 크기를 커버 가능하다. (세로로 늘일 경우는 다소 깨지긴 하지만. -_ - 한마디로 귀차나서 만든 클래스이다.)
[/code]

[code]
// ButtonEx.cpp : implementation file
//

// DATE        : February 13, 2007
// CODER    : aucd29 (aucd29@gmail.com)
// VERSION    : 1.0
//
//

// Require
// ----------------------------------------------------------
// GDI+
// installation Guide : http://sarangnamu.net/basic/basic_view.php?no=1369
// Manual(kor) : http://winapi.co.kr/project/library/gdiplus/gdiplus.htm
//
// CParserXML
// Link : http://www.sarangnamu.net/basic/basic_view.php?no=2825
//
// CRectEx
// Link : http://www.sarangnamu.net/basic/basic_view.php?no=2828
//

// ----------------------------------------------------------
// NOTE : February 13, 2007
// ----------------------------------------------------------
// * 디자인 회의 하다가 버튼 클래스가지고 -_ - 디자이너가
// 스크립트를 논하며 머라 하길래 -_- 버튼 클래스 만든다.
// 성격있는 최씨 -_ -ㅎ삐뚤어져 주겠어
//
// ----------------------------------------------------------
// NOTE : February 21, 2007
// ----------------------------------------------------------
// * GDI+ 의 단점인 느린 로딩 -_ - 을 해결하기 위해서
// CButtonLoadImage를 생성.. 조금 나아지긴 했다. 아직 느린
// 게 보이긴 하는데 -_ -;;;;;
//
// * 머랄까 음... 로딩된 이미지를 Distructor에서 Free를 해
// 주려고 했는데 오류가 난다. 왜 그런 것일까??? 우선은 주
// 석질을 했다.
//
// * 한 개의 이미지를 적용했을 경우 버튼이 이미지 크기로 변경
// 한다. (어차피 해당 사이즈를 이용하기 위해서 니깐)
//


#include "stdafx.h"
#include "GDIPLUS_TEST.h"
#include "ButtonEx.h"
#include "ParserXML.h"

// CButtonEx

IMPLEMENT_DYNAMIC(CButtonEx, CButton)

CButtonEx::CButtonEx()
: m_szFont(L"Tahoma")
, m_nFontSize(11)
, m_bLoadImage(false)
, m_pLoadImage(NULL)
, m_nPressMove(0)
, m_bMouseOver(false)
, m_nLeftMargin(0)
, m_nFontStyle(FontStyleRegular)
, m_bFullImage(false)
{
    // 가운데/중간 정렬
    gdiStringFormat.SetAlignment(StringAlignmentCenter);
    gdiStringFormat.SetLineAlignment(StringAlignmentCenter);

    // 폰트 색
    m_crFontColor = Color(0, 0, 0);    // 검정

    // 변수 초기화
    memset(m_nOneImage, 0, sizeof(m_nOneImage));
    memset(m_resize_rect, 0, sizeof(m_resize_rect));
}

CButtonEx::~CButtonEx()
{
    if (m_pLoadImage)
    {
        // 이미지를 추가했을 때만 지우자.
        if (m_nLeftMargin)
        {
            delete m_imgBtnIcon;
        }

        // 브러시/폰트 등등
        delete m_brFontColor;
        delete m_memBitmap;
        delete m_mDC;
        delete m_Font;
        delete m_Position;
    }
}


BEGIN_MESSAGE_MAP(CButtonEx, CButton)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_LBUTTONDBLCLK()
    ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

// CButtonEx message handlers


void CButtonEx::OnPaint()
{
    CPaintDC dc(this); // device context for painting

    if (m_pLoadImage)
    {
        InitObject();

        Graphics objG(dc);
        objG.DrawImage(m_memBitmap, 0, 0);    
    }
    else
    {
        // 이미지 객체에 링크가 없을 경우는 고냥
        // 버튼 위치만 보여주자.
        Graphics objG(dc);
        Pen penBlack(Color(0, 0, 0));
        Font fontBlack(m_szFont, m_nFontSize, m_nFontStyle, UnitPixel);
        SolidBrush brushBlack(Color(0, 0, 0));

        GetClientRect(&rect);
        GetWindowText(m_szWindowText);
        objG.DrawRectangle(&penBlack, 0, 0, rect.Width()-1, rect.Height()-1);
        PointF ptfPos(static_cast<REAL>(static_cast<float>(rect.Width()-1) / 2.0f),
            static_cast<REAL>(static_cast<float>(rect.Height()-1) / 2.0f));
        objG.DrawString(m_szWindowText, -1, &fontBlack, ptfPos, &gdiStringFormat, &brushBlack);
    }
}

BOOL CButtonEx::OnEraseBkgnd(CDC* pDC)
{
    return true;
}

void CButtonEx::SetFontStyle(CString szFont, REAL nFontSize, int nFontStyle)
{
    //FontStyleRegular    = 0,
    //FontStyleBold     = 1,
    //FontStyleItalic     = 2,
    //FontStyleBoldItalic = 3,
    //FontStyleUnderline = 4,
    //FontStyleStrikeout = 8

    m_szFont     = szFont;
    m_nFontSize = nFontSize;
    m_nFontStyle = nFontStyle;
}

void CButtonEx::InitObject(void)
{
    // 이미지를 불러 들이고
    if (!m_bLoadImage)
    {
        if (m_pLoadImage->m_szOneImage.GetLength() && m_resize_rect.Width())
        {
            // 통이미지 일경우 버튼의 크기를 이미지 사이즈로 맞춘다.
            m_nOneImage[0] = static_cast<int>(m_pLoadImage->m_imgFull[0]->GetWidth());
            m_nOneImage[1] = static_cast<int>(m_pLoadImage->m_imgFull[0]->GetHeight());

            MoveWindow(m_resize_rect.left, m_resize_rect.top, m_nOneImage[0], m_nOneImage[1]);
            //rect.SetRect(0, 0, m_nOneImage[0], m_nOneImage[1]);
            GetClientRect(&rect);
        }
        else
        {
            GetClientRect(&rect);
        }
        
        try
        {
            // 브러시
            m_brFontColor = new SolidBrush(m_crFontColor);

            //
            m_memBitmap = new Bitmap(rect.Width(), rect.Height());
            m_mDC        = new Graphics(m_memBitmap);
            m_Font        = new Font(m_szFont, m_nFontSize, m_nFontStyle, UnitPixel);
            m_Position    = new PointF(static_cast<REAL>(static_cast<float>(rect.Width()) / 2.0f),
                                     static_cast<REAL>(static_cast<float>(rect.Height()) / 2.0f));

            if (m_nLeftMargin)
            {
                gdiStringFormat.SetAlignment(StringAlignmentNear);
                (*m_Position).X = static_cast<REAL>(m_imgBtnIcon->GetWidth() + m_nLeftMargin + 20);
            }
        }
        catch (CMemoryException* e)
        {
            e->ReportError();
            e->Delete();
        }

        // 윈도우 텍스트 가져오기
        GetWindowText(m_szWindowText);

        // 버튼 그리기
        DrawButton(NORMAL_BUTTON);

        m_bLoadImage = true;
    }
}

void CButtonEx::CenterDraw(Image* pImg, int* pnLeftWidth, int* pnRightPos)
{
    int i;

    for (i=*pnLeftWidth; i<*pnRightPos; ++i)
    {
        m_mDC->DrawImage(pImg, i, 0, 1, rect.Height());    
    }
}

void CButtonEx::DrawButton(int nType)
{
    if (!m_pLoadImage->m_szOneImage.GetLength())
    {
        int nRightPos, nLeftWidth, nRightWidth;

        nRightPos = rect.Width() - static_cast<int>(m_pLoadImage->m_imgNormal[_RIGHT]->GetWidth());
        nLeftWidth = m_pLoadImage->m_imgNormal[_LEFT]->GetWidth();
        nRightWidth = m_pLoadImage->m_imgNormal[_RIGHT]->GetWidth();

        switch(nType)
        {
        case NORMAL_BUTTON:
            m_mDC->DrawImage(m_pLoadImage->m_imgNormal[_LEFT], 0, 0, nLeftWidth, rect.Height());
            m_mDC->DrawImage(m_pLoadImage->m_imgNormal[_RIGHT], nRightPos, 0, nRightWidth, rect.Height());
            CenterDraw(m_pLoadImage->m_imgNormal[_CENTER], &nLeftWidth, &nRightPos);
            break;

        case OVER_BUTTON:
            m_mDC->DrawImage(m_pLoadImage->m_imgOver[_LEFT], 0, 0, nLeftWidth, rect.Height());
            m_mDC->DrawImage(m_pLoadImage->m_imgOver[_RIGHT], nRightPos, 0, nRightWidth, rect.Height());
            CenterDraw(m_pLoadImage->m_imgOver[_CENTER], &nLeftWidth, &nRightPos);
            break;

        case ACTIVE_BUTTON:
            m_mDC->DrawImage(m_pLoadImage->m_imgActive[_LEFT], 0, 0, nLeftWidth, rect.Height());
            m_mDC->DrawImage(m_pLoadImage->m_imgActive[_RIGHT], nRightPos, 0, nRightWidth, rect.Height());
            CenterDraw(m_pLoadImage->m_imgActive[_CENTER], &nLeftWidth, &nRightPos);
            break;

        default:
            break;
        }
    }
    else
    {
        switch(nType)
        {
        case NORMAL_BUTTON:
            m_mDC->DrawImage(m_pLoadImage->m_imgFull[0], 0, 0, rect.Width(), rect.Height());
            break;

        case OVER_BUTTON:
            m_mDC->DrawImage(m_pLoadImage->m_imgFull[1], 0, 0, rect.Width(), rect.Height());
            break;

        case ACTIVE_BUTTON:
            m_mDC->DrawImage(m_pLoadImage->m_imgFull[2], 0, 0, rect.Width(), rect.Height());
            break;

        default:
            break;
        }
    }
    
    // 중간에 아이콘 넣을 경우
    if (m_nLeftMargin)
    {
        int nIconPos;
        nIconPos = static_cast<int>((rect.Height() / 2.0) - (m_imgBtnIcon->GetHeight() / 2.0) );

        if (m_nPressMove && nType == ACTIVE_BUTTON)
        {
            m_mDC->DrawImage(m_imgBtnIcon, m_nLeftMargin + static_cast<int>(m_nPressMove), nIconPos + static_cast<int>(m_nPressMove));
        }
        else
        {
            m_mDC->DrawImage(m_imgBtnIcon, m_nLeftMargin, nIconPos);
        }
    }

    // 버튼 문구 적어주시고 m_nPressMove 에 값이 존재하면
    // 그 만큼 이동 해주도록 하자.
    if (m_szWindowText.GetLength())
    {
        if (m_nPressMove && nType == ACTIVE_BUTTON)
        {
            PointF MovePosition((*m_Position).X + m_nPressMove, (*m_Position).Y + m_nPressMove);
            m_mDC->DrawString(m_szWindowText, -1, m_Font, MovePosition, &gdiStringFormat, m_brFontColor);
        }
        else
        {
            m_mDC->DrawString(m_szWindowText, -1, m_Font, *m_Position, &gdiStringFormat, m_brFontColor);
        }
    }
}

void CButtonEx::OnLButtonDown(UINT nFlags, CPoint point)
{
    if (m_pLoadImage)
    {
        m_bMouseOver = true;
        DrawButton(ACTIVE_BUTTON);    
        Invalidate();
    }
    
    CButton::OnLButtonDown(nFlags, point);
}

void CButtonEx::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (m_pLoadImage)
    {
        DrawButton(NORMAL_BUTTON);
        Invalidate();
    }

    CButton::OnLButtonUp(nFlags, point);

    if (m_pLoadImage)
    {
        ReleaseCapture();
        m_bMouseOver = false;
    }
}

void CButtonEx::SetActiveMoveText(REAL nDistance)
{
    m_nPressMove = nDistance;
}

void CButtonEx::OnLButtonDblClk(UINT nFlags, CPoint point)
{
    if (m_pLoadImage)
    {
        OnLButtonDown(nFlags, point);
    }

    CButton::OnLButtonDblClk(nFlags, point);
}

void CButtonEx::OnMouseMove(UINT nFlags, CPoint point)
{
    if (m_pLoadImage)
    {
        // 마우스가 버튼 위치를 떠났을 때
        if (rect.PtInRect(point) == false)
        {
            DrawButton(NORMAL_BUTTON);
            Invalidate();

            if (!m_bMouseOver)
            {
                ReleaseCapture();
            }
        }
        else
        {
            if (m_bMouseOver)
            {
                // 마우스는 클릭한 상태에서 버튼 위치일 경우
                DrawButton(ACTIVE_BUTTON);
                Invalidate();
            }
            else
            {
                // 마우스는 클릭하지 않은 상태 에서의 버튼 위치 일 경우    
                DrawButton(OVER_BUTTON);
                Invalidate();
                SetCapture();
            }
        }
    }

    CButton::OnMouseMove(nFlags, point);
}

void CButtonEx::ButtonIcon(CString szButtonIcon, int nLeftMargin)
{
    try
    {
        m_imgBtnIcon = new Image(szButtonIcon);
        m_nLeftMargin = nLeftMargin;
    }
    catch (CMemoryException* e)
    {
        e->ReportError();
        e->Delete();
    }
}

void CButtonEx::SetLoadImage(CButtonLoadImage* img)
{
    // CButtonLoadImage 에서 불러들인 이미지를 링크한다.
    m_pLoadImage = img;
}


void CButtonEx::Resize(CRect rect)
{
    m_resize_rect = rect;
}
[/code]

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

CHorbarText  (0) 2013.10.02
다이얼로그에 색을 가져오자 Dialog color (GetSysColor)  (0) 2013.10.02
CRectEx  (0) 2013.10.02
MFC TIP  (0) 2013.10.02
XML Parser  (0) 2013.10.02