MFC 之 CButton 控件重绘(GDI篇)

论坛 期权论坛 脚本     
匿名网站用户   2020-12-20 23:39   11   0

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格式)


下面贴代码:

基类代码(BaseBtn.h)

  1. #ifndef__BASEBTN_H__
  2. #define__BASEBTN_H__
  3. #include"stdafx.h"
  4. #include<atlimage.h>
  5. #if_MSC_VER>1000
  6. #pragmaonce
  7. #endif
  8. classCBaseBtn:publicCButton
  9. {
  10. public:
  11. CBaseBtn();
  12. ~CBaseBtn();
  13. public:
  14. virtualBOOLCreate(LPCTSTRlpszClassName,LPCTSTRlpszWindowName,DWORDdwStyle,constRECT&rect,CWnd*pParentWnd,UINTnID,CCreateContext*pContext=NULL);
  15. virtualvoidDrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct);
  16. virtualvoidSetFont(CFont*pFont,BOOLbRedraw=TRUE);
  17. virtualvoidSetWindowText(LPCTSTRlpszString);
  18. public:
  19. voidInit(UINTuImageID);
  20. voidSetBtnTextColor(COLORREFclr);
  21. protected:
  22. afx_msgBOOLOnEraseBkgnd(CDC*pDC);
  23. DECLARE_MESSAGE_MAP()
  24. protected:
  25. intm_nCtrlState;
  26. CImagem_Image;
  27. intm_nSrcWidth;
  28. intm_nSrcHeight;
  29. private:
  30. CStringm_strBtnText;
  31. CFont*m_pFont;
  32. COLORREFm_clr;
  33. };
  34. #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. #ifdef_DEBUG
  5. #definenewDEBUG_NEW
  6. #undefTHIS_FILE
  7. staticcharTHIS_FILE[]=__FILE__;
  8. #endif
  9. CBaseBtn::CBaseBtn()
  10. {
  11. m_pFont=newCFont;
  12. VERIFY(m_pFont->CreateFont(15,0,0,0,FW_BOLD,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
  13. CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,_T("Tahoma")));
  14. m_strBtnText=L"";
  15. m_clr=RGB(0,0,0);
  16. }
  17. CBaseBtn::~CBaseBtn()
  18. {
  19. if(!m_Image.IsNull())
  20. m_Image.Destroy();
  21. if(m_pFont!=NULL)
  22. {
  23. m_pFont->DeleteObject();
  24. deletem_pFont;
  25. m_pFont=NULL;
  26. }
  27. }
  28. BEGIN_MESSAGE_MAP(CBaseBtn,CButton)
  29. ON_WM_ERASEBKGND()
  30. END_MESSAGE_MAP()
  31. voidCBaseBtn::Init(UINTuImageID)
  32. {
  33. SetButtonStyle(BS_OWNERDRAW);
  34. LoadPicture(m_Image,uImageID);
  35. m_nSrcWidth=m_Image.GetWidth();
  36. m_nSrcHeight=m_Image.GetHeight();
  37. SetWindowPos(NULL,0,0,m_nSrcWidth/4,m_nSrcHeight,SWP_NOMOVE|SWP_NOACTIVATE);
  38. if(IsWindowEnabled())
  39. m_nCtrlState=CTRL_NOFOCUS;
  40. else
  41. m_nCtrlState=CTRL_DISABLE;
  42. }
  43. voidCBaseBtn::SetFont(CFont*pFont,BOOLbRedraw)
  44. {
  45. m_pFont=pFont;
  46. if(bRedraw)
  47. Invalidate();
  48. }
  49. voidCBaseBtn::SetWindowText(LPCTSTRlpszString)
  50. {
  51. m_strBtnText=lpszString;
  52. Invalidate();
  53. }
  54. voidCBaseBtn::SetBtnTextColor(COLORREFclr)
  55. {
  56. m_clr=clr;
  57. Invalidate();
  58. }
  59. BOOLCBaseBtn::Create(LPCTSTRlpszClassName,LPCTSTRlpszWindowName,DWORDdwStyle,constRECT&rect,CWnd*pParentWnd,UINTnID,CCreateContext*pContext)
  60. {
  61. returnCWnd::Create(lpszClassName,lpszWindowName,dwStyle,rect,pParentWnd,nID,pContext);
  62. }
  63. voidCBaseBtn::DrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct)
  64. {
  65. if(m_Image.IsNull())
  66. return;
  67. CRectbuttonRect;
  68. GetClientRect(buttonRect);
  69. CDC*pDC=CDC::FromHandle(lpDrawItemStruct->hDC);//按钮控件DC
  70. CDCdcMem;
  71. dcMem.CreateCompatibleDC(pDC);
  72. CBitmapmemBitmap;
  73. memBitmap.CreateCompatibleBitmap(pDC,buttonRect.Width(),buttonRect.Height());
  74. dcMem.SelectObject(memBitmap);
  75. dcMem.FillSolidRect(buttonRect,RGB(255,0,255));//设置画布颜色
  76. CRectrcSrc=CRect(0,0,0,0);
  77. switch(m_nCtrlState)
  78. {
  79. caseCTRL_NOFOCUS:
  80. {
  81. rcSrc=CRect(0,0,m_nSrcWidth/4,m_nSrcHeight);
  82. }
  83. break;
  84. caseCTRL_FOCUS:
  85. {
  86. rcSrc=CRect(m_nSrcWidth/4,0,m_nSrcWidth/4*2,m_nSrcHeight);
  87. }
  88. break;
  89. caseCTRL_SELECTED:
  90. {
  91. rcSrc=CRect(m_nSrcWidth/4*2,0,m_nSrcWidth/4*3,m_nSrcHeight);
  92. }
  93. break;
  94. caseCTRL_DISABLE:
  95. {
  96. rcSrc=CRect(m_nSrcWidth/4*3,0,m_nSrcWidth,m_nSrcHeight);
  97. }
  98. break;
  99. default:
  100. break;
  101. }
  102. m_Image.Draw(dcMem.m_hDC,buttonRect,rcSrc);
  103. dcMem.SetBkMode(TRANSPARENT);
  104. dcMem.SetTextColor(m_clr);
  105. CFont*pOldFont=dcMem.SelectObject(m_pFont);
  106. DrawText(dcMem.m_hDC,m_strBtnText,-1,buttonRect,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  107. dcMem.SelectObject(pOldFont);
  108. pDC->BitBlt(0,0,buttonRect.Width(),buttonRect.Height(),&dcMem,0,0,SRCCOPY);
  109. memBitmap.DeleteObject();
  110. }
  111. BOOLCBaseBtn::OnEraseBkgnd(CDC*pDC)
  112. {
  113. returnTRUE;
  114. }
#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. #include"BaseBtn.h"
  4. classCNormalBtn:publicCBaseBtn
  5. {
  6. public:
  7. CNormalBtn();
  8. ~CNormalBtn();
  9. protected:
  10. afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);
  11. afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);
  12. afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint);
  13. afx_msgLRESULTOnMouseLeave(WPARAM,LPARAM);
  14. afx_msgLRESULTOnMouseHover(WPARAM,LPARAM);
  15. DECLARE_MESSAGE_MAP()
  16. private:
  17. BOOLm_bTracking;//捕获设置标记
  18. };
  19. #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. #ifdef_DEBUG
  5. #definenewDEBUG_NEW
  6. #undefTHIS_FILE
  7. staticcharTHIS_FILE[]=__FILE__;
  8. #endif
  9. CNormalBtn::CNormalBtn()
  10. :m_bTracking(FALSE)
  11. {
  12. }
  13. CNormalBtn::~CNormalBtn()
  14. {
  15. }
  16. BEGIN_MESSAGE_MAP(CNormalBtn,CBaseBtn)
  17. ON_WM_MOUSEMOVE()
  18. ON_WM_LBUTTONDOWN()
  19. ON_WM_LBUTTONUP()
  20. ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
  21. ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)
  22. END_MESSAGE_MAP()
  23. voidCNormalBtn::OnMouseMove(UINTnFlags,CPointpoint)
  24. {
  25. if(!m_bTracking)
  26. {
  27. TRACKMOUSEEVENTtme;
  28. tme.cbSize=sizeof(tme);
  29. tme.hwndTrack=m_hWnd;
  30. tme.dwFlags=TME_LEAVE|TME_HOVER;
  31. tme.dwHoverTime=1;
  32. m_bTracking=_TrackMouseEvent(&tme);
  33. }
  34. CBaseBtn::OnMouseMove(nFlags,point);
  35. }
  36. LRESULTCNormalBtn::OnMouseHover(WPARAMwParam,LPARAMlParam)
  37. {
  38. if(m_nCtrlState==CTRL_NOFOCUS)
  39. {
  40. m_nCtrlState=CTRL_FOCUS;
  41. Invalidate();
  42. }
  43. m_bTracking=FALSE;
  44. return0;
  45. }
  46. LRESULTCNormalBtn::OnMouseLeave(WPARAMwParam,LPARAMlParam)
  47. {
  48. if(m_nCtrlState!=CTRL_NOFOCUS)
  49. {
  50. m_nCtrlState=CTRL_NOFOCUS;
  51. Invalidate();
  52. }
  53. m_bTracking=FALSE;
  54. return0;
  55. }
  56. voidCNormalBtn::OnLButtonDown(UINTnFlags,CPointpoint)
  57. {
  58. if(m_nCtrlState==CTRL_FOCUS)
  59. {
  60. m_nCtrlState=CTRL_SELECTED;
  61. Invalidate();
  62. }
  63. CBaseBtn::OnLButtonDown(nFlags,point);
  64. }
  65. voidCNormalBtn::OnLButtonUp(UINTnFlags,CPointpoint)
  66. {
  67. if(m_nCtrlState==CTRL_SELECTED)
  68. {
  69. m_nCtrlState=CTRL_FOCUS;
  70. Invalidate();
  71. }
  72. CBaseBtn::OnLButtonUp(nFlags,point);
  73. }
