下面,我们来看看我们自定义的Create函数,原本来讲,对于Create函数,我们只需定义按钮类的对象,而后引用一个Create函数就行了。可是,既然我们都自定义按钮类了,那么,我们就自定义其Create函数。
首先,我们派生一个继承自CButton类的CMybutton类,而后在派生类中,定义一个HRGN变量m_hRgn;然后,我们在构造函数中,初始化这个变量,初始化为0.
BOOL CMybutton::Create(LPCTSTR lpszCaption, DWORD dwStyle, const CPoint point, const HRGN hRgn, CWnd* pParentWnd, UINT nID)
{
// store region in member variable
DeleteObject(m_hRgn);
m_hRgn = CreateRectRgn(0, 0, 31, 31);
CRect box(0, 0, 0, 0);
if (m_hRgn != 0)
CombineRgn(m_hRgn, hRgn, 0, RGN_COPY);//拷贝hRgn;
// make sure that region bounding rect is located in (0, 0)
GetRgnBox(m_hRgn, &box);
OffsetRgn(m_hRgn, -box.left, -box.top);//保证区域的左顶点在原点;
GetRgnBox(m_hRgn, &box);
// update position of region center for caption output
m_CenterPoint = CPoint(box.left + box.Width() /2 , box.top + box.Height() /2);//找到区域的中点坐标,进而平移过去
box.OffsetRect(point);
return CButton::Create(lpszCaption, dwStyle, box, pParentWnd, nID);
}
既然要自定义按钮,我们需要修改按钮的样式,设置按钮样式为BS_OWNERDRAW方能自定义按钮。那么,我们就可以在presubclasswindow函数中设置。
void CMybutton::PreSubclassWindow()
{
// change window style to allow owner draw
ModifyStyle(0, BS_OWNERDRAW | BS_PUSHBUTTON);
CButton::PreSubclassWindow();
}
当我们修改按钮样式为自绘时,就会调用DrawItem函数。这个函数实现的是按钮等控件的自绘,而OnDrawItem函数则是实现父类对子类的绘制。下面,我们设计DrawItem函数:
void CMybutton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
CDC* pDC = CDC::FromHandle(lpDrawItemStruct -> hDC);
CRect rect;
GetClientRect(rect);
DrawButton(pDC, &rect, lpDrawItemStruct -> itemState);
}
void CMybutton::DrawButton(CDC * pDC, CRect * pRect, UINT state)
{
// 创建内存设备
HRGN hBaseRgn = CreateRectRgn(0, 0, 0, 0);
HBRUSH hBrush;
COLORREF ltInner; //左上内存边框的颜色
ltInner = RGB(255,0,0);
COLORREF rbOuter; //右下外侧边框的颜色
rbOuter = RGB(0,255,0);
HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
GetWindowRgn(hRgn);
CombineRgn(hBaseRgn, hRgn, 0, RGN_COPY);
OffsetRgn(hBaseRgn, 1, 1);
CombineRgn(hBaseRgn, hRgn, hBaseRgn, RGN_DIFF);//得到左上框的部分并上色为红色
hBrush = CreateSolidBrush(ltInner);
FillRgn(*pDC, hBaseRgn, hBrush);
DeleteObject(hBrush);
CombineRgn(hBaseRgn, hRgn, 0, RGN_COPY);
OffsetRgn(hBaseRgn, -1, -1);
CombineRgn(hBaseRgn, hRgn, hBaseRgn, RGN_DIFF);//得到右上框的部分并上色为红色
hBrush = CreateSolidBrush(rbOuter);
FillRgn(*pDC, hBaseRgn, hBrush);
DeleteObject(hBrush);
}
最后,我们在派生类的OnCreate函数中,设置区域:
int CMybutton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CButton::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
SetWindowRgn(m_hRgn,true);
return 0;
}
下面,我们在主对话框类中,调用我们的派生类:首先定义派生类的对象:
CMybutton m_Open;
同时引入派生类的头文件:
#include "Mybutton.h"
然后在OnInitDialog函数中:
HRGN c,r;
c = CreateRectRgn(8, 0, 55, 31);
r = CreateEllipticRgn(48, 8, 15 + 48, 15 + 8);
CombineRgn(c, c, r, RGN_OR);
m_Open.Create(L"Open", WS_CHILD | WS_VISIBLE, CPoint(37, 115), c, this, 101012);
DeleteObject(c);
DeleteObject(r);
在这里,我需要重复强调一个事:对于内存设备对象,我们需要用完之后释放,同时最好还要初始化,还有就是指针对象,一定要记得初始化。要不然,你就会被内存访问问题缠死.....最后看看实现:
对于按钮标题为什么没有显现,主要是,我并没有设计按钮的前景色,使得自定义按钮的标题颜色是白色,你看不出来,因此,这个按钮自定义类,我还得继续完善......