之前经常看到同事和各位网友说控件自绘,没有相关需求,所以一直没有了解过,现在终于忍不住,学习下这方面知识。
控件自绘的方式有两种:1.将控件的自绘封装成一个类,控件类中自己绘制2.直接在父窗口进行自绘。
首先学习下第一种方式,在vs2008下示例:
1、建立基于对话框的MFC程序OwnerDrawing,添加按钮ID为IDC_BUTTON1。
2、项目名上右击->添加->类,添加MFC类(选MFC类非C++类),派生于CButton 的名为CMyBtn的类。
3、给IDC_BUTTON1添加CMyBtn类型的变量m_btn。
4、将IDC_BUTTON1的Owner Draw属性设置为true。
5、随便添加两个.bmp位图,ID为IDB_BITMAP1、IDB_BITMAP2。
6、CMyBtn类中重载CButton类的DrawItem()函数。
//声明:
afx_msg void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//定义
void CMyBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
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();
}
}
这样,就实现了当IDC_BUTTON1没有焦点时按钮bmp为IDB_BITMAP1,有焦点时按钮bmp为IDB_BITMAP2。