图标按钮、位图按钮、CBitmapButton 类位图按钮的制作

来源:互联网 发布:万网域名过户流程 编辑:程序博客网 时间:2024/05/09 03:56
★5--2--1 图标按钮

图标按钮可谓是按钮控件使用图像最简单的方式,除此之外图标按钮的优点还在于显示在按钮上的图标能够使用透明色,因而不必再去为处理非矩形图像在按钮颜色发生变化时边缘颜色的处理而费心。不过也正是使用图标导致了图标按钮的天生弱点。图标太小了,仅仅才 32×32 像素大小,在有的场合仅靠使用这么小的图像就有些显得力不从心了。

在讲图标按钮如何使用之前,先得告诉读者句柄的概念。句柄是什么?很多教科书上都这样定义:句柄是一个用于代表对象的 32 位整型值。不过这对于很多初学者而言,并不是太好理解。其实也可以将未赋值的句柄理解为一个指向“空白”(void *)的指针,事实上也如此,在 Winnt.h 中,句柄就是如此被声明的:typedef void *HANDLE; 当句柄被赋值之后,它就成为指向某个特定位置的指针,即代表了某个特定的对象。之所以在现在提及句柄,是因为句柄是 Windows 编程中的一个关键性概念。尽管在前面除第三章外的内容中很少涉及它,不过在下面的学习中我们将会很频繁的使用到句柄。

技术概要:
使用图标按钮很简单,大的步骤仅仅就三步:
①.从外部导入一个图标或自己创建一个图标作为资源。
②.从资源中载入所要使用的图标。
③.在要使用图标的按钮上设置图标。

具体实现:
■第一步导入图标没有什么特别之处,同前面 2.2 节中使用静态图像控件导入位图是非常类似的。无非就是使用 Insert 菜单上的 Resource 命令,导入或创建一个图标即可。

■第二步载入图标就涉及到一些细节问题了。使用函数 LoadIcon() 载入图标。因为LoadIcon() 是类 CWinApp 的成员函数,同时函数 LoadIcon() 返回所载入图标的句柄。所以我们采用以下方法来调用函数 LoadIcon():
h_Icon = AfxGetApp() -> LoadIcon(IDI_Icon);
  当然,在该语句之前还必须要有对图标句柄 h_Icon 的定义:
            HICON h_Icon;

■第三步为按钮设置图标了,这通过调用函数 SetIcon() 来实现。同时不要忘记,还须在使用图标的按钮的 Properties 设置中设置 Icon 属性,指明该按钮是一个图标按钮。因为函数 SetIcon() 为类 CButton 的成员函数,可以通过两种方法来调用该函数。一是通过 CButton 类对象来调用 SetIcon(),如下面代码:
         m_BtonIcon.SetIcon(h_Icon);   // m_BtonIcon 为一个 CButton 类对象。
  二是先由函数 GetDlgItem() 获得一个指向 CWnd 对象的指针,再通过强制类型转换将该指针转换为一个指向 CButton 类对象的指针。进而通过该指针来调用函数 SetIcon()。具体实现代码如下:
         CWnd *pWnd =  GetDlgItem(IDC_RADIO2);
       CButton *pBton = (CButton *) pWnd;
         pBton -> SetIcon(h_Icon2);
  既然有第一种较为简便的方法为按钮设置图标,为何还要提及第二种方法呢?因为并不是在任何情况下都会有 CButton 类对象的,例如对于一组单选按钮。只能为它们定义一个 CButton 类对象,如果使用该对象来调用函数 SetIcon(),则只能在设置了 Group 属性的那个单选按钮上设置图标。所以要达到在一组单选按钮中分别设置不同图标的目的,就只有使用第二种方法。

    尽管在现在的 Windows 编程中,资源句柄数多得相对于我们而言几乎是无限的,但最好在使用完资源句柄后及时的把它们删除掉。上面所讲述的方法不仅适用于 Push Button,而且同样适用于 Radio Button、Check Box 和 Group Box。


★5--2--2 位图按钮

图标按钮虽有着种种优点,但它能显示的图像实在是太小了。在有的场合显然就不适用了。位图按钮可以在按钮表面显示一幅位图而不再是一个小小的图标。但是因为在位图中不能使用透明色,因而当显示的位图不为矩形时,就得为位图中非矩形部分的背景色动一番脑筋了。因为存在着用户改变按钮表面颜色,也就是位图背景色的可能性。可以用透明位图的技术来解决这一难题,这将在后面 5.7 实现具有透明性的位图中讲述。

技术概要:
位图按钮的使用的大致步骤同图标按钮基本相似,也是以下三个步骤:
①从外部导入一个位图或自己创建一个位图作为资源。
②从资源中载入所要使用的位图。
③在要使用位图的按钮上设置位图。

具体实现:
    ■第一步从外部导入一个位图作为资源同使用图标按钮时是完全一致的,在此就不详细讲述了。

    ■第二步中,利用函数 LoadBitmap() 从资源中载入位图。函数 LoadBitmap() 为一个 API 函数,定义如下:
HBITMAP LoadBitmap(
HINSTANCE hInstance, // handle of application instance
LPCTSTR lpBitmapName // address of bitmap resource name
);
所以,为达到载入位图的目的,不仅要定义一个位图句柄 hBitmap:
             HBITMAP hBitmap;
而且还要定义一个应用程序实例句柄 hInstance;:
             HINSTANCE hInstance;
