MFC 之 CButton 控件重绘(GDI篇)



http://blog.csdn.net/yuzhenxiong0823/article/details/23278763


最近在为公司用MFC做产品界面。因为是小公司,所以也没有现成的界面库,必须自己一点一点写。自己在网上收集了点资料,就写了几个类型的button类,以供以后使用。

目前为止,做了三种类型的按钮,分别是:

1.一般情况使用的,比较常用的button类CNormalBtn;

2.特殊一点的,类似拥有菜单功能的button类CMenuBtn(和CNormal的区别是按钮selected后的状态不会随着鼠标的离开而消失);

3.静态按钮,用来呈现log等图片之类的button类CStatic,该类不会响应鼠标事件。

对于1,2种按钮,用的图片模式是:(png格式,一幅图里有四副小图,依次表示NoFoucs,Mousemove, buttondown, Disable四种状态);

对于3类按钮,用的图片模式是:(png格式)


下面贴代码:

扫描二维码关注公众号,回复: 1922278 查看本文章

基类代码(BaseBtn.h)

  1. #ifndef __BASEBTN_H__  
  2. #define __BASEBTN_H__  
  3.   
  4. #include "stdafx.h"  
  5. #include <atlimage.h>  
  6.   
  7. #if _MSC_VER > 1000  
  8. #pragma once  
  9. #endif  
  10.   
  11. class CBaseBtn : public CButton  
  12. {  
  13. public:  
  14.     CBaseBtn();  
  15.     ~CBaseBtn();  
  16.   
  17. public:  
  18.     virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);  
  19.     virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);  
  20.     virtual void SetFont(CFont* pFont, BOOL bRedraw = TRUE);  
  21.     virtual void SetWindowText(LPCTSTR lpszString);  
  22.       
  23. public:  
  24.     void Init(UINT uImageID);  
  25.     void SetBtnTextColor(COLORREF clr);  
  26.           
  27. protected:  
  28.     afx_msg BOOL OnEraseBkgnd(CDC* pDC);  
  29.   
  30.     DECLARE_MESSAGE_MAP()  
  31.   
  32. protected:  
  33.     int         m_nCtrlState;  
  34.   
  35.     CImage      m_Image;  
  36.     int         m_nSrcWidth;  
  37.     int         m_nSrcHeight;  
  38.   
  39. private:  
  40.     CString     m_strBtnText;  
  41.     CFont*      m_pFont;  
  42.     COLORREF    m_clr;  
  43. };  
  44.   
  45. #endif  
#ifndef __BASEBTN_H__
#define __BASEBTN_H__

#include "stdafx.h"
#include <atlimage.h>

#if _MSC_VER > 1000
#pragma once
#endif

class CBaseBtn : public CButton
{
public:
	CBaseBtn();
	~CBaseBtn();

public:
	virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
	virtual void SetFont(CFont* pFont, BOOL bRedraw = TRUE);
	virtual void SetWindowText(LPCTSTR lpszString);
	
public:
	void Init(UINT uImageID);
	void SetBtnTextColor(COLORREF clr);
		
protected:
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);

	DECLARE_MESSAGE_MAP()

protected:
	int			m_nCtrlState;

	CImage		m_Image;
	int			m_nSrcWidth;
	int			m_nSrcHeight;

private:
	CString		m_strBtnText;
	CFont*		m_pFont;
	COLORREF	m_clr;
};

#endif


