1.首先从一个现成的控件类(比如CButton)设计派生出自己的控件类,比如CButtonExte,
2.实现虚函数virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct):
LPDRAWITEMSTRUCT 定义如下
typedef struct tagDRAWITEMSTRUCT {
UINT CtlType;
UINT CtlID;
UINT itemID;
UINT itemAction;
UINT itemState;
HWND hwndItem;
HDC hDC;
RECT rcItem;
ULONG_PTR itemData;
} DRAWITEMSTRUCT, NEAR *PDRAWITEMSTRUCT, FAR *LPDRAWITEMSTRUCT
利用lpDrawItemStruct的属性信息即可对CButtonExte外观进行设计,比如利用lpDrawItemStruct->hDC绘制一些比较炫图形图像,
注意我们创建的控件类属性
WNDCLASS,其风格里都是CS_PARENTDC,即和父窗口共用DC,这里传递进来的lpDrawItemStruct->hDC的剪切区已经被DrawItem的调用者(应该是其父窗口)把DC的剪切区设置为rcItem了,
所以如果想在CButtonExte控件的自身区域之外进行绘制动作(比如想实现按钮点下时的波射效果),就要重设剪切区,示例:
void CButtonExte::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
HRGN preHrgn = CreateRectRgn(lpDrawItemStruct->rcItem.left,lpDrawItemStruct->rcItem.top, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom);
HRGN hrgn = CreateRectRgn(-100, -100, 100, 100);
SelectClipRgn(lpDrawItemStruct->hDC, hrgn); //设置新的剪切区
MoveToEx(lpDrawItemStruct->hDC,-100,-100,NULL); //在新的剪切区进行绘制
LineTo(lpDrawItemStruct->hDC,100,100);
SelectClipRgn(lpDrawItemStruct->hDC, preHrgn);//恢复剪切区
}
当然了也可以在DrawItem函数中通过GetDC直接获取父窗口DC来在父窗口上进行绘制:
HDC hdc;
//这个通过GetDC或取得额父窗口DC的剪切区是父窗口的客户区,这个应该是GetDC里面进行了处理,疑问:CS_PARENTDC说是共用DC,那么DC的剪切区是如何随时切换的呐?这个值得琢磨
hdc=::GetDC(::GetParent(m_hWnd));
MoveToEx(hdc,2,2,NULL);
LineTo(hdc,123,123);
::ReleaseDC(::GetParent(m_hWnd),hdc);
3.使用CButtonExte创建一个控件对象,利用对话框编辑器进行静态创建和利用手动编代码动态创建都可以,设置其Owner Draw属性为TRUE,这样可以在按钮需要重绘时触发DrawItem。
对于控件要自定义的行为动作,可以重载其对应的消息响应函数来完成。还可以加上自己想添加的功能函数,实现控件的定制。