并调用函数 AfxGetInstanceHandle() 以获得当前的应用程序实例句柄,代码如下:
hInstance = ::AfxGetInstanceHandle();
只有在声明并获得了当前的应用程序句柄后,才能使用以下语句载入位图:
hBitmap = ::LoadBitmap(hInstance,"BMP1");
注意,在函数 LoadBitmap() 中的第二个参数为资源名,而非资源 ID。因为资源名是一个字符串,而资源 ID 则是一个整型量。所以在创建或导入位图后,为该位图资源命名时要加上双引号以表示这是一个资源名。如右图 5-2:

■在第三步中,为要使用位图的按钮设置位图,方法与图标按钮完全相同。首先是要在使用位图的按钮的 Properties 设置中设置 Bitmap 属性,指明该按钮是一个位图按钮。然后再调用 CButton 类函数 SetBitmap() 为按钮设置位图。代码如下:

  // m_BtonBmp 为一个 CButton 类对象。
  m_BtonBmp.SetBitmap(hBitmap);
  或
  pWnd =  GetDlgItem(IDC_Check);
  pBton = (CButton *) pWnd;
  pBton -> SetBitmap(hBitmap);

    同图标按钮一样,使用位图不局限于 Push Button,而且同样适用于 Radio Button、Check Box 和 Group Box。同时,最好在使用完位图句柄后及时的将它删除掉。


★5--2--3 CBitmapButton 类位图按钮

前面所讲述的图标及位图按钮最大的不足在于,无论当按钮控件处于何种状态,按钮上所显示的图案总是一成不变的,相比之下那些随着操作而实时改变图案的按钮就具有更加生动的效果。MFC 库为我们捉供了一个这样的类 CBitmapButton。利用这个类,我们可以为一个按钮设计四幅不同位图、分别用于正常状态、按下状态、获得输入焦点和无效时。这样,随着按钮状态的改变,位图也随之切换,这样就使按钮呈现出很强的动感效果。令人高兴的是,类 CBitmapButton 将很多操作的细节都封装了起来,因而我们能够很方便的达到上述目的。由于以上原因,CBitmapButton 类位图按钮有着比图标按钮和位图按钮更为广阔的使用范围。在一般情况下,都将 CBitmapButton 类位图按钮称作是位图按钮,而将真正的位图按钮给忽略了。
CBitmapButton 类位图按钮的缺点同位图按钮是一致的,都是在对透明色的处理上。还有一个比较严重的问题是 CBitmapButton 类位图按钮是将位图按原始大小绘制在按钮上,而不是随按钮大小而缩放位图。这在平时不会导致任何问题,但若是在 Windows 中更改了显示字体的大小,则对话框及上面的按钮控件大小也随之改变,但位图按钮上的位图却保持原有大小不变,这样就会在外观上造成严重的问题。尽管有以上问题的存在,CBitmapButton 类位图按钮还是具有很大的实用价值,因为付出很少的代码就可以得到生动形象的图形效果。、下面就讲述 CBitmapButton 类位图按钮的使用方法(以下均简称为位图按钮)。
绝大数情况下,使用位图按钮只需四个步骤:

●第一步:在要使用位图的按钮的 Properties 设置中设置 Owner Draw 属性

●第二步:创建或从外部导入至少一幅至多四幅位图。位图按钮所使用的位图颜色最多可达 256 色,但对于 256 色的位图不能通过剪贴的的方式来创建。而必须使用导入的方式来创建。若该按钮控件的 Caption (标题)为 BmpBton,则将这四幅位图的 ID 分别设定为 “BMPBTONU”、“BMPBTOND”、“BMPBTONF”、“BMPBTONX”分别对应于按钮的正常状态、按下状态、获得输入焦点状态和无效状态。注意,只有在正常状态显示的位图是必须的,其它状态的位图都是可选的;还有就是代表位图的 ID 都必须加上双引号并且大写(如下图 5-3)。实际上,加上双引号就表示该资源是以字符串常量来标识。








●第三步:在使用位图按钮的类的类定义文件中声明 CBitmapButton 类对象:CBitmapButton m_BtonSet;

●第四步:在对话框的 OnInitDialog() 函数中通过 CBitmapButton 类对象调用函数 AutoLoad() 自动加载位图: m_BtonSet.AutoLoad(IDC_BtonSet,this);

经过以上四个步骤,一个位图按钮就创建好了。在运行中,CBitmapButton 类会自动根据按钮的状态显示对应的位图。利用位图按钮技术,再加上一点鼠标感应技术,就很容易做出像网页按钮那样的在鼠标经过时加亮的动态效果。也能轻易的实现像 Word 中那样的平面按钮。这些将在后面的章节中讲述。
需要说明的是,CBitmapButton 类位图按钮仅限于在 Push Button 使用。在默写情况下,我们可能需要动态创建位图按钮,在动态创建位图按钮时,不能使用函数 AutoLoad() 加载位图,而要使用函数 LoadBitmaps() 来加载位图。动态创建位图按钮主要有以下几个步骤:
    ●第一步:为要创建的控件分配一个 ID 值。
    ●第二步:定义一个 CBitmapButton 类对象。
    ●第三步:由该对象调用函数 Create() 创建位图按钮,并调用函数 LoadBitmap() 加载位图。在调用函数 SizeToContent() 调整按钮控件的大小以适应位图。
●第四步:加入对新创建按钮的消息处理。