基类代码(BaseBtn.cpp)

  1. #include "stdafx.h"  
  2. #include "BaseBtn.h"  
  3. #include "Public.h"  
  4.   
  5. #ifdef _DEBUG  
  6. #define new DEBUG_NEW  
  7. #undef THIS_FILE  
  8. static char THIS_FILE[] = __FILE__;  
  9. #endif  
  10.   
  11. CBaseBtn::CBaseBtn()  
  12. {  
  13.     m_pFont = new CFont;  
  14.     VERIFY(m_pFont->CreateFont(15, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,   
  15.         CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Tahoma")));  
  16.   
  17.     m_strBtnText = L"";  
  18.     m_clr = RGB(0, 0, 0);  
  19. }  
  20.   
  21. CBaseBtn::~CBaseBtn()  
  22. {  
  23.     if (!m_Image.IsNull())  
  24.         m_Image.Destroy();  
  25.   
  26.     if (m_pFont != NULL)  
  27.     {  
  28.         m_pFont->DeleteObject();  
  29.   
  30.         delete m_pFont;  
  31.         m_pFont = NULL;  
  32.     }  
  33. }  
  34.   
  35. BEGIN_MESSAGE_MAP(CBaseBtn, CButton)  
  36.     ON_WM_ERASEBKGND()  
  37. END_MESSAGE_MAP()  
  38.   
  39. void CBaseBtn::Init(UINT uImageID)  
  40. {  
  41.     SetButtonStyle(BS_OWNERDRAW);  
  42.   
  43.     LoadPicture(m_Image, uImageID);  
  44.     m_nSrcWidth = m_Image.GetWidth();  
  45.     m_nSrcHeight = m_Image.GetHeight();  
  46.   
  47.     SetWindowPos(NULL, 0, 0, m_nSrcWidth/4, m_nSrcHeight, SWP_NOMOVE|SWP_NOACTIVATE);  
  48.   
  49.     if (IsWindowEnabled())  
  50.         m_nCtrlState = CTRL_NOFOCUS;  
  51.     else  
  52.         m_nCtrlState = CTRL_DISABLE;  
  53. }  
  54.   
  55. void CBaseBtn::SetFont(CFont* pFont, BOOL bRedraw)  
  56. {  
  57.     m_pFont = pFont;  
  58.   
  59.     if(bRedraw)  
  60.         Invalidate();  
  61. }  
  62.   
  63. void CBaseBtn::SetWindowText(LPCTSTR lpszString)  
  64. {  
  65.     m_strBtnText = lpszString;  
  66.     Invalidate();  
  67. }  
  68.   
  69. void CBaseBtn::SetBtnTextColor(COLORREF clr)  
  70. {  
  71.     m_clr = clr;  
  72.     Invalidate();  
  73. }  
  74.   
  75. BOOL CBaseBtn::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)   
  76. {  
  77.     return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);  
  78. }  
  79.   
  80. void CBaseBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)   
  81. {  
  82.     if (m_Image.IsNull())  
  83.         return ;  
  84.   
  85.     CRect buttonRect;  
  86.     GetClientRect(buttonRect);  
  87.   
  88.     CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);       //按钮控件DC  
  89.   
  90.     CDC dcMem;  
  91.     dcMem.CreateCompatibleDC(pDC);  
  92.   
  93.     CBitmap memBitmap;  
  94.     memBitmap.CreateCompatibleBitmap(pDC, buttonRect.Width(), buttonRect.Height());  
  95.     dcMem.SelectObject(memBitmap);  
  96.   
  97.     dcMem.FillSolidRect(buttonRect, RGB(255,0,255));    //设置画布颜色  
  98.   
  99.     CRect rcSrc = CRect(0,0,0,0);  
  100.     switch(m_nCtrlState)  
  101.     {  
  102.     case CTRL_NOFOCUS:  
  103.         {  
  104.             rcSrc = CRect(0, 0, m_nSrcWidth/4, m_nSrcHeight);         
  105.         }  
  106.         break;  
  107.   
  108.     case CTRL_FOCUS:  
  109.         {  
  110.             rcSrc = CRect(m_nSrcWidth/4, 0, m_nSrcWidth/4 * 2, m_nSrcHeight);  
  111.         }  
  112.         break;  
  113.     case CTRL_SELECTED:  
  114.         {  
  115.             rcSrc = CRect(m_nSrcWidth/4 * 2, 0, m_nSrcWidth/4 * 3, m_nSrcHeight);  
  116.         }  
  117.         break;  
  118.   
  119.     case CTRL_DISABLE:  
  120.         {  
  121.             rcSrc = CRect(m_nSrcWidth/4 * 3, 0, m_nSrcWidth, m_nSrcHeight);  
  122.         }  
  123.         break;  
  124.   
  125.     default:  
  126.         break;  
  127.     }  
  128.     m_Image.Draw(dcMem.m_hDC, buttonRect, rcSrc);  
  129.   
  130.     dcMem.SetBkMode(TRANSPARENT);  
  131.     dcMem.SetTextColor(m_clr);  
  132.     CFont* pOldFont = dcMem.SelectObject(m_pFont);  
  133.     DrawText(dcMem.m_hDC, m_strBtnText, -1, buttonRect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);  
  134.     dcMem.SelectObject(pOldFont);  
  135.   
  136.     pDC->BitBlt(0, 0, buttonRect.Width(), buttonRect.Height(), &dcMem, 0, 0, SRCCOPY);  
  137.     memBitmap.DeleteObject();  
  138. }  
  139.   
  140. BOOL CBaseBtn::OnEraseBkgnd(CDC* pDC)  
  141. {  
  142.     return TRUE;  
  143. }  
