MFC + CxImage 实现自绘半透明按钮

btn.h

[cpp] view plain copy
 
  1. #pragma once  
  2.   
  3. // CBtn  
  4. #include "ximage/ximage.h"  
  5.   
  6. class CBtn : public CButton  
  7. {  
  8.     DECLARE_DYNAMIC(CBtn)  
  9. private:  
  10.     CxImage * m_pImgNormal;  
  11.     CxImage * m_pImgOver;  
  12.     CxImage * m_pImgDown;  
  13.     CxImage * m_pImgFocus;  
  14.     CxImage * m_pImgDisable;  
  15.   
  16.     BOOL m_bTracking;  
  17.     BOOL m_bMouseOver;  
  18.     BOOL m_bLBtnDown;  
  19. public:  
  20.     CBtn(UINT imgID_LbtnDown,UINT imgID_Over,UINT imgID_Normal,UINT imgID_Disabled=0,UINT imgID_Focus=0);  
  21.     virtual ~CBtn();  
  22.   
  23. protected:  
  24.     DECLARE_MESSAGE_MAP()  
  25. public:  
  26.     virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);  
  27.     afx_msg void OnDestroy();  
  28.     afx_msg BOOL OnEraseBkgnd(CDC* pDC);  
  29.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  30.     afx_msg void OnMouseLeave();  
  31.     afx_msg void OnMouseHover(UINT nFlags, CPoint point);  
  32. protected:  
  33.     virtual BOOL PreCreateWindow(CREATESTRUCT& cs);  
  34. public:  
  35.     void PaintParent();  
  36.     virtual BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);  
  37.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
  38.     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
  39.     afx_msg void OnBnDoubleclicked();  
  40.     afx_msg void OnKillFocus(CWnd* pNewWnd);  
  41. };  


btn.cpp

