动态加载CBitmapButton的四副状态图 2010-11-8 13:49

来源:互联网 发布:阿里云 电商解决方案 编辑:程序博客网 时间:2024/05/16 07:48

一、CBitmapButton存在的问题
在MFC中,要使用图形按钮,一般会选择CBitmapButton类,使用CBitmapButton类可以设置按钮的Normal、Selected、Focused和Disabled四种状态的bmp图像,这四副状态图像要求同尺寸大小,其中normal状态图片是必需提供的。常见调用代码示例:

    CBitmapButton m_bmpBtn;    m_bmpBtn.SubclassDlgItem(IDC_BUTTON1,this);//关联控件    //CBitmapButton对象m_bmpBtn的LoadBitmaps函数加载程序内bmp资源。    m_bmpBtn.LoadBitmaps(IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4);    m_bmpBtn.SizeToContent();

遗憾的是:上述代码中LoadBitmaps函数只可以加载程序内部bmp资源文件,不可以加载磁盘图像文件,但有时我们又急需更改CBitmapButton 对象的按钮状态图,比如界面皮肤动态切换时,就有可能碰到这种情况。如何才能让CBitmapButton 对象动态加载状态图像呢?这里给出一个解决方案。

二、解决思路分析
通过分析CBitmapButton发现,其四种状态图保存在四个CBitmap类型的成员变量中,其定义如下:

class CBitmapButton : public CButton{....protected:// all bitmaps must be the same sizeCBitmap m_bitmap;           // normal image (REQUIRED)CBitmap m_bitmapSel;        // selected image (OPTIONAL)CBitmap m_bitmapFocus;      // focused but not selected (OPTIONAL)CBitmap m_bitmapDisabled;   // disabled bitmap (OPTIONAL)...} 

由于CBitmapButton的protected属性成员变量普通外部函数无法直接访问,因此我们定义一个其public继承类CGetBitmaps,从而可以访问这四个成员变量,CGetBitmaps类定义如下:

class CGetBitmaps : public CBitmapButton{    CBitmapButton *btn;public:    CGetBitmaps(CBitmapButton *button)    {        btn=button;    }    inline CBitmap * Nor(){ //normal image (REQUIRED)        return (CBitmap *)(PCHAR(btn)+(ULONG)(PCHAR (&m_bitmap)-PCHAR(this)));//not PTCHAR, butPCHAR    }    inline CBitmap * Sel(){ // selected image (OPTIONAL)        return (CBitmap *)(PCHAR(btn)+(ULONG)(PCHAR (&m_bitmapSel)-PCHAR(this)));//not PTCHAR, butPCHAR    }    inline CBitmap * Foc(){ // focused but not selected (OPTIONAL)        return (CBitmap *)(PCHAR(btn)+(ULONG)(PCHAR (&m_bitmapFocus)-PCHAR(this)));//not PTCHAR, butPCHAR    }    inline CBitmap * Dis(){ // disabled bitmap (OPTIONAL)        return (CBitmap *)(PCHAR(btn)+(ULONG)(PCHAR (&m_bitmapDisabled)-PCHAR(this)));//not PTCHAR, butPCHAR    }};

增加了四个inline函数用来得到四副状态图对应的保存地址。在保持原CBitmapButton对象的不变情况下,我提供一个普通函数BOOL ChangeBitmapBtnImages(CBitmapButton &button,LPCTSTR lpszFilename)来更改CBitmapButton对象的按钮状态图,该函数接受一个CBitmapButton引用对象和一个四状态组合的bmp磁盘文件路径名,如果成功设置返回TRUE,否则FALSE,该函数定义的核心代码如下(详细请看示例源代码中changeBmp.cpp文件):

BOOL ChangeBitmapBtnImages(CBitmapButton &button,LPCTSTR lpszFilename)// {...HBITMAP hbm = (HBITMAP) ::LoadImage (NULL, lpszFilename, IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);//动态加载磁盘bmp文件if (hbm == NULL){return FALSE;}src.Attach(hbm);...CGetBitmaps gbitmap(&button);//这里调用我们的定义类CBitmap * pbitmap[4];...BOOL Rz=TRUE;for(int i=0;i<4;i++) //分割四副状态图{pbitmap[i]->CreateCompatibleBitmap(&srcDC,bmpWidth,bmpHeight);   memDC.SelectObject(pbitmap[i]);   if(   !memDC.BitBlt(0,0,bmpWidth, bmpHeight, &srcDC,bmpWidth*i,0,SRCCOPY)  ) {Rz=FALSE;break;}}...return Rz;}

三、代码示例
为了更好的理解,本文提供示例源代码程序,运行界面如“图一”。程序开始时,界面中的图形按钮加载了程序内部资源中的四副bmp状态图,可以点击下面的“动态加载bmp文件”按钮来选择磁盘上一个四副状态组合的bmp图,加载成功以后图形按钮的按钮状态图将被更改,再单击图形按钮将看到状态图已经更改的效果。


图一 示例程序运行效果图

四、结束语
对于ChangeBitmapBtnImages函数,这里把它当成一个独立普通函数使用,当然也可以把它稍加修改放到CGetBitmaps中当成员函数使用,另外这里的ChangeBitmapBtnImages加载的bmp磁盘文件是四种状态组合的单个bmp文件,在此程序的基础上读者可以很容易的把它修改成加载四副单独按钮状态的程序。

在此谢谢作者

原创粉丝点击