#include "stdafx.h"
#include "BaseBtn.h"
#include "Public.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CBaseBtn::CBaseBtn()
{
	m_pFont = new CFont;
	VERIFY(m_pFont->CreateFont(15, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Tahoma")));

	m_strBtnText = L"";
	m_clr = RGB(0, 0, 0);
}

CBaseBtn::~CBaseBtn()
{
	if (!m_Image.IsNull())
		m_Image.Destroy();

	if (m_pFont != NULL)
	{
		m_pFont->DeleteObject();

		delete m_pFont;
		m_pFont = NULL;
	}
}

BEGIN_MESSAGE_MAP(CBaseBtn, CButton)
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

void CBaseBtn::Init(UINT uImageID)
{
	SetButtonStyle(BS_OWNERDRAW);

	LoadPicture(m_Image, uImageID);
	m_nSrcWidth = m_Image.GetWidth();
	m_nSrcHeight = m_Image.GetHeight();

	SetWindowPos(NULL, 0, 0, m_nSrcWidth/4, m_nSrcHeight, SWP_NOMOVE|SWP_NOACTIVATE);

	if (IsWindowEnabled())
		m_nCtrlState = CTRL_NOFOCUS;
	else
		m_nCtrlState = CTRL_DISABLE;
}

void CBaseBtn::SetFont(CFont* pFont, BOOL bRedraw)
{
	m_pFont = pFont;

	if(bRedraw)
		Invalidate();
}

void CBaseBtn::SetWindowText(LPCTSTR lpszString)
{
	m_strBtnText = lpszString;
	Invalidate();
}

void CBaseBtn::SetBtnTextColor(COLORREF clr)
{
	m_clr = clr;
	Invalidate();
}

BOOL CBaseBtn::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}

void CBaseBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	if (m_Image.IsNull())
		return ;

	CRect buttonRect;
	GetClientRect(buttonRect);

	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);		//按钮控件DC

	CDC dcMem;
	dcMem.CreateCompatibleDC(pDC);

	CBitmap memBitmap;
	memBitmap.CreateCompatibleBitmap(pDC, buttonRect.Width(), buttonRect.Height());
	dcMem.SelectObject(memBitmap);

	dcMem.FillSolidRect(buttonRect, RGB(255,0,255));	//设置画布颜色

	CRect rcSrc = CRect(0,0,0,0);
	switch(m_nCtrlState)
	{
	case CTRL_NOFOCUS:
		{
			rcSrc = CRect(0, 0, m_nSrcWidth/4, m_nSrcHeight);		
		}
		break;

	case CTRL_FOCUS:
		{
			rcSrc = CRect(m_nSrcWidth/4, 0, m_nSrcWidth/4 * 2, m_nSrcHeight);
		}
		break;
	case CTRL_SELECTED:
		{
			rcSrc = CRect(m_nSrcWidth/4 * 2, 0, m_nSrcWidth/4 * 3, m_nSrcHeight);
		}
		break;

	case CTRL_DISABLE:
		{
			rcSrc = CRect(m_nSrcWidth/4 * 3, 0, m_nSrcWidth, m_nSrcHeight);
		}
		break;

	default:
		break;
	}
	m_Image.Draw(dcMem.m_hDC, buttonRect, rcSrc);

	dcMem.SetBkMode(TRANSPARENT);
	dcMem.SetTextColor(m_clr);
	CFont* pOldFont = dcMem.SelectObject(m_pFont);
	DrawText(dcMem.m_hDC, m_strBtnText, -1, buttonRect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
	dcMem.SelectObject(pOldFont);

	pDC->BitBlt(0, 0, buttonRect.Width(), buttonRect.Height(), &dcMem, 0, 0, SRCCOPY);
	memBitmap.DeleteObject();
}

BOOL CBaseBtn::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}


第一类button(NormalBtn.h)

  1. #ifndef __NORMALBTN_H__  
  2. #define __NORMALBTN_H__  
  3.   
  4. #include "BaseBtn.h"  
  5.   
  6. class CNormalBtn : public CBaseBtn  
  7. {  
  8. public:  
  9.     CNormalBtn();  
  10.     ~CNormalBtn();  
  11.   
  12. protected:  
  13.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  14.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
  15.     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
  16.     afx_msg LRESULT OnMouseLeave(WPARAMLPARAM);         
  17.     afx_msg LRESULT OnMouseHover(WPARAMLPARAM);  
  18.   
  19.     DECLARE_MESSAGE_MAP()  
  20.   
  21. private:  
  22.     BOOL   m_bTracking;                     // 捕获设置标记  
  23.       
  24. };  
  25.   
  26. #endif  
#ifndef __NORMALBTN_H__
#define __NORMALBTN_H__

#include "BaseBtn.h"

class CNormalBtn : public CBaseBtn
{
public:
	CNormalBtn();
	~CNormalBtn();

protected:
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg LRESULT OnMouseLeave(WPARAM, LPARAM);       
	afx_msg LRESULT OnMouseHover(WPARAM, LPARAM);

	DECLARE_MESSAGE_MAP()

private:
	BOOL   m_bTracking;						// 捕获设置标记
	
};

#endif


第一类button(NormalBtn. cpp)

  1. #include "stdafx.h"  
  2. #include "NormalBtn.h"  
  3. #include "Public.h"  
  4.   
  5. #ifdef _DEBUG  
  6. #define new DEBUG_NEW  
  7. #undef THIS_FILE  
  8. static char THIS_FILE[] = __FILE__;  
  9. #endif  
  10.   
  11. CNormalBtn::CNormalBtn()  
  12.     :m_bTracking(FALSE)  
  13. {  
  14.   
  15. }  
  16.   
  17. CNormalBtn::~CNormalBtn()  
  18. {  
  19.   
  20. }  
  21.   
  22. BEGIN_MESSAGE_MAP(CNormalBtn, CBaseBtn)  
  23.     ON_WM_MOUSEMOVE()  
  24.     ON_WM_LBUTTONDOWN()  
  25.     ON_WM_LBUTTONUP()  
  26.     ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)         
  27.     ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)  
  28. END_MESSAGE_MAP()  
  29.   
  30. void CNormalBtn::OnMouseMove(UINT nFlags, CPoint point)   
  31. {  
  32.     if (!m_bTracking)    
  33.     {     
  34.         TRACKMOUSEEVENT tme;    
  35.         tme.cbSize = sizeof(tme);    
  36.         tme.hwndTrack = m_hWnd;    
  37.         tme.dwFlags = TME_LEAVE|TME_HOVER;    
  38.         tme.dwHoverTime = 1;    
  39.         m_bTracking = _TrackMouseEvent(&tme);    
  40.     }    
  41.   
  42.     CBaseBtn::OnMouseMove(nFlags, point);  
  43. }  
  44. LRESULT CNormalBtn::OnMouseHover(WPARAM wParam,LPARAM lParam)  
  45. {  
  46.     if (m_nCtrlState == CTRL_NOFOCUS)  
  47.     {  
  48.         m_nCtrlState = CTRL_FOCUS;  
  49.         Invalidate();  
  50.     }  
  51.   
  52.     m_bTracking = FALSE;  
  53.     return 0;  
  54. }  
  55.   
  56. LRESULT CNormalBtn::OnMouseLeave(WPARAM wParam,LPARAM   lParam)         
  57. {     
  58.     if(m_nCtrlState != CTRL_NOFOCUS)  
  59.     {  
  60.         m_nCtrlState = CTRL_NOFOCUS;  
  61.         Invalidate();  
  62.     }  
  63.   
  64.     m_bTracking = FALSE;   
  65.     return 0;         
  66. }         
  67.   
  68. void CNormalBtn::OnLButtonDown(UINT nFlags, CPoint point)   
  69. {  
  70.     if(m_nCtrlState == CTRL_FOCUS)  
  71.     {  
  72.         m_nCtrlState = CTRL_SELECTED;  
  73.         Invalidate();  
  74.     }  
  75.   
  76.     CBaseBtn::OnLButtonDown(nFlags, point);  
  77. }  
  78.   
  79. void CNormalBtn::OnLButtonUp(UINT nFlags, CPoint point)  
  80. {  
  81.     if(m_nCtrlState == CTRL_SELECTED)  
  82.     {  
  83.         m_nCtrlState = CTRL_FOCUS;  
  84.         Invalidate();  
  85.     }  
  86.     CBaseBtn::OnLButtonUp(nFlags, point);  
  87. }  
