MFC自绘Button按钮分析和实现
对于按压式的Button按钮,WM_CTLCOLOR无法完成按钮控件的背景颜色和字体颜色修改,若想要完成外观定制需要添加WM_DRAWITEM消息或者重写CButton类中的DrawItem函数完成按钮外观修改,下面逐一介绍。
自绘制知识基础
自绘制需要的两个基础步骤:
1.控件类型设置为 BS_OWNERDRAW
2.添加WM_DRAWITEM消息响应函数或者重写DrawItem函数。
WM_DRAWITEM消息响应原型如下:
afx_msg void OnDrawItem( int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct );
参数:
nIDCtl
包含了发送WM_DRAWITEM消息的控件的标识符。如果菜单发送了此消息,则nIDCtl中包含0。
lpDrawItemStruct
指定了指向DRAWITEMSTRUCT数据结构的长指针,其中包含有关要画出的项和要求的绘图类型的信息。
说明:
当控件或菜单的可视状态发生变化时,框架为自画按钮控件、组合框控件、列表框控件或者菜单的拥有者调用这个成员函数。
DRAWITEMSTRUCT结构体信息如下:
typedef struct tagDRAWITEMSTRUCT { UINT CtlType; UINT CtlID; UINT itemID; UINT itemAction; UINT itemState; HWND hwndItem; HDC hDC; RECT rcItem; ULONG_PTR itemData; } DRAWITEMSTRUCT;
DrawItem函数原型如下,入参和OnDrawItem一样,不再重复介绍:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
需要说明的是,若某个控件拥有了BS_OWNERDRAW属性,则控件的绘制将由父窗口完成转移给了“程序员”,程序员需要完成所有的绘制工作,也就实现了控件自绘,若没有完成控件绘制功作,我们在界面上将看不到对应的控件,我们在重绘某个控件时,强烈推荐使用子类化方法,比如想自绘Button控件, 首先添加自己的类CMYButton 继承自 CButton,这样的设计符合程序设计思想,避免了父类功能的臃肿,也实现了程序的复用。
自绘制原理分析
自绘基本流程我已经绘制成流程图了,这样也清晰易懂,图中的数字标识也给出了简单介绍,自绘流程如图1所示:
图1 自绘制原理
1.子控件将要被绘制时,检测该控件有BS_OWNERDRAW属性,则向父窗口发送WM_DRAWITEM消息
2.父窗口完成收集和准备控件绘制所必要的信息
3.若ReflectLastMsg函数返回TRUE,表示消息反射成功,使用子控件中的绘制代码
4.若ReflectLastMsg函数返回FALSE,表示消息反射失败,使用父窗口中的绘制代码
5.消息反射成功了,我们就可以重写CButton中DrawItem虚函数完成控件自绘制
下面将展示如何完成控件的绘制步骤:
1.基于对话框建立DrawButton工程
2.添三个按压式Button控件,其ID分别四IDC_YES,IDC_NO, IDC_HELP如图2所示:
图2 控件布局
3.分别在父窗口(对话框)和子类化中实现自绘,具体过程如下:
父窗口中实现自绘制
具体过程:类视图->属性->查找WM_WM_DRAWITEM->添加并编辑"OnDrawItem",其代码如下:
void CDrawButtonDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //获得button标题 CString btnCaption = _T("Dialog"); CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect drawRect; //获得绘图DC //得到原Button的矩形大小 drawRect.CopyRect(&(lpDrawItemStruct->rcItem)); //绘制控件框架 pDC->DrawFrameControl(&drawRect,DFC_BUTTON,lpDrawItemStruct->CtlType); //创建画刷 CBrush pBrush; pBrush.CreateSolidBrush(RGB(100,130,10)); //画矩形 pDC->FillRect(drawRect,&pBrush); //定义一个CRect用于绘制文本 CRect textRect; //拷贝矩形区域 textRect.CopyRect(&drawRect); //获得字符串尺寸 CSize sz = pDC->GetTextExtent(btnCaption); //调整文本位置 居中 textRect.top += (textRect.Height()- sz.cy)/2; //设置文本背景透明 pDC->SetBkMode(TRANSPARENT); //设置文本颜色 pDC->SetTextColor(RGB(0,0,255)); //绘制文本内容 pDC->DrawText(btnCaption,&textRect,DT_RIGHT|DT_CENTER|DT_BOTTOM); CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); }
子类化实现自绘制
具体过程:
1.类视图->点击工程名->点击添加->MFC类->基类:CButton,子类命名为CMyButton。
2.资源视图->控件IDC_YES,IDC_HELP添加变量->类型选择为CMyButton。
在自定义的CMyButton中我们添加DrawItem虚函数,其具体代码如下:
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CString btnCaption = ""; //设置标题 switch (lpDrawItemStruct->CtlID) { case IDC_YES: btnCaption = "Yes"; break; case IDC_NO: btnCaption = "No"; break; case IDC_HELP: btnCaption = "Help"; break; default: ; } CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect drawRect; //获得绘图DC //得到原Button的矩形大小 drawRect.CopyRect(&(lpDrawItemStruct->rcItem)); //绘制控件框架 pDC->DrawFrameControl(&drawRect,DFC_BUTTON,lpDrawItemStruct->CtlType); //使得初始的button颜色不一样 static int nStepColor = 0; //创建画刷 CBrush pBrush; pBrush.CreateSolidBrush(RGB(100+nStepColor,130,nStepColor)); //画矩形 pDC->FillRect(drawRect,&pBrush); //定义一个CRect用于绘制文本 CRect textRect; //拷贝矩形区域 textRect.CopyRect(&drawRect); //获得字符串尺寸 CSize sz = pDC->GetTextExtent(btnCaption); //调整文本位置 居中 textRect.top += (textRect.Height()- sz.cy)/2; //设置文本背景透明 pDC->SetBkMode(TRANSPARENT); //设置文本颜色 pDC->SetTextColor(RGB(0,0,255)); //绘制文本内容 pDC->DrawText(btnCaption,&textRect,DT_RIGHT|DT_CENTER|DT_BOTTOM); nStepColor += 120; }
运行效果:
说明中间一个Button按钮的自绘是由父窗口的OnDrawItem实现的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
相关文章
iOS设置UIButton文字显示位置和字体大小、颜色的方法
这篇文章给大家分享了iOS如何设置UIButton的文字显示位置和字体的大小、颜色,文中给出了示例代码,相信对大家的学习和理解很有帮助,有需要的朋友们下面来一起看看吧。...2020-06-30- 下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
- 这篇文章主要为大家详细解析了BootStrap栅格系统、表单样式与按钮样式源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2017-01-23
- 这篇文章主要介绍了C#使用浏览按钮获得文件路径和文件夹路径的方法,结合实例形式分析了C#浏览器事件响应及文件操作相关技巧,需要的朋友可以参考下...2020-06-25
- 在淘宝等购物网站,我们都会看到一个发送短信倒计时的按钮,究竟是如何实现的呢?下面小编通过本篇文章给大家分享一段代码关于js实现手机短信按钮倒计时,需要的朋友参考下...2016-01-02
- 这篇文章主要为大家介绍了python编程使用PyQt5如何创建按钮及触发点击事件的示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步...2021-10-29
ASP.NET单选按钮控件RadioButton常用属性和方法介绍
RadioButton又称单选按钮,其在工具箱中的图标为 ,单选按钮通常成组出现,用于提供两个或多个互斥选项,即在一组单选钮中只能选择一个...2021-09-22- 这篇文章主要为大家详细介绍了jquery mobile实现可折叠的导航按钮,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2017-03-13
- 这篇文章主要介绍了微信小程序将页面按钮悬浮固定在底部的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-29
- javascript代码判断按钮是否被点击了在项目中经常会遇到这个需求,今天小编抽点时间给大家分享一段代码关于javascript判断按钮是否被点击的方法,感兴趣的朋友一起学习吧...2015-12-14
- 这篇文章主要介绍了javascript+css3 实现动态按钮菜单特效的相关资料,需要的朋友可以参考下...2016-02-12
- 这篇文章主要为大家详细介绍了vue实现自定义多选按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-07-16
- 这篇文章主要介绍了如何在.Net版本UEditor中添加一个普通按钮,需要的朋友可以参考下...2021-09-22
- 下面小编就为大家带来一篇JS判断键盘是否按的回车键并触发指定按钮点击操作的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2017-02-19
- 这篇文章主要介绍了Angular2搜索和重置按钮过场动画,需要的朋友可以参考下...2017-05-27
- 新旧MFC版本实现CEdit透明的2种方法的实例代码,需要的朋友可以参考一下...2020-04-25
- 这篇文章主要介绍了C#动态创建button按钮的方法实例详解的相关资料,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了C#动态生成按钮及定义按钮事件的方法,涉及C#按钮操作的相关技巧,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了Unity 按钮添加OnClick事件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-10
- 这是关于c#重写TabControl控件实现关闭按钮的例子,整理了一下,与大家分享。...2020-06-25