看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件。
YuButton.h头文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#pragma once  
#include "afxwin.h"  
class  CYuButton : public  CWnd  
{  
     private :  
         BOOL   m_bIsDown;  
         BOOL   m_bIsMove;  
         BOOL   _bMouseTrack; //鼠标追踪状态  
   
         CString  m_sCaption;  
         CFont    *m_pFont;  
           
     public :  
     CYuButton( void );  
     virtual  ~CYuButton( void );  
   
     BOOL  Create( LPCTSTR  sCpation, DWORD  dwStyle,CONST CRect & rt,CWnd * pParendWnd,  
                    UINT  uId);  
     BOOL  CreateEx( DWORD  dwExStyle, LPCTSTR  sCaption, DWORD  dwStyle,CONST CRect & rt,  
CWnd * pParendWnd, UINT  uId);  
     DECLARE_MESSAGE_MAP()  
     afx_msg  void  OnNcPaint();  
     afx_msg  BOOL  OnEraseBkgnd(CDC* pDC);  
     afx_msg  void  OnPaint();  
     afx_msg  void  OnLButtonDown( UINT  nFlags, CPoint point);  
     afx_msg  void  OnLButtonUp( UINT  nFlags, CPoint point);  
     afx_msg  void  OnMouseMove( UINT  nFlags, CPoint point);  
   
     //鼠标按下  
     void  DrawDown(CDC * pDC);  
     //鼠标移动  
     void  DrawMove(CDC * pDC);  
     //字体  
     void  SetFont(CFont * pFont);  
     CFont * GetFont();  
     afx_msg  void  OnKillFocus(CWnd* pNewWnd);  
     afx_msg  void  OnMouseHover( UINT  nFlags, CPoint point);  
     afx_msg  void  OnMouseLeave();  
};

YuButton.cpp文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "StdAfx.h"  
#include "YuButton.h"  
   
   
CYuButton::CYuButton( void )  
{  
     WNDCLASS wd={CS_VREDRAW|CS_HREDRAW,::DefWindowProc};  
     wd.lpszClassName = _T( "YUButton" );  
   
     AfxRegisterClass(&wd);  
   
     m_bIsDown   = FALSE;  
     m_bIsMove   = FALSE;  
     _bMouseTrack = TRUE;  
}  
   
CYuButton::~CYuButton( void )  
{  
}  
   
BOOL  CYuButton::Create( LPCTSTR  sCaption, DWORD  dwStyle,CONST CRect & rt,CWnd *  
pParendWnd, UINT  uId)  
{  
     m_sCaption = sCaption;  
     m_pFont = pParendWnd->GetFont();  
     return  CWnd::Create(_T( "YUButton" ),sCaption,dwStyle|WS_CHILD,rt,pParendWnd,uId);  
}  
   
BOOL  CYuButton::CreateEx( DWORD  dwExStyle, LPCTSTR  sCaption, DWORD  dwStyle,CONST CRect & rt,  
CWnd * pParendWnd, UINT  uId)  
{  
     m_sCaption = sCaption;  
     return  CWnd::CreateEx(dwExStyle,_T( "YUButton" ),sCaption,dwStyle|WS_CHILD,rt,  
                           pParendWnd,uId);  
}  
BEGIN_MESSAGE_MAP(CYuButton, CWnd)  
     ON_WM_NCPAINT()  
     ON_WM_ERASEBKGND()  
     ON_WM_PAINT()  
     ON_WM_LBUTTONDOWN()  
     ON_WM_LBUTTONUP()  
     ON_WM_MOUSEMOVE()  
     ON_WM_KILLFOCUS()  
     ON_WM_MOUSEHOVER()  
     ON_WM_MOUSELEAVE()  
END_MESSAGE_MAP()  
   
void  CYuButton::OnNcPaint()  
{  
   
}  
   
BOOL  CYuButton::OnEraseBkgnd(CDC* pDC)  
{  
     return  true ; //CWnd::OnEraseBkgnd(pDC);  
}  
   
void  CYuButton::OnPaint()  
{  
     CPaintDC dc( this );  // device context for painting  
     CRect rt;  
     GetClientRect(&rt);  
       
     if (!m_bIsDown ) //未点击填充  
     {  
         CBrush brush(RGB(241,243,248));  
         dc.SelectObject(brush);  
         dc.FillRect(rt,&brush);  
     }  
     else  
         DrawDown(&dc);  
   
     if (m_bIsMove && !m_bIsDown) //鼠标移动  
     {  
         DrawMove(&dc);  
     }  
   
     CPen pen; //画边框  
     pen.CreatePen(PS_SOLID,1,RGB(85,134,233));  
     dc.SelectObject(pen);  
     dc.Rectangle(rt);  
   
     dc.SelectObject(m_pFont); //父窗口字体  
     dc.SetBkMode(TRANSPARENT);  
     dc.DrawText(m_sCaption,rt,DT_VCENTER|DT_CENTER|DT_SINGLELINE);  
}  
   