#include "stdafx.h"
#include "NormalBtn.h"
#include "Public.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CNormalBtn::CNormalBtn()
	:m_bTracking(FALSE)
{

}

CNormalBtn::~CNormalBtn()
{

}

BEGIN_MESSAGE_MAP(CNormalBtn, CBaseBtn)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)       
	ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)
END_MESSAGE_MAP()

void CNormalBtn::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (!m_bTracking)  
	{   
		TRACKMOUSEEVENT tme;  
		tme.cbSize = sizeof(tme);  
		tme.hwndTrack = m_hWnd;  
		tme.dwFlags = TME_LEAVE|TME_HOVER;  
		tme.dwHoverTime = 1;  
		m_bTracking = _TrackMouseEvent(&tme);  
	}  

	CBaseBtn::OnMouseMove(nFlags, point);
}
LRESULT CNormalBtn::OnMouseHover(WPARAM wParam,LPARAM lParam)
{
	if (m_nCtrlState == CTRL_NOFOCUS)
	{
		m_nCtrlState = CTRL_FOCUS;
		Invalidate();
	}

	m_bTracking = FALSE;
	return 0;
}

LRESULT CNormalBtn::OnMouseLeave(WPARAM wParam,LPARAM   lParam)       
{   
	if(m_nCtrlState != CTRL_NOFOCUS)
	{
		m_nCtrlState = CTRL_NOFOCUS;
		Invalidate();
	}

	m_bTracking = FALSE; 
	return 0;       
}       

void CNormalBtn::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if(m_nCtrlState == CTRL_FOCUS)
	{
		m_nCtrlState = CTRL_SELECTED;
		Invalidate();
	}

	CBaseBtn::OnLButtonDown(nFlags, point);
}

void CNormalBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(m_nCtrlState == CTRL_SELECTED)
	{
		m_nCtrlState = CTRL_FOCUS;
		Invalidate();
	}
	CBaseBtn::OnLButtonUp(nFlags, point);
}


第二类按钮(CMenu.h)

  1. #ifndef __MENUBTN_H__  
  2. #define __MENUBTN_H__  
  3.   
  4. #include "BaseBtn.h"  
  5.   
  6. class CMenuBtn : public CBaseBtn  
  7. {  
  8. public:  
  9.     CMenuBtn();  
  10.     ~CMenuBtn();  
  11.   
  12. public:  
  13.     BOOL GetMenuOn()    { return m_bMenuOn; }  
  14.     void SetMenuOn(BOOL bMenuOn);  
  15.   
  16. protected:  
  17.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  18.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
  19.     afx_msg LRESULT OnMouseLeave(WPARAMLPARAM);         
  20.     afx_msg LRESULT OnMouseHover(WPARAMLPARAM);  
  21.   
  22.     DECLARE_MESSAGE_MAP()  
  23.   
  24. private:  
  25.     BOOL   m_bTracking;                     // 捕获设置标记  
  26.     BOOL   m_bMenuOn;                       // 该菜单按钮是否被选中  
  27.   
  28. };  
  29.   
  30. #endif  
#ifndef __MENUBTN_H__
#define __MENUBTN_H__

#include "BaseBtn.h"

class CMenuBtn : public CBaseBtn
{
public:
	CMenuBtn();
	~CMenuBtn();

public:
	BOOL GetMenuOn()	{ return m_bMenuOn;	}
	void SetMenuOn(BOOL bMenuOn);

protected:
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg LRESULT OnMouseLeave(WPARAM, LPARAM);       
	afx_msg LRESULT OnMouseHover(WPARAM, LPARAM);

