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实现的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • MFC实现漂亮界面之美化按钮

    上次我们学习了如何美化对话框的界面,这次我们为上次的对话框添加两个按钮,一个是关闭按钮,另一个是最小化按钮,好,现在我们先看一下效果: 是不是很难看,因为我们的对话框美化了,所以我们的按钮也要美化,因为采用贴图的方式来美化,所以,我先给出这两个按钮的PNG格式的图片,该图片支持透明色,具体如下: 关闭按钮效果图: 最小化按钮效果图: 这两张效果图是我自己从网上找的,可能不是很合适,但是用来教学,完全没有问题,它们的尺寸都是108*21,每张图片都有四个小图片,第一张和第四张小图片都是透明的,所以

  • MFC自绘Button按钮分析和实现

    对于按压式的Button按钮,WM_CTLCOLOR无法完成按钮控件的背景颜色和字体颜色修改,若想要完成外观定制需要添加WM_DRAWITEM消息或者重写CButton类中的DrawItem函数完成按钮外观修改,下面逐一介绍. 自绘制知识基础 自绘制需要的两个基础步骤: 1.控件类型设置为 BS_OWNERDRAW 2.添加WM_DRAWITEM消息响应函数或者重写DrawItem函数. WM_DRAWITEM消息响应原型如下: afx_msg void OnDrawItem( int nIDC

  • MFC中Radio Button的用法详解

    本文通过针对两个常见问题的解决方案,详细阐述了MFC中Radio Button的用法.有助于读者加深对于MFC运行机制及Radio Button控件用法的理解. 首先为对话框加上2个radio button,分别是Radio1和Radio2. 问题1:如何让Radio1或者Radio2默认选上?如何知道哪个被选上了? 关键是选上,"默认"只要放在OnInitDialog()即可.有如下的三种方法可以让它选上: 第一种: ((CButton *)GetDlgItem(IDC_RADIO1

  • WPF中button按钮同时点击多次触发click解决方法

    解决WPF中button按钮同时点击多次触发click的方法,供大家参考,具体内容如下 DateTime lastClick = DateTime.Now; object obj = new object(); int i = 0; private void Button_Click(object sender, RoutedEventArgs e) { this.IsEnabled = false; var t = (DateTime.Now - lastClick).TotalMillise

  • Android编程实现长按Button按钮连续响应功能示例

    本文实例讲述了Android编程实现长按Button按钮连续响应功能.分享给大家供大家参考,具体如下: 在电商类app的购物车页面,经常会有这样的需求:长按"+"按钮或者"-"按钮时,购物车中的商品数量连续的增加或减少. 本例的目的就是为了实现这个效果.预览图: 1.自定义Button. /** * 长按连续响应的Button * Created by admin on 15-6-1. */ public class LongClickButton extends

  • JavaScript在form表单中使用button按钮实现submit提交方法

    submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了,submit和button,二者都以按钮的形式展现,看起来都是按钮,所不同的是type属性和处发响应的事件上. 在javaScript中关于submit和button的区别介绍 在form表单提交中,使用button来间接完成submit的提交更为灵活.下面是实现方法: 使用button按钮实现submit提交,需要在button标签中的使用onclick方法,然后在JavaScript中实现具体,代码如下

  • JS button按钮实现submit按钮提交效果

    今天在使用表单是同时使用POST更新.删除操作.然而form表单的 submit 且一旦提交则全部提交,所以想到的实现方法就是 使用button实现,代码实现见如下: form设置: <form method="post" name="linkform"> 隐藏的act方法设置,代码如下: <input name="act" type="hidden" /> 最后关键的是 button的设置,更新按钮,

  • C#动态创建button按钮的方法实例详解

    C#动态创建button按钮的方法实例详解 C#编程中经常需要动态创建,本文主要介绍C#动态创建button按钮的方法,涉及C#按钮属性动态设置的相关技巧,以供借鉴参考.具体实现方法如下: 例子: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.T

  • Android实现圆角Button按钮

    本文实例讲述了Android开发圆角Button按钮实现过程,分享给大家供大家参考,具体内容如下 需求及效果图: 实现思路: 1.shape实现圆角 在drawable新建两个xml 文件, 这两个 xml文件用shape 实现了圆角效果. Note: 因为要让用户有按下去的效果体验, 所有要有两套圆角图, 在按下去时候切换 <!-- res/drawable/button_shape_normal.xml --> <shape xmlns:android="http://sc

  • jQuery Mobile中的button按钮组件基础使用教程

    一.Button 组件及 jQuery Mobile 如何丰富组件样式 在 jQuery Mobile 里,可以通过给任意链接添加 data-role="button" 来产生一个 button 组件,jQuery Mobile 会追加一定的样式到链接,值得注意的是,jQuery Mobile 在给组件元素追加样式时不一定只在原有的元素上添加 CSS 和 Javascript 响应,一般还会追加一些新的元素使到组件的样式更接近于原生的 App 组件样式.下面给出一个例子: 这是一个添加

  • EXT中单击button按钮grid添加一行(光标位置可设置)的实例代码

    先给大家说下什么是ext ext是一个强大的js类库,以前是基于YAHOO-UI,现在已经完全独立了, 主要包括data,widget,form,grid,dd,menu,其中最强大的应该算grid了,编程思想是基于面向对象编程(oop),扩展性相当的好.可以自己写扩展.自己定义命名空间.web应用可能感觉太大.不过您可以根据需要按需加载您想要的类库就可以了. 主要包括三个大的文件ext-all.css,ext-base.js,ext-all.js(包括所有的类库,您可以根据需要进行删减.官方网

随机推荐