[cpp] view plain copy
 
  1. // Btn.cpp : 实现文件     
  2. //     
  3.     
  4. #include "stdafx.h"     
  5. #include "Btn.h"     
  6.     
  7.     
  8. // CBtn  
  9. IMPLEMENT_DYNAMIC(CBtn, CButton)    
  10.     
  11. CBtn::CBtn(UINT imgID_LbtnDown,UINT imgID_Over,UINT imgID_Normal,UINT imgID_Disabled,UINT imgID_Focus):    
  12.       m_pImgNormal(NULL)    
  13.     , m_pImgOver(NULL)    
  14.     , m_pImgDown(NULL)    
  15.     , m_pImgFocus(NULL)    
  16.     , m_pImgDisable(NULL)    
  17.     , m_bTracking(FALSE)    
  18.     , m_bMouseOver(FALSE)    
  19.     , m_bLBtnDown(FALSE)    
  20. {    
  21.     if(imgID_Normal > 0)    
  22.     {    
  23.         if(!m_pImgNormal)    
  24.             m_pImgNormal = new CxImage(CXIMAGE_FORMAT_PNG);    
  25.         m_pImgNormal ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Normal),L"PNG"),CXIMAGE_FORMAT_PNG);    
  26.     }    
  27.     if(imgID_Focus > 0)    
  28.     {    
  29.         if(!m_pImgFocus)    
  30.             m_pImgFocus = new CxImage(CXIMAGE_FORMAT_PNG);    
  31.         m_pImgFocus ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Focus),L"PNG"),CXIMAGE_FORMAT_PNG);    
  32.     }    
  33.     if( imgID_LbtnDown>0 )    
  34.     {    
  35.         if(!m_pImgDown)    
  36.             m_pImgDown = new CxImage(CXIMAGE_FORMAT_PNG);    
  37.         m_pImgDown ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_LbtnDown),L"PNG"),CXIMAGE_FORMAT_PNG);    
  38.     }    
  39.     if( imgID_Disabled > 0 )    
  40.     {    
  41.         if(!m_pImgDisable)    
  42.             m_pImgDisable = new CxImage(CXIMAGE_FORMAT_PNG);    
  43.         m_pImgDisable ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Disabled),L"PNG"),CXIMAGE_FORMAT_PNG);    
  44.     }    
  45.     if( imgID_Over > 0)    
  46.     {    
  47.         if(!m_pImgOver)    
  48.             m_pImgOver = new CxImage(CXIMAGE_FORMAT_PNG);    
  49.         m_pImgOver ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(imgID_Over),L"PNG"),CXIMAGE_FORMAT_PNG);    
  50.     }    
  51. }    
  52.     
  53. CBtn::~CBtn()    
  54. {    
  55. }    
  56.     
  57. BEGIN_MESSAGE_MAP(CBtn, CWnd)    
  58.     ON_WM_DESTROY()    
  59.     ON_WM_ERASEBKGND()    
  60.     ON_WM_MOUSEMOVE()    
  61.     ON_WM_MOUSELEAVE()    
  62.     ON_WM_MOUSEHOVER()    
  63.     ON_WM_LBUTTONDOWN()    
  64.     ON_WM_LBUTTONUP()    
  65.     ON_CONTROL_REFLECT(BN_DOUBLECLICKED, &CBtn::OnBnDoubleclicked)    
  66.     ON_WM_KILLFOCUS()    
  67. END_MESSAGE_MAP()    
  68.     
  69.     
  70. // CBtn 消息处理程序     
  71. void CBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)    
  72. {    
  73.     CDC ButtonDC;     
  74.     CRect rc;    
  75.         
  76.     ButtonDC.Attach(lpDrawItemStruct->hDC); //得到用于绘制按钮的DC      
  77.     rc=lpDrawItemStruct->rcItem; //获取按钮所占的矩形大小     
  78.     
  79.     UINT state = lpDrawItemStruct->itemState; //获取按钮目前所处的状态,根据不同的状态绘制不同的按钮      
  80.     
  81.     if(state&ODS_DISABLED && m_pImgDisable)     
  82.     {     
  83.         m_pImgDisable ->Draw(ButtonDC.GetSafeHdc(),rc);    
  84.     }    
  85.     else    
  86.     {    
  87.     
  88.         if( m_bLBtnDown && m_pImgDown)    
  89.         {    
  90.             m_pImgDown ->Draw(ButtonDC.GetSafeHdc(),rc);    
  91.         }    
  92.         else if(m_bMouseOver && m_pImgOver)    
  93.         {    
  94.             m_pImgOver ->Draw(ButtonDC.GetSafeHdc(),rc);    
  95.         }    
  96.         else if(state&ODS_FOCUS && m_pImgFocus)     
  97.         {     
  98.             m_pImgFocus ->Draw(ButtonDC.GetSafeHdc(),rc);    
  99.         }    
  100.         else if(m_pImgNormal)    
  101.         {    
  102.             m_pImgNormal ->Draw(ButtonDC.GetSafeHdc(),rc);    
  103.         }    
  104.     }    
  105. }    
  106.     
  107. void CBtn::OnDestroy()    
  108. {    
  109.     CButton::OnDestroy();    
  110.     
  111.     // TODO: 在此处添加消息处理程序代码     
  112.     if(m_pImgNormal)    
  113.     {    
  114.         m_pImgNormal ->Destroy();    
  115.         delete m_pImgNormal;    
  116.         m_pImgNormal = NULL;    
  117.     }    
  118.     if(m_pImgOver)    
  119.     {    
  120.         m_pImgOver ->Destroy();    
  121.         delete m_pImgOver;    
  122.         m_pImgOver = NULL;    
  123.     }    
  124.     if(m_pImgDown)    
  125.     {    
  126.         m_pImgDown ->Destroy();    
  127.         delete m_pImgDown;    
  128.         m_pImgDown = NULL;    
  129.     }    
  130.     if(m_pImgFocus)    
  131.     {    
  132.         m_pImgFocus ->Destroy();    
  133.         delete m_pImgFocus;    
  134.         m_pImgFocus = NULL;    
  135.     }    
  136.     if(m_pImgDisable)    
  137.     {    
  138.         m_pImgDisable ->Destroy();    
  139.         delete m_pImgDisable;    
  140.         m_pImgDisable = NULL;    
  141.     }    
  142. }    
  143.     
  144. BOOL CBtn::OnEraseBkgnd(CDC* pDC)    
  145. {    
  146.     // TODO: 在此添加消息处理程序代码和/或调用默认值     
  147.     return TRUE;    
  148.     //return CButton::OnEraseBkgnd(pDC);     
  149. }    
  150.     
  151. BOOL CBtn::PreCreateWindow(CREATESTRUCT& cs)    
  152. {    
  153.     // TODO: 在此添加专用代码和/或调用基类     
  154.     cs.style |= BS_OWNERDRAW;    
  155.     
  156.     return CButton::PreCreateWindow(cs);    
  157. }    
  158.     
  159. void CBtn::OnMouseMove(UINT nFlags, CPoint point)    
  160. {    
  161.     // TODO: 在此添加消息处理程序代码和/或调用默认值     
  162.     m_bMouseOver = TRUE;    
  163.     if (!m_bTracking)    
  164.     {    
  165.         TRACKMOUSEEVENT   tme;     
  166.         tme.cbSize      =   sizeof(TRACKMOUSEEVENT);     
  167.         tme.dwFlags     =   TME_LEAVE|TME_HOVER; //     
  168.         tme.hwndTrack   =   GetSafeHwnd();     
  169.         tme.dwHoverTime =   8;     
  170.         _TrackMouseEvent(&tme);    
  171.         m_bTracking = TRUE;    
  172.     }    
  173.     CButton::OnMouseMove(nFlags, point);    
  174.     ::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));    
  175. }    
  176.     
  177. void CBtn::OnMouseLeave()    
  178. {    
  179.     // TODO: 在此添加消息处理程序代码和/或调用默认值     
  180.     m_bMouseOver    =   FALSE;     
  181.     m_bTracking     =   FALSE;      
  182.     m_bLBtnDown     =   FALSE;    
  183.     PaintParent();    
  184.     CButton::OnMouseLeave();    
  185. }    
  186.     
  187. void CBtn::OnMouseHover(UINT nFlags, CPoint point)    
  188. {    
  189.     m_bMouseOver = TRUE;    
  190.     PaintParent();    
  191.     ::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));    
  192. }    
  193.     
  194. void CBtn::PaintParent()    
  195. {    
  196.     CRect   rect;     
  197.     GetWindowRect(&rect);     
  198.     GetParent()-> ScreenToClient(&rect);     
  199.     GetParent()-> InvalidateRect(&rect);    
  200. }    
  201.     
  202. BOOL CBtn::Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)    
  203. {    
  204.     BOOL OK=CButton::Create(lpszCaption, dwStyle, rect, pParentWnd, nID);    
  205.     ModifyStyleEx(0, WS_EX_TRANSPARENT);// WS_EX_LAYERED||WS_EX_TRANSPARENT       
  206.     return OK;    
  207. }    
  208.     
  209. void CBtn::OnLButtonDown(UINT nFlags, CPoint point)    
  210. {    
  211.     m_bLBtnDown = TRUE;    
  212.     PaintParent();    
  213.     CButton::OnLButtonDown(nFlags, point);    
  214.     ::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));    
  215. }    
  216.     
  217. void CBtn::OnLButtonUp(UINT nFlags, CPoint point)    
  218. {    
  219.     m_bLBtnDown = FALSE;    
  220.     PaintParent();    
  221.     CButton::OnLButtonUp(nFlags, point);    
  222.     ::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));    
  223. }    
  224.     
  225. void CBtn::OnBnDoubleclicked()    
  226. {    
  227.     // TODO: 在此添加控件通知处理程序代码     
  228.     ::SetCursor(AfxGetApp() ->LoadCursor(IDC_CURSOR_HAND));    
  229. }    
  230.     
  231. void CBtn::OnKillFocus(CWnd* pNewWnd)    
  232. {    
  233.     CButton::OnKillFocus(pNewWnd);    
  234.     
  235.     // TODO: 在此处添加消息处理程序代码     
  236.     PaintParent();    
  237. }    

