位图按钮类,实现了按下、放开和鼠标在按钮上的图片更换。

一个位图按钮类,实现了按下、放开和鼠标在按钮上的图片更换。

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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/ 
// 工程: YF_GCM -> ButtonDemo
// 作者: **
// 描述: 自绘制位图按钮
// 主要函数:
// SetButtonUpBitmapEx()设置鼠标放置在按钮上的图片
// SetButtonDownBitmapEx()设置按钮按下的图片
// SetButtonNormalBitmapEx()设置鼠标不在按钮是的图片
// 日期: 2013.12.16
// 版本: 1.0
// 修改:
/
// BitmapButtonEx.cpp : 实现文件
//

#include "stdafx.h"
#include "resource.h"
#include "BitmapButtonEx.h"


// CBitmapButtonEx

IMPLEMENT_DYNAMIC(CBitmapButtonEx, CBitmapButton)

CBitmapButtonEx::CBitmapButtonEx()
: m_hUpBitmap(NULL)
, m_hDownBitmap(NULL)
, m_hNormalBitmap(NULL)
, m_lButtonDown(FALSE)
, m_bMouseOver(FALSE)
, m_bTrack(FALSE)
{
m_rgn.CreateRectRgn(0,0,0,0);
}

CBitmapButtonEx::~CBitmapButtonEx()
{
if (NULL != m_hUpBitmap)
{
::DeleteObject(m_hUpBitmap);
}
if (NULL != m_hDownBitmap)
{
::DeleteObject(m_hDownBitmap);
}
if (NULL != m_hNormalBitmap)
{
::DeleteObject(m_hDownBitmap);
}
}


BEGIN_MESSAGE_MAP(CBitmapButtonEx, CBitmapButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()



// CBitmapButtonEx 消息处理程序

BOOL CBitmapButtonEx::SetButtonUpBitmapEx(const CString& szFilePath)
{
if (NULL != m_hUpBitmap)
{
::DeleteObject(m_hUpBitmap);
m_hUpBitmap = NULL;
}

m_hUpBitmap = (HBITMAP)LoadImage(NULL, szFilePath, IMAGE_BITMAP, 0,0, LR_LOADFROMFILE); // 载入


return NULL != m_hUpBitmap;
}


BOOL CBitmapButtonEx::SetButtonUpBitmapEx(HBITMAP hBitmap)
{
m_hUpBitmap = hBitmap;

return NULL != m_hUpBitmap;
}
BOOL CBitmapButtonEx::SetButtonNormalBitmapEx(HBITMAP hBitmap)
{
m_hNormalBitmap = hBitmap;

return NULL != m_hNormalBitmap;
}
BOOL CBitmapButtonEx::SetButtonNormalBitmapEx(const CString& szFilePath)
{
if (NULL != m_hNormalBitmap)
{
::DeleteObject(m_hNormalBitmap);
m_hNormalBitmap = NULL;
}
m_hNormalBitmap = (HBITMAP)LoadImage(NULL, szFilePath, IMAGE_BITMAP, 0,0, LR_LOADFROMFILE); // 载入

return NULL != m_hNormalBitmap;
}

BOOL CBitmapButtonEx::SetButtonDownBitmapEx(const CString& szFilePath)
{
if (NULL != m_hDownBitmap)
{
::DeleteObject(m_hDownBitmap);
m_hDownBitmap = NULL;
}
m_hDownBitmap = (HBITMAP)LoadImage(NULL, szFilePath, IMAGE_BITMAP, 0,0, LR_LOADFROMFILE); // 载入

return NULL != m_hDownBitmap;
}
BOOL CBitmapButtonEx::SetButtonDownBitmapEx(HBITMAP hBitmap)
{
m_hDownBitmap = hBitmap;

return NULL != m_hDownBitmap;
}
void CBitmapButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
//
CBitmap hbmp;
if (m_lButtonDown)
{
hbmp.Attach(m_hDownBitmap);
}
else
{
if (m_bMouseOver)
{
hbmp.Attach(m_hUpBitmap);
}
else
{
hbmp.Attach(m_hNormalBitmap);
}
}

BITMAP bm;
hbmp.GetBitmap(&bm);
CDC* thisdc = NULL;
thisdc = GetDC();

CDC dcMem;
dcMem.CreateCompatibleDC(thisdc);
CBitmap *poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);
//显示位图
thisdc->SelectClipRgn(&m_rgn); //改变pDC的裁减区域
dcMem.SelectClipRgn(&m_rgn);
// 无缩放
// GetDC()->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcMem, 0, 0, SRCCOPY);
// 缩放
thisdc->StretchBlt(rect.left ,rect.top , rect.Width(), rect.Height(),
&dcMem,0 ,0, bm.bmWidth, bm.bmHeight, SRCCOPY);