	DECLARE_MESSAGE_MAP()

private:
	BOOL   m_bTracking;						// 捕获设置标记
	BOOL   m_bMenuOn;						// 该菜单按钮是否被选中

};

#endif


第二类按钮(CButton.cpp)

  1. #include "stdafx.h"  
  2. #include "MenuBtn.h"  
  3. #include "Public.h"  
  4.   
  5. #ifdef _DEBUG  
  6. #define new DEBUG_NEW  
  7. #undef THIS_FILE  
  8. static char THIS_FILE[] = __FILE__;  
  9. #endif  
  10.   
  11. CMenuBtn::CMenuBtn()  
  12. :m_bTracking(FALSE)  
  13. ,m_bMenuOn(FALSE)  
  14. {  
  15.   
  16. }  
  17.   
  18. CMenuBtn::~CMenuBtn()  
  19. {  
  20.   
  21. }  
  22.   
  23. BEGIN_MESSAGE_MAP(CMenuBtn, CBaseBtn)  
  24.     ON_WM_MOUSEMOVE()  
  25.     ON_WM_LBUTTONDOWN()  
  26.     ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)         
  27.     ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)  
  28. END_MESSAGE_MAP()  
  29.   
  30. void CMenuBtn::OnMouseMove(UINT nFlags, CPoint point)   
  31. {         
  32.     if (!m_bTracking)    
  33.     {     
  34.         TRACKMOUSEEVENT tme;    
  35.         tme.cbSize = sizeof(tme);    
  36.         tme.hwndTrack = m_hWnd;    
  37.         tme.dwFlags = TME_LEAVE|TME_HOVER;    
  38.         tme.dwHoverTime = 1;    
  39.         m_bTracking = _TrackMouseEvent(&tme);    
  40.     }    
  41.   
  42.     CButton::OnMouseMove(nFlags, point);  
  43. }  
  44.   
  45. void CMenuBtn::OnLButtonDown(UINT nFlags, CPoint point)   
  46. {  
  47.     if(m_nCtrlState != CTRL_SELECTED)  
  48.     {  
  49.         m_nCtrlState = CTRL_SELECTED;  
  50.         m_bMenuOn = TRUE;  
  51.         Invalidate();  
  52.     }  
  53.   
  54.     CButton::OnLButtonDown(nFlags, point);  
  55. }  
  56.   
  57. LRESULT CMenuBtn::OnMouseLeave(WPARAM     wParam,LPARAM   lParam)         
  58. {     
  59.     if(m_bMenuOn)  
  60.     {  
  61.         m_nCtrlState = CTRL_SELECTED;  
  62.         Invalidate();  
  63.     }  
  64.     else  
  65.     {  
  66.         m_nCtrlState = CTRL_NOFOCUS;  
  67.         Invalidate();  
  68.     }  
  69.   
  70.     m_bTracking = FALSE;   
  71.     return 0;         
  72. }         
  73.   
  74. LRESULT CMenuBtn::OnMouseHover(WPARAM wParam,LPARAM lParam)  
  75. {  
  76.     if (m_nCtrlState != CTRL_FOCUS)  
  77.     {  
  78.         m_nCtrlState = CTRL_FOCUS;  
  79.         Invalidate();  
  80.     }  
  81.   
  82.     m_bTracking = FALSE;  
  83.     return 0;  
  84. }  
  85.   
  86. void CMenuBtn::SetMenuOn(BOOL bMenuOn)  
  87. {  
  88.     m_bMenuOn = bMenuOn;  
  89.     Invalidate();  
  90. }  
#include "stdafx.h"
#include "MenuBtn.h"
#include "Public.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CMenuBtn::CMenuBtn()
:m_bTracking(FALSE)
,m_bMenuOn(FALSE)
{

}

CMenuBtn::~CMenuBtn()
{

}

BEGIN_MESSAGE_MAP(CMenuBtn, CBaseBtn)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)       
	ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)
END_MESSAGE_MAP()

void CMenuBtn::OnMouseMove(UINT nFlags, CPoint point) 
{		
	if (!m_bTracking)  
	{   
		TRACKMOUSEEVENT tme;  
		tme.cbSize = sizeof(tme);  
		tme.hwndTrack = m_hWnd;  
		tme.dwFlags = TME_LEAVE|TME_HOVER;  
		tme.dwHoverTime = 1;  
		m_bTracking = _TrackMouseEvent(&tme);  
	}  

	CButton::OnMouseMove(nFlags, point);
}