调用

[cpp] view plain copy
 
  1. ///头文件中添加  
  2. ...  
  3. #include "Btn.h"  
  4. ...  
  5.         enum {emTestBtnId1=8099,emTestBtnId2,emTestBtnId3};  
  6.     CBtn m_btnTest1,m_btnTest2,m_btnTest3;//test  
  7.   
  8. ///在构造函数初始化列表中初始化变量(IDB_PNG_BTN_TEST_*为Png图片资源ID)     
  9.     , m_btnTest1(IDB_PNG_BTN_TEST_DOWN,  
  10.             IDB_PNG_BTN_TEST_MOUSEOVER,  
  11.             IDB_PNG_BTN_TEST_NORMAL,  
  12.             IDB_PNG_BTN_TEST_DISABLE,  
  13.             IDB_PNG_BTN_TEST_FOCUS)   
  14.     , m_btnTest2(IDB_PNG_BTN_TEST_DOWN,  
  15.             IDB_PNG_BTN_TEST_MOUSEOVER,  
  16.             IDB_PNG_BTN_TEST_NORMAL,  
  17.             IDB_PNG_BTN_TEST_DISABLE/*,IDB_PNG_BTN_TEST_FOCUS*/)   
  18.     , m_btnTest3(IDB_PNG_BTN_TEST_DOWN,  
  19.             IDB_PNG_BTN_TEST_MOUSEOVER,  
  20.             IDB_PNG_BTN_TEST_NORMAL,  
  21.             IDB_PNG_BTN_TEST_DISABLE/*,IDB_PNG_BTN_TEST_FOCUS*/)  
  22.   
  23. ////在OnInitDialog()函数中创建按钮  
  24.     //test   
  25.     m_btnTest1.Create(_T("test"),WS_VISIBLE | WS_CHILD/* |WS_DISABLED*/,CRect(10,10,58,58),this,emTestBtnId1);   
  26.     m_btnTest2.Create(_T("test"),WS_VISIBLE | WS_CHILD/* |WS_DISABLED*/,CRect(10,60,58,108),this,emTestBtnId2);   
  27.     m_btnTest3.Create(_T("test"),WS_VISIBLE | WS_CHILD |WS_DISABLED,CRect(10,110,58,158),this,emTestBtnId2);  

效果图

原文地址:https://www.cnblogs.com/lidabo/p/6923347.html