dcMem.SelectObject(&poldBitmap);
this->ReleaseDC(thisdc);
hbmp.Detach();
}

void CBitmapButtonEx::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类

ModifyStyle(0, BS_OWNERDRAW); //设置按钮的有效区域
CRgn rgn;
CRect rc;
GetClientRect(&rc); //有效区域为一个角半径为5的圆角矩形
m_rgn.DeleteObject();
m_rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom, 5, 5);
rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom, 5, 5);
rgn.CopyRgn(&m_rgn);

SetWindowRgn(rgn, TRUE);
rgn.DeleteObject();

// CRgn rgn;
// CRect rc;
// GetClientRect(&rc); //有效区域为一个角半径为5的圆角矩形
//
// rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom, 5, 5);
// SetWindowRgn(rgn,TRUE);
// rgn.DeleteObject();
//
CBitmapButton::PreSubclassWindow();
}

void CBitmapButtonEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_lButtonDown = TRUE;
InvalidateRect(NULL);
CBitmapButton::OnLButtonDown(nFlags, point);
}

void CBitmapButtonEx::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_lButtonDown = FALSE;
InvalidateRect(NULL);
CBitmapButton::OnLButtonUp(nFlags, point);
}

BOOL CBitmapButtonEx::SetButtonRgn(const CRgn& rgn)
{
m_rgn.CopyRgn(&m_rgn);
return 0;
}

BOOL CBitmapButtonEx::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类



if(pMsg->message==WM_MOUSELEAVE)
{
m_bTrack=FALSE;
m_bMouseOver = FALSE;
InvalidateRect(NULL);
}
else if (pMsg->message==WM_MOUSEHOVER)
{
m_bMouseOver = TRUE;
InvalidateRect(NULL);
}

return CBitmapButton::PreTranslateMessage(pMsg);
}

void CBitmapButtonEx::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值

if(!m_bTrack)
{
TRACKMOUSEEVENT tme;
tme.cbSize=sizeof(TRACKMOUSEEVENT);
tme.dwFlags=TME_HOVER | TME_LEAVE;
tme.dwHoverTime=HOVER_DEFAULT;
tme.hwndTrack=m_hWnd;

m_bTrack=_TrackMouseEvent(&tme);
}

CBitmapButton::OnMouseMove(nFlags, point);
}

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
#pragma once
#include "afxwin.h"
// 工程: YF_GCM -> ButtonDemo
// 作者: **
// 描述: 自绘制位图按钮
// 主要函数:
// SetButtonUpBitmapEx()设置鼠标放置在按钮上的图片
// SetButtonDownBitmapEx()设置按钮按下的图片
// SetButtonNormalBitmapEx()设置鼠标不在按钮是的图片
// 日期: 2013.12.16
// 版本: 1.0
// 修改:
/
// CBitmapButtonEx

class CBitmapButtonEx : public CBitmapButton
{
DECLARE_DYNAMIC(CBitmapButtonEx)

public:
CBitmapButtonEx();
virtual ~CBitmapButtonEx();

protected:
DECLARE_MESSAGE_MAP()

protected:
// // all bitmaps must be the same size
// CBitmap m_bitmap; // normal image (REQUIRED)
// CBitmap m_bitmapSel; // selected image (OPTIONAL)
// CBitmap m_bitmapFocus; // focused but not selected (OPTIONAL)
// CBitmap m_bitmapDisabled; // disabled bitmap (OPTIONAL)
//
// virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);



public:
// 设置按钮抬起图片
BOOL SetButtonUpBitmapEx(const CString& szFilePath);
BOOL SetButtonUpBitmapEx(HBITMAP hBitmap);
// 设置按钮按下图片
BOOL SetButtonDownBitmapEx(const CString& szFilePath);
BOOL SetButtonDownBitmapEx(HBITMAP hBitmap);
// 普通按钮图片
BOOL SetButtonNormalBitmapEx(const CString& szFilePath);
BOOL SetButtonNormalBitmapEx(HBITMAP hBitmap);

protected:
virtual void PreSubclassWindow();
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
protected:
BOOL m_lButtonDown;
// 按钮有效区域
CRgn m_rgn;
private:
// 图片
HBITMAP m_hUpBitmap;
HBITMAP m_hDownBitmap;
HBITMAP m_hNormalBitmap;

public:
BOOL SetButtonRgn(const CRgn & rgn);
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
protected:
BOOL m_bMouseOver;
BOOL m_bTrack;
};

效果图显示如图中in的按钮

20140106174957906