void CMenuBtn::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if(m_nCtrlState != CTRL_SELECTED)
	{
		m_nCtrlState = CTRL_SELECTED;
		m_bMenuOn = TRUE;
		Invalidate();
	}

	CButton::OnLButtonDown(nFlags, point);
}

LRESULT CMenuBtn::OnMouseLeave(WPARAM     wParam,LPARAM   lParam)       
{   
	if(m_bMenuOn)
	{
		m_nCtrlState = CTRL_SELECTED;
		Invalidate();
	}
	else
	{
		m_nCtrlState = CTRL_NOFOCUS;
		Invalidate();
	}

	m_bTracking = FALSE; 
	return 0;       
}       

LRESULT CMenuBtn::OnMouseHover(WPARAM wParam,LPARAM lParam)
{
	if (m_nCtrlState != CTRL_FOCUS)
	{
		m_nCtrlState = CTRL_FOCUS;
		Invalidate();
	}

	m_bTracking = FALSE;
	return 0;
}

void CMenuBtn::SetMenuOn(BOOL bMenuOn)
{
	m_bMenuOn = bMenuOn;
	Invalidate();
}


第三类按钮(CStaticBtn.h)

  1. #ifndef __STATICBTN_H__  
  2. #define __STATICBTN_H__  
  3.   
  4. #include "BaseBtn.h"  
  5.   
  6. class CStaticBtn : public CBaseBtn  
  7. {  
  8. public:  
  9.     CStaticBtn();  
  10.     ~CStaticBtn();  
  11.   
  12. public:  
  13.     virtual void Init(UINT uImageID);  
  14.     virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);  
  15. };  
  16.   
  17.   
  18. #endif  
#ifndef __STATICBTN_H__
#define __STATICBTN_H__

#include "BaseBtn.h"

class CStaticBtn : public CBaseBtn
{
public:
	CStaticBtn();
	~CStaticBtn();

public:
	virtual void Init(UINT uImageID);
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};


#endif


第三类按钮(CStaticBtn.cpp)

  1. #include "stdafx.h"  
  2. #include "StaticBtn.h"  
  3. #include "Public.h"  
  4.   
  5. CStaticBtn::CStaticBtn()  
  6. {  
  7.   
  8. }  
  9.   
  10. CStaticBtn::~CStaticBtn()  
  11. {  
  12.   
  13. }  
  14.   
  15. void CStaticBtn::Init(UINT uImageID)  
  16. {  
  17.     SetButtonStyle(BS_OWNERDRAW);  
  18.   
  19.     LoadPicture(m_Image, uImageID);  
  20.     m_nSrcWidth = m_Image.GetWidth();  
  21.     m_nSrcHeight = m_Image.GetHeight();  
  22.   
  23.     SetWindowPos(NULL, 0, 0, m_nSrcWidth, m_nSrcHeight, SWP_NOMOVE|SWP_NOACTIVATE);  
  24. }  
  25.   
  26. void CStaticBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  
  27. {  
  28.     if (m_Image.IsNull())  
  29.         return;  
  30.   
  31.     CRect rcBtutton;  
  32.     GetClientRect(rcBtutton);  
  33.   
  34.     CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);  
  35.   
  36.     CRect rcSrc = CRect(0, 0, m_nSrcWidth, m_nSrcHeight);  
  37.     m_Image.Draw(pDC->m_hDC, rcBtutton, rcSrc);  
  38. }  
#include "stdafx.h"
#include "StaticBtn.h"
#include "Public.h"

CStaticBtn::CStaticBtn()
{

}

CStaticBtn::~CStaticBtn()
{

}

void CStaticBtn::Init(UINT uImageID)
{
	SetButtonStyle(BS_OWNERDRAW);

	LoadPicture(m_Image, uImageID);
	m_nSrcWidth = m_Image.GetWidth();
	m_nSrcHeight = m_Image.GetHeight();

	SetWindowPos(NULL, 0, 0, m_nSrcWidth, m_nSrcHeight, SWP_NOMOVE|SWP_NOACTIVATE);
}

void CStaticBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	if (m_Image.IsNull())
		return;

	CRect rcBtutton;
	GetClientRect(rcBtutton);

	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

	CRect rcSrc = CRect(0, 0, m_nSrcWidth, m_nSrcHeight);
	m_Image.Draw(pDC->m_hDC, rcBtutton, rcSrc);
}


使用方法:

CNoraml m_NorBtn;

m_NorBtn.Init(UNIT);


因为NormalBtn和MenuBtn需要相应鼠标事件,有图片切换,为了更好的图片切换效果使用双缓冲绘图。双缓冲绘图需要先创建一张画布(CBaseBtn::DrawItem()函数

  1. CBitmap memBitmap;  
  2. memBitmap.CreateCompatibleBitmap(pDC, buttonRect.Width(), buttonRect.Height());  
  3. dcMem.SelectObject(memBitmap);  
  4. dcMem.FillSolidRect(buttonRect, RGB(255,0,255));    //设置画布颜色  
	CBitmap memBitmap;
	memBitmap.CreateCompatibleBitmap(pDC, buttonRect.Width(), buttonRect.Height());
	dcMem.SelectObject(memBitmap);
	dcMem.FillSolidRect(buttonRect, RGB(255,0,255));	//设置画布颜色


所以虽然用了虽然PNG图片有透明属性,但是画布无法设置透明属性,最后的结果是虽然PNG图片背景透明了,因为画布的存在,无法做出一个不规程的按钮出来。
而StaticBtn使用的是单缓冲,没有画布的存在,利用PNG图片的透明属性,可以做出一个不规则的按钮。但是单缓冲绘图对于图片的切换效果不好,所以只用来做一个不响应鼠标消息的静态按钮。未来有空我将会写《MFC 之 CButton 控件重绘(GDI+篇)》利用GDI+绘图来解决这个问题。

完整的项目工程下载地址:http://download.csdn.net/detail/yuzhenxiong0823/7167827

  1. <pre class="cpp" name="code" snippet_file_name="blog_20140409_9_2739585" code_snippet_id="283280"><pre snippet_file_name="blog_20140409_9_2739585" code_snippet_id="283280"></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  
  5. <pre></pre>  
  6.       
  7.         <div style="padding-top: 20px;">           
  8.             <p style="font-size: 12px;">版权声明:本文为博主原创文章,未经博主允许不得转载。</p>  
  9.         </div>  
  10. </pre>  
<div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><strong>[cpp]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/yuzhenxiong0823/article/details/23278763#">view plain</a><a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/yuzhenxiong0823/article/details/23278763#">copy</a><a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/yuzhenxiong0823/article/details/23278763#">print</a><a target=_blank title="?" class="About" href="http://blog.csdn.net/yuzhenxiong0823/article/details/23278763#">?</a><a target=_blank title="在CODE上查看代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/283280" target="_blank"><img width="12" height="12" style="left: 2px; top: 1px; position: relative;" alt="在CODE上查看代码片" src="https://code.csdn.net/assets/CODE_ico.png" /></a><a target=_blank title="派生到我的代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/283280/fork" target="_blank"><img width="12" height="12" style="left: 2px; top: 2px; position: relative;" alt="派生到我的代码片" src="https://code.csdn.net/assets/ico_fork.svg" /></a></div></div><ol class="dp-cpp"><li class="alt"><span><span><pre snippet_file_name=</span><span class="string">"blog_20140409_9_2739585"</span><span> code_snippet_id=</span><span class="string">"283280"</span><span>></pre>  </span></span></li><li><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li><span>      </span></li><li class="alt"><span>        <div style=<span class="string">"padding-top: 20px;"</span><span>>           </span></span></li><li><span>            <p style=<span class="string">"font-size: 12px;"</span><span>>版权声明:本文为博主原创文章,未经博主允许不得转载。</p>  </span></span></li><li class="alt"><span>        </div>  </span></li></ol></div><pre class="cpp" style="display: none;" name="code" code_snippet_id="283280" snippet_file_name="blog_20140409_9_2739585"><pre code_snippet_id="283280" snippet_file_name="blog_20140409_9_2739585">
 
 
 
 
 
 
 
 

版权声明:本文为博主原创文章,未经博主允许不得转载。

 
 
 
 


          

猜你喜欢

转载自blog.csdn.net/myiszjf/article/details/49125521