#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. #include"BaseBtn.h"
  4. classCMenuBtn:publicCBaseBtn
  5. {
  6. public:
  7. CMenuBtn();
  8. ~CMenuBtn();
  9. public:
  10. BOOLGetMenuOn(){returnm_bMenuOn;}
  11. voidSetMenuOn(BOOLbMenuOn);
  12. protected:
  13. afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);
  14. afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);
  15. afx_msgLRESULTOnMouseLeave(WPARAM,LPARAM);
  16. afx_msgLRESULTOnMouseHover(WPARAM,LPARAM);
  17. DECLARE_MESSAGE_MAP()
  18. private:
  19. BOOLm_bTracking;//捕获设置标记
  20. BOOLm_bMenuOn;//该菜单按钮是否被选中
  21. };
  22. #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. #ifdef_DEBUG
  5. #definenewDEBUG_NEW
  6. #undefTHIS_FILE
  7. staticcharTHIS_FILE[]=__FILE__;
  8. #endif
  9. CMenuBtn::CMenuBtn()
  10. :m_bTracking(FALSE)
  11. ,m_bMenuOn(FALSE)
  12. {
  13. }
  14. CMenuBtn::~CMenuBtn()
  15. {
  16. }
  17. BEGIN_MESSAGE_MAP(CMenuBtn,CBaseBtn)
  18. ON_WM_MOUSEMOVE()
  19. ON_WM_LBUTTONDOWN()
  20. ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
  21. ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)
  22. END_MESSAGE_MAP()
  23. voidCMenuBtn::OnMouseMove(UINTnFlags,CPointpoint)
  24. {
  25. if(!m_bTracking)
  26. {
  27. TRACKMOUSEEVENTtme;
  28. tme.cbSize=sizeof(tme);
  29. tme.hwndTrack=m_hWnd;
  30. tme.dwFlags=TME_LEAVE|TME_HOVER;
  31. tme.dwHoverTime=1;
  32. m_bTracking=_TrackMouseEvent(&tme);
  33. }
  34. CButton::OnMouseMove(nFlags,point);
  35. }
  36. voidCMenuBtn::OnLButtonDown(UINTnFlags,CPointpoint)
  37. {
  38. if(m_nCtrlState!=CTRL_SELECTED)
  39. {
  40. m_nCtrlState=CTRL_SELECTED;
  41. m_bMenuOn=TRUE;
  42. Invalidate();
  43. }
  44. CButton::OnLButtonDown(nFlags,point);
  45. }
  46. LRESULTCMenuBtn::OnMouseLeave(WPARAMwParam,LPARAMlParam)
  47. {
  48. if(m_bMenuOn)
  49. {
  50. m_nCtrlState=CTRL_SELECTED;
  51. Invalidate();
  52. }
  53. else
  54. {
  55. m_nCtrlState=CTRL_NOFOCUS;
  56. Invalidate();
  57. }
  58. m_bTracking=FALSE;
  59. return0;
  60. }
  61. LRESULTCMenuBtn::OnMouseHover(WPARAMwParam,LPARAMlParam)
  62. {
  63. if(m_nCtrlState!=CTRL_FOCUS)
  64. {
  65. m_nCtrlState=CTRL_FOCUS;
  66. Invalidate();
  67. }
  68. m_bTracking=FALSE;
  69. return0;
  70. }
  71. voidCMenuBtn::SetMenuOn(BOOLbMenuOn)
  72. {
  73. m_bMenuOn=bMenuOn;
  74. Invalidate();
  75. }
