之前很长一段时间,在做界面中的自绘按钮时,都是通过将控件子类化的办法,
切换按钮贴图来完成按钮的一些动画效果。但是,后来慢慢发现,每次做程序
界面画一个按钮都需要将按钮子类化,按钮多了过程就繁重,代码重复性也很
高,于是就想了个办法,将其封装成一个类,以后再做自绘按钮的时候 只要载
入这个类,调用一个函数,就可以完成按钮的动画效果,现在贴出来大家分享下,
如果觉得方便您可以自己建一个头文件,把代码放进去,每次程序调用该头文件
就可以轻松完成按钮的自绘。
代码如下:
/********************************************************************
** 定义自绘按钮类. **
** DrawBtn类,允许用户自己绘制自己所要的按钮外观,如载入按钮表面贴图, **
** 当鼠标在按钮上和离开按钮时候两种情况下的按钮外观.让按钮具有多样化 **
** 外观,使界面更加人性化. **
********************************************************************/
//调用所需头文件
#ifndef WINDOWS_H
#define WINDOWS_H
#include <Windows.h>
#endif
class DrawBtn
{
public:
//类构造函数
DrawBtn(HWND hwndOfParent):
hwnd(hwndOfParent){}
//创建按钮函数
HWND CreateDrawButton(int uIdOfOnButton, //鼠标在按钮上显示的图片
int uIdOfOffButton, //鼠标离开按钮显示的图片
int xofposition, //按钮在父窗口的X坐标
int yofposition, //按钮在父窗口的Y坐标
int xofsize, //按钮的宽度
int yofsize, //按钮的高度
int IdOfButton) ; //按钮ID
private:
//私有成员变量定义
HWND hwnd ; //父窗口句柄
int uID_OnButton ; //鼠标在按钮上时,绘制的贴图
int uID_OffButton ; //鼠标离开按钮时,绘制的贴图
//私有成员函数定义
static LRESULT CALLBACK ButtonProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) ;
void MakeTheEffectButton(HWND hwnd) ;
};
/*************************************************
** 定义一个静态变量指针,因为回调函数在类中调用如果 **
** 不定义为static,则会隐含有this指针,返回的参数和 **
** 地址都有问题,定义为static就能锁定地址和参数。 **
** 而再一个静态的成员函数中调用非静态的变量,我们要 **
** 变量也为静态,但是变量为静态就不能接受用户给定的 **
** 值,因此我们定义一个静态的类类型指针,并为其申请 **
** 内存空间,用静态的类类型指针来引用非静态的变量, **
** 就可以使非静态的变量在静态成员中使用。 **
*************************************************/
static DrawBtn* pthis = (DrawBtn*)malloc(sizeof(int)*2) ;
//返回上一个回调函数
WNDPROC OldButtonProc ;
HWND DrawBtn::CreateDrawButton(int uIdOfOnButton, int uIdOfOffButton,
int xofposition, int yofposition, int xofsize, int yofsize, int IdOfButton)
{
//在父窗口创建按钮,并获得按钮句柄用于函数返回.
HWND hwndofButton ;
hwndofButton = CreateWindow(TEXT("button"),TEXT(""),WS_CHILD | WS_VISIBLE | BS_BITMAP | BS_DEFPUSHBUTTON,
xofposition, yofposition, xofsize, yofsize,
hwnd, (HMENU)IdOfButton, (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), NULL) ;
pthis->uID_OnButton = uIdOfOnButton ;
pthis->uID_OffButton = uIdOfOffButton ;
//载入按钮初始化界面.即为鼠标离开按钮时候的界面.
HBITMAP hBitmap ;
hBitmap = LoadBitmap((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), MAKEINTRESOURCE(pthis->uID_OffButton)) ;
SendMessage(hwndofButton, BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)hBitmap);
//载入按钮检测鼠标界面.
MakeTheEffectButton(hwndofButton) ;
return hwndofButton ;
}
LRESULT CALLBACK DrawBtn::ButtonProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
static BOOL bIsOnButton = FALSE;
switch(uMsg)
{
case WM_MOUSEMOVE:
{
if(!bIsOnButton)
{
//定义结构体,用于返回鼠标按钮事件.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER|TME_LEAVE;
tme.hwndTrack = hwnd;
tme.dwHoverTime = 1;
TrackMouseEvent(&tme);
}
}
break;
case WM_MOUSEHOVER:
{
//鼠标在按钮上时.
bIsOnButton = TRUE;
HBITMAP hBmpOn = LoadBitmap((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
MAKEINTRESOURCE(pthis->uID_OnButton));
SendMessage(hwnd,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)hBmpOn);
break;
}
case WM_MOUSELEAVE:
{
//鼠标离开按钮时.
bIsOnButton = FALSE;
HBITMAP hBmpOff = LoadBitmap((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
MAKEINTRESOURCE(pthis->uID_OffButton));
SendMessage(hwnd,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)hBmpOff);
break;
}
}
return CallWindowProc(OldButtonProc,hwnd,uMsg,wParam,lParam);
}
void DrawBtn::MakeTheEffectButton(HWND hwnd)
{
OldButtonProc = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,(LONG)ButtonProc);
}
然后再MAIN函数中,你只要下面两句代码就能创建一个具有动画效果的按钮:
DrawBtn drawbtn(hwnd) ; //调用DrawBtn类,并为其创建对象,初始化载入一个父窗口句柄。
//改函数返回按钮句柄,IDB_BITMAP1和 IDB_BITMAP2是你希望鼠标在按钮上和离开按钮时候按钮的图片,需要你自己载入.
drawbtn.CreateDrawButton(IDB_BITMAP2,IDB_BITMAP1,220,20,40,20,ID_BUTTON) ;
如果是VC6.0的用户,你可以需要自己再添加一些头文件和库文件,因为TRACKMOUSEEVENT结构只有在VS2010里面才是编译器自动载入的. 百度上有将得很详细载入什么库文件和头文件,这里我就不多说,也是只要两行代码。