void  CYuButton::OnLButtonDown( UINT  nFlags, CPoint point)  
{  
     // TODO: 在此添加消息处理程序代码和/或调用默认值  
     m_bIsDown = TRUE;  
     this ->SetFocus();  
     this ->Invalidate(TRUE);  
       
     CWnd::OnLButtonDown(nFlags, point);  
}  
   
void  CYuButton::OnLButtonUp( UINT  nFlags, CPoint point)  
{  
     // TODO: 在此添加消息处理程序代码和/或调用默认值  
     m_bIsDown = FALSE;  
   
     this ->Invalidate(TRUE);  
   
     CWnd * pWnd =  this ->GetParent();  
   
     if (pWnd)  
         pWnd->SendMessage(WM_COMMAND,GetDlgCtrlID(),( LPARAM ) this ->GetSafeHwnd());  
   
     CWnd::OnLButtonUp(nFlags, point);  
}  
   
void  CYuButton::OnMouseMove( UINT  nFlags, CPoint point)  
{  
     if  (_bMouseTrack)      //若允许追踪,则。   
     {  
         TRACKMOUSEEVENT csTME;  
         csTME.cbSize =  sizeof  (csTME);  
         csTME.dwFlags = TME_LEAVE|TME_HOVER;  
         csTME.hwndTrack = m_hWnd ; // 指定要追踪的窗口   
         csTME.dwHoverTime = 10;   // 鼠标在按钮上停留超过 10ms ,才认为状态为 HOVER  
         ::_TrackMouseEvent (&csTME);  //开启 Windows 的 WM_MOUSELEAVE,WM_MOUSEHOVER 事件支持  
         _bMouseTrack=FALSE ;    // 若已经追踪,则停止追踪   
     }  
   
     CWnd::OnMouseMove(nFlags, point);  
}  
   
void  CYuButton::DrawDown(CDC * pDC)  
{  
     CRect rt;  
     GetClientRect(&rt);  
   
     CBrush brush;  
     brush.CreateSolidBrush(RGB(124,180,233));  
     pDC->SelectObject(brush);  
     pDC->FillRect(rt,&brush);  
}  
   
void  CYuButton::SetFont(CFont * pFont)  
{  
     m_pFont = pFont;  
}  
   
CFont * CYuButton::GetFont()  
{  
     return  m_pFont;  
}  
   
void  CYuButton::DrawMove(CDC * pDC)  
{  
     CRect rt;  
     GetClientRect(&rt);  
   
     CBrush brush;  
     brush.CreateSolidBrush(RGB(188,199,216));  
     pDC->SelectObject(brush);  
     pDC->FillRect(rt,&brush);  
}  
   
void  CYuButton::OnKillFocus(CWnd* pNewWnd)  
{  
     CWnd::OnKillFocus(pNewWnd);  
     m_bIsMove = FALSE;  
     Invalidate(TRUE);  
}  
   
void  CYuButton::OnMouseHover( UINT  nFlags, CPoint point)  
{  
     m_bIsMove = TRUE;  
     Invalidate(TRUE);  
     CWnd::OnMouseHover(nFlags, point);  
}  
   
void  CYuButton::OnMouseLeave()  
{  
     _bMouseTrack = TRUE;  
     m_bIsMove = FALSE;  
     Invalidate(TRUE);  
     CWnd::OnMouseLeave();  
}

在对话框窗口头文件中声明:CYuButton m_ok成员变量,然后OnInitDialog函数中创建自绘按钮:
(注意:对话框窗口头文件,须包含自绘按钮控件的.h文件YuButton.h)

1
2
3
4
5
6
7
BOOL  CtestDlg::OnInitDialog()  
{  
     ...  
     CRect rc(20,20,120,43);  
     m_ok.Create(_T( "确定" ),WS_VISIBLE,rc, this ,1290);  
     ...  
}

手动添加消息映射,为什么手动,因为自绘按钮,其ID不在资源中,所以不能用类向导管理,如下:

1
2
3
4
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)  
    ...  
    ON_BN_CLICKED(1290,&CtestDlg::OnClickedOk)  
END_MESSAGE_MAP()

对话框窗口头文件中,声明相应的消息处理函数OnClickedOk,如下:

1
void  OnClickedOk();

编写消息处理函数代码:

1
2
3
4
void  CtestDlg::OnClickedOk()  
{  
     AfxMessageBox(_T( "ok" ));  
}

wKiom1nB_s6zcRgcAAEHbfkDIkI139.gif

代码很长,很多是自动生成的,主要的自绘过程都在OnPaint消息函数中完成。

































本文转自Chinayu201451CTO博客,原文链接: http://blog.51cto.com/9233403/1967115,如需转载请自行联系原作者