看了吕鑫老师的视频,自己试着编写了一个自绘按钮控件。
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"
));
}
|
代码很长,很多是自动生成的,主要的自绘过程都在OnPaint消息函数中完成。
本文转自Chinayu201451CTO博客,原文链接: http://blog.51cto.com/9233403/1967115,如需转载请自行联系原作者