• 로그인 함 해보끄나?

  • Sarangnamu.net June 17, 2003
    Home Login Profile Study Open Project Q&A Google Code
    CButtonEx (Version 1.5)
    Last Modify : 27 December, 2010(02:47)
    GDI+ 의 경우 GDI는 다르게 이미지를 사용하고 나서도 계속해서 유지된다. (GDI 의 경우는 내부적으로 삭제한다. 고로 재 한 오브젝트당 하나의 이미지객체를 사용할 수 있다.) 고로 미리 하나를 불러들인다음 계속해서 그 객체를 이용하면되므로 이전에 생성해둔 CImageLoader 와 연동한 CButtonEx 만들어 보았다.
    // ButtonEx.cpp : implementation file
    //
    
    // DATE		: February 13, 2007
    // CODER	: Kurome (aucd29@gmail.com)
    // VERSION	: 1.5
    //
    //
    
    // Require
    // ----------------------------------------------------------
    // GDI+
    // installation Guide : http://sarangnamu.net/basic/basic_view.php?no=1369
    // Manual(kor) : http://winapi.co.kr/project/library/gdiplus/gdiplus.htm
    //
    // CImageLoader
    // http://www.sarangnamu.net/basic/basic_view.php?no=2839
    //
    
    // ----------------------------------------------------------
    // NOTE : February 13, 2007
    // ----------------------------------------------------------
    // * 디자인 회의 하다가 버튼 클래스가지고 -_ - 디자이너가
    //   스크립트를 논하며 머라 하길래 -_- 버튼 클래스 만든다. 
    //   성격있는 최씨 -_ -ㅎ삐뚤어져 주겠어
    //
    // ----------------------------------------------------------
    // NOTE : February 21, 2007
    // ----------------------------------------------------------
    // * GDI+ 의 단점인 느린 로딩 -_ - 을 해결하기 위해서
    //   CButtonLoadImage를 생성.. 조금 나아지긴 했다. 아직 느린
    //   게 보이긴 하는데 -_ -;;;;;
    // 
    // * 머랄까 음... 로딩된 이미지를 Distructor에서 Free를 해
    //   주려고 했는데 오류가 난다. 왜 그런 것일까??? 우선은 주
    //   석질을 했다.
    //
    // * 한 개의 이미지를 적용했을 경우 버튼이 이미지 크기로 변경
    //   한다. (어차피 해당 사이즈를 이용하기 위해서 니깐)
    //
    // ----------------------------------------------------------
    // BUGFIX : March 13, 2007
    // ----------------------------------------------------------
    // * 이미지는 할당을 하였으나 해당 폼을 불러들이지 않았을
    //   경우 클래스에서 브러시 등에 대한 것을 생성을 시키지 않
    //   았는데 디스트럭트에서 삭제를 하려고 하는 현상을 수정
    //
    //   해결 방법 
    //   m_bCallPaint 변수 추가
    //
    
    
    #include "stdafx.h"
    #include "ButtonEx.h"
    
    // CButtonEx
    
    IMPLEMENT_DYNAMIC(CButtonEx, CButton)
    
    CButtonEx::CButtonEx()
    : m_szFont(L"Tahoma")
    , m_nFontSize(11)
    , m_bLoadImage(false)
    , m_nPressMove(0)
    , m_bMouseOver(false)
    , m_nLeftMargin(0)
    , m_nFontStyle(FontStyleRegular)
    , m_bFullImage(false)
    , m_bOneImage(false)
    , m_bCallPaint(false)
    {
    	m_pLoadImage[_NORMAL_BUTTON] = NULL;
    	m_pLoadImage[_OVER_BUTTON]	 = NULL;
    	m_pLoadImage[_ACTIVE_BUTTON] = NULL;
    
    	// 가운데/중간 정렬
    	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[_NORMAL_BUTTON] && m_bCallPaint)
    	{
    		// 이미지를 추가했을 때만 지우자.
    		if (m_nLeftMargin)
    		{
    			TRACE(L"LEFT MARGINE");
    			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[_NORMAL_BUTTON])
    	{
    		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)
    {
    	// Paint에 들어온 흔적을 남기자.
    	m_bCallPaint = true;
    
    	// 이미지를 불러 들이고
    	if (!m_bLoadImage)
    	{
    		if (m_bOneImage && m_resize_rect.Width())
    		{
    			// 통이미지 일경우 버튼의 크기를 이미지 사이즈로 맞춘다.
    			m_nOneImage[0] = static_cast<int>(m_pLoadImage[_NORMAL_BUTTON]->m_pImg[0]->GetWidth());
    			m_nOneImage[1] = static_cast<int>(m_pLoadImage[_NORMAL_BUTTON]->m_pImg[0]->GetHeight());
    
    			MoveWindow(m_resize_rect.left, m_resize_rect.top, m_nOneImage[0], m_nOneImage[1]);
    			GetClientRect(&rect);
    		}
    		else
    		{
    			GetClientRect(&rect);
    		}
    		
    		try
    		{
    			// 브러시
    			TRACE(L"CREATE FONT\n");
    			m_brFontColor = new SolidBrush(m_crFontColor);
    
    			//
    			TRACE(L"CREATE BITMAP\n");
    			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[_ACTIVE_BUTTON])
    	{
    		int nRightPos, nLeftWidth, nRightWidth;
    
    		nRightPos   = rect.Width() - static_cast<int>(m_pLoadImage[_NORMAL_BUTTON]->m_pImg[2]->GetWidth());
    		nLeftWidth  = m_pLoadImage[_NORMAL_BUTTON]->m_pImg[0]->GetWidth();
    		nRightWidth = m_pLoadImage[_NORMAL_BUTTON]->m_pImg[2]->GetWidth();
    		
    		m_mDC->DrawImage(m_pLoadImage[nType]->m_pImg[0], 0, 0, nLeftWidth, rect.Height());
    		m_mDC->DrawImage(m_pLoadImage[nType]->m_pImg[2], nRightPos, 0, nRightWidth, rect.Height());
    		CenterDraw(m_pLoadImage[nType]->m_pImg[1], &nLeftWidth, &nRightPos);
    	}
    	else
    	{
    		m_mDC->DrawImage(m_pLoadImage[_NORMAL_BUTTON]->m_pImg[0], 0, 0, rect.Width(), rect.Height());
    	}
    	
    	// 중간에 아이콘 넣을 경우
    	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[_NORMAL_BUTTON])
    	{
    		m_bMouseOver = true;
    		DrawButton(_ACTIVE_BUTTON);	
    		Invalidate();
    	}
    	
    	CButton::OnLButtonDown(nFlags, point);
    }
    
    void CButtonEx::OnLButtonUp(UINT nFlags, CPoint point)
    {
    	if (m_pLoadImage[_NORMAL_BUTTON])
    	{
    		DrawButton(_NORMAL_BUTTON);
    		Invalidate();
    	}
    
    	CButton::OnLButtonUp(nFlags, point);
    
    	if (m_pLoadImage[_NORMAL_BUTTON])
    	{
    		ReleaseCapture();
    		m_bMouseOver = false;
    	}
    }
    
    void CButtonEx::SetActiveMoveText(REAL nDistance)
    {
    	m_nPressMove = nDistance;
    }
    
    void CButtonEx::OnLButtonDblClk(UINT nFlags, CPoint point)
    {
    	if (m_pLoadImage[_NORMAL_BUTTON])
    	{
    		OnLButtonDown(nFlags, point);
    	}
    
    	CButton::OnLButtonDblClk(nFlags, point);
    }
    
    void CButtonEx::OnMouseMove(UINT nFlags, CPoint point)
    {
    	if (m_pLoadImage[_NORMAL_BUTTON])
    	{
    		// 마우스가 버튼 위치를 떠났을 때
    		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(CImageData* pImgNormal,
    							 CImageData* pImgOver,
    							 CImageData* pImgActive)
    {
    	m_pLoadImage[_NORMAL_BUTTON] = pImgNormal;
    	m_pLoadImage[_OVER_BUTTON]   = pImgOver;
    	m_pLoadImage[_ACTIVE_BUTTON] = pImgActive;
    }
    
    void CButtonEx::Resize(CRect rect)
    {
    	m_resize_rect = rect;
    }
    
    void CButtonEx::SetLoadImage(CImageData* pImage)
    {
    	m_bOneImage = true;
    	m_pLoadImage[_NORMAL_BUTTON] = pImage;
    }
    
    #pragma once
    
    #include "ImageLoader.h"
    
    // CButtonEx
    
    enum DrawButtonType
    {
    	_NORMAL_BUTTON = 0,
    	_OVER_BUTTON,
    	_ACTIVE_BUTTON
    };
    
    class CButtonEx : public CButton
    {
    	DECLARE_DYNAMIC(CButtonEx)
    
    public:
    	CButtonEx();
    	virtual ~CButtonEx();
    private:
    	void CenterDraw(Image* pImg, int* pnLeftWidth, int* pnRightPos);
    
    protected:
    	int m_nFontStyle, m_nLeftMargin;
    	int m_nOneImage[2];
    	Font* m_Font;
    	REAL m_nFontSize, m_nPressMove;
    	bool m_bLoadImage, m_bMouseOver, m_bFullImage;
    	bool m_bOneImage, m_bCallPaint;
    	Image* m_imgBtnIcon;
    	CRect rect, m_resize_rect;
    	Color m_crFontColor;
    	Bitmap* m_memBitmap;
    	PointF* m_Position;
    	CString m_szFont, m_szWindowText;
    	Graphics* m_mDC;
    	SolidBrush* m_brFontColor;
    	CImageData* m_pLoadImage[3];
    	StringFormat gdiStringFormat;
    	
    	afx_msg void OnPaint();
    	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    
    	DECLARE_MESSAGE_MAP()
    public:
    	void SetFontStyle(CString szFont, REAL nFontSize, int nFontStyle = FontStyleRegular);	
    	void InitObject(void);
    	void DrawButton(int nType);
    	void SetActiveMoveText(REAL nDistance);
    	void ButtonIcon(CString szButtonIcon, int nLeftMargin = 10);
    	void SetLoadImage(CImageData* pImgNormal,
    					  CImageData* pImgOver,
    					  CImageData* pImgActive);
    	void Resize(CRect rect);
    	void SetLoadImage(CImageData* pImage);
    };
    

    Comment


    입력하3 1508231992



    Locations of visitors to this page