MFC的CButton类提供Windows按钮控件的功能,从CButton类派生的CBitmapButton类封装了自绘制按钮的功能,使得程序员可以通过在按钮上绘制位图并为这些位图实例化类CBitmapButton的一个拷贝来创建按钮。在绘制位图按钮时,必须先设计好按钮所在的对话框及位图按钮在对话框中所对应的标准按钮,因为位图按钮实际上是标准按钮的一种特殊情况,只是按钮上显示的信息由用户来定制,而其余的消息映射响应和更新方法均相同,所以绘制位图按钮实际上也是定制按钮上各种显示信息的过程。
下面介绍两种绘制位图按钮的基本方法:
CBitmapButton类常用的成员函数有LoadBitmaps和AutoLoad,它们均可实现位图按钮的绘制。
1.LoadBitmaps函数
原型:BOOL LoadBitmaps( LPCTSTR lpszBitmapResource,
LPCTSTR lpszBitmapResourceSel = NULL, LPCTSTR lpszBitmapResourceFocus = NULL, LPCTSTR lpszBitmapResourceDisabled = NULL );
位图按钮共有四种状态:抬起(Up),按下(Down),选中(Focused),禁止(Disabled)。
该函数的四个参数是与这四种状态相对应的位图文件名。
2.AutoLoad函数
原型:BOOL AutoLoad( UINT nID, CWnd* pParent );
该函数将一个普通按钮与一个CBitmapButton类对象联系起来。反映位图按钮四种状态的位图文件名必须以U(Up)、D(Down)、F(Focused)、X(Disabled)结尾,并且要使位图的ID标识与对话框中按钮的ID标识相对应,即如果按钮的ID标识为IDOK,那么位图的ID标识必须为OKU、OKD、OKF和OKX,这是该方法实现的关键。
上述两种方法的主要区别是,第一种方法位图资源和按钮的ID标识可以随意确定,而其代码相对来说比较复杂;第二种方法位图资源和按钮的ID标识必须统一,而其代码简单有效。
具体实现过程如下:
1.使用AppWizard生成应用程序框架
应用程序可以是基于对话框或基于文档的,本文实例是选择基于对话框的,其应用程序项目名称为BMTestDlg。
2.在对话框编辑器中编辑对话框
图1 对话框编辑结果
在对话框中增加两个按钮,设置按钮的风格为 Visible、Tab stop 和 Owner draw,其ID标识分别为IDOK和IDCANCLE,结果如图1所示。
3.在资源编辑器中建立位图资源
增加两个按钮所需的按下、抬起、选中和禁止状态对应的位图及其ID标识。在本文中共增加了8个位图,它们的ID标识分别为” ImageDown”、”ImageUp”、”ImageFocus”、
”ImgaeDis”、”CancelD”、”CancelU”、”CancelF”、“CancelX“。要注意这里的ID标识都要包含双引号,从而使得 Visual C++ 不为它们生成标识符定义语句。
4.使用CBitmapButton类对象
(1)利用LoadBitmaps函数绘制按钮
① 向CBMTestDlg类中添加成员变量:
protected:
CBitmapButton button1; //定义位图按钮
② 在CBMTestDlg类的构造函数CBMTestDlg::CBMTestDlg中添加如下代码:
//调入按钮位图资源函数
if(!button1.LoadBitmaps(_T(“ImageUp"), //按钮一所需位图
_T(“ImageDown"),_T(“ImageFocus"),
_T(“ImageDis”))) // 抬起、按下、选中和禁止
{
TRACE("Failed to load bitmap for button1\n");
AfxThrowResourceException();
}
③ 向类CBMTestDlg类的OnInitDialog成员函数中添加如下代码:
//将对话框中按钮标识与位图连接
VERIFY(button1.SubclassDlgItem(IDOK, this));
button1.SizeToContent();//使按钮大小适应位图
(2)利用AutoLoad函数绘制按钮
① 向CBMTestDlg类中添加成员变量:
protected:
CBitmapButton button2; //定义位图按钮
② 向类CBMTestDlg类的OnInitDialog成员函数中添加如下代码:
VERIFY(button2.AutoLoad(IDCANCEL,this)); //调入位图
程序运行的结果如图2所示,其中OK按钮是采用LoadBitmaps方法实现,而Cancel按钮的实现是使用了AutoLoad方法。比较这两种方法实现的过程,可以看出后者更为简单方便