#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. #include"BaseBtn.h"
  4. classCStaticBtn:publicCBaseBtn
  5. {
  6. public:
  7. CStaticBtn();
  8. ~CStaticBtn();
  9. public:
  10. virtualvoidInit(UINTuImageID);
  11. virtualvoidDrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct);
  12. };
  13. #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. CStaticBtn::CStaticBtn()
  5. {
  6. }
  7. CStaticBtn::~CStaticBtn()
  8. {
  9. }
  10. voidCStaticBtn::Init(UINTuImageID)
  11. {
  12. SetButtonStyle(BS_OWNERDRAW);
  13. LoadPicture(m_Image,uImageID);
  14. m_nSrcWidth=m_Image.GetWidth();
  15. m_nSrcHeight=m_Image.GetHeight();
  16. SetWindowPos(NULL,0,0,m_nSrcWidth,m_nSrcHeight,SWP_NOMOVE|SWP_NOACTIVATE);
  17. }
  18. voidCStaticBtn::DrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct)
  19. {
  20. if(m_Image.IsNull())
  21. return;
  22. CRectrcBtutton;
  23. GetClientRect(rcBtutton);
  24. CDC*pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
  25. CRectrcSrc=CRect(0,0,m_nSrcWidth,m_nSrcHeight);
  26. m_Image.Draw(pDC->m_hDC,rcBtutton,rcSrc);
  27. }
#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. CBitmapmemBitmap;
  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. <preclass="cpp"name="code"snippet_file_name="blog_20140409_9_2739585"code_snippet_id="283280"><presnippet_file_name="blog_20140409_9_2739585"code_snippet_id="283280"></pre>
  2. <pre></pre>
  3. <pre></pre>
  4. <pre></pre>
  5. <pre></pre>
  6. <divstyle="padding-top:20px;">
  7. <pstyle="font-size:12px;">版权声明:本文为博主原创文章,未经博主允许不得转载。</p>
  8. </div>
  9. </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><presnippet_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><divstyle=<span class="string">"padding-top:20px;"</span><span>></span></span></li><li><span><pstyle=<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">




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




分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP