控件自绘的方式有两种:
1.直接在父窗口进行自绘(本文所讲述的)
2.将控件的自绘封装成一个类,控件类中自己绘制(本文不讲,参考其他文章)
-----------------------------------------------------------------
实现过程:
1.在主窗口中放置一个按钮
2.设置按钮的行为为:Owner Draw (控件自绘)
设置此行为后,控件需要自己绘制,否则显示不了控件。默认没有设置,系统会绘制此控件。
如图:
3.对父窗口的WM_DRAWITEM消息进行处理
在父窗口资源对话框中,右击,查看属性,如下图:
找到WM_DRAWITEM,添加处理函数。如图:
添加消息处理后,如下图:
4.消息处理函数OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
第一个参数int nIDCtl是控件ID,可以通过IF语句对ID进行判断,然后对不同的ID的控件进行自绘。上图中可以看出,有两个按钮,判断后调用相应的函数进行自绘处理。当然,我都使用了相同的方式自绘。注意,调用函数要将第二个参数LPDRAWITEMSTRUCT lpDrawItemStruct传给自绘函数。这个参数是自绘结构体,有自绘需要的各种信息。
5.自绘函数编写。
具体的每一句就不详细解释了。代码中有注释。
void C自绘按钮Dlg::draw(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC ButtonDC;
CBitmap bitmapTrans;
BITMAP bmp;
CDC mem;
CRect rc;
//得到用于绘制按钮的DC
ButtonDC.Attach(lpDrawItemStruct->hDC);
//准备用于向按钮区域传输位图
mem.CreateCompatibleDC(&ButtonDC);
//获取按钮所占的矩形大小
rc=lpDrawItemStruct->rcItem;
//获取按钮目前所处的状态,根据不同的状态绘制不同的按钮
UINT state = lpDrawItemStruct->itemState;
//如果按钮已经得到焦点,绘制选中状态下的按钮
if(state&ODS_FOCUS)
{
bitmapTrans.LoadBitmap(IDB_BITMAP2);
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans);
//向按钮所在位置传输位图
//使用StretcnBlt的目的是为了让位图随按钮的大小而改变
ButtonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
mem.SelectObject(old);
bitmapTrans.DeleteObject();
}
else
{
bitmapTrans.LoadBitmap(IDB_BITMAP1);
CBitmap *old2 = mem.SelectObject(&bitmapTrans);
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans);
ButtonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
mem.SelectObject(old2);
bitmapTrans.DeleteObject();
}
}
IDB_BITMAP1IDB_BITMAP2是两个Bitmap资源,需要提前添加以下。
6.运行的结果就是:
单击按钮(得到焦点)会更换按钮显示的图片,单击另外的按钮(失去焦点)后又会恢复之前的图片。
另外实现的截图:
单击前:
单击后: