[返回]
计算机世界2001年第4期
在C++Builder中创建图像按钮
福建省古田县水电局 朱丽莺 向雅
在开发程序时,程序的界面设计是一个非常重要的方面。目前有不少软件采用类似Web页面的程序界面,看起来非常友好。从这个角度讲,在界面中使用Windows标准按钮就显得不怎么“好看"了,它需要更加图像化的按钮。
本文介绍在C++Builder中编写的一种图像按钮:按钮在通常情况下是静止的;当用户移动鼠标进入按钮所在区域时,按钮开始显示动画;当用户把鼠标从按钮上移开时,按钮的动画停止。该按钮还有其他的用户响应事件,比如,鼠标按下和弹起时,按钮的图像发生变化等等。
增加属性方法
__property TImageList* FrameList = {read=FFrameList, write=SetFrameList};
用来保存按钮所需的各幅图像。
__property int FrameLeave = { read=FFrameLeave, write=SetFrameLeave};
用来控制图像按钮的正常图像帧。
__property int FrameStart = { read=FFrameStart, write=FFrameStart};
用来控制图像按钮的动画的起始帧。
__property int FrameEnd={read=FFrameEnd, write=FFrameEnd};
用来控制图像按钮的动画的末尾帧。
__property int FrameInterval={read=FFrameInterval, write=SetFrameInterval, default=250};
用来控制动画的时间间隔。
定义辅助变量
TImageList* FFrameList; //用来控制图像列表
int FFrameLeave; //用来控制正常图像帧
int FFrameStart; //用来控制动画起始图像帧
int FFrameEnd; //用来控制动画末尾图像帧
int FFrameInterval; //用来控制动画事件间隔
TTimer* FTimer; //控制动画的定时器
int FCurFrame; //当前帧辅助变量
编写访问方法
//设置图像
void __fastcall TxyImage::SetBitmap(int CurFrame)
{
if (FFrameList !=NULL)
{
FFrameList->GetBitmap(CurFrame,Picture->Bitmap);
Paint();
}
}
//设置鼠标进入的图像帧
void __fastcall TxyImage::SetFrameEnter(int Value)
{
if(FFrameEnter != Value)
{
FFrameEnter = Value;
}
}
//设置鼠标移出的图像帧
void __fastcall TxyImage::SetFrameLeave(int Value)
{
if(FFrameLeave != Value)
{
FFrameLeave = Value;
SetBitmap(FFrameLeave);
}
}
//设置图像的标签控件
void __fastcall TxyImage::SetLabel(TLabel* value)
{
if (FLabel != value)
{
FLabel = value;
FLabel->Font->Size = 12;
FLabel->Font->Name = “黑体";
FLabel->Font->Color = clBlue;
FLabel->Transparent = true;
if (FLabelLayout)
FLabel->Left = Left + Width + 5;
else
FLabel->Top = Top + Height + 5;
}
}
//设置图像控件的标题
void __fastcall TxyImage::SetCaption(AnsiString value)
{
if(FCaption != value)
{
FCaption = value;
if (FLabel != NULL)
{
FLabel->Caption = FCaption;
}
}
}
//用于控制动画帧的图像控件的定时器事件。本例只是简单地使用TTimer控件,并且在定时器事件处理函数中改变动画的帧
void __fastcall TxyImage::OnTimer(TObject* Sender)
{
FCurFrame ++;
if (FCurFrame>FrameEnd)
{
FCurFrame=FrameStart;
}
SetBitmap(FCurFrame);
}
当然,也可以不使用TTimer控件,而直接使用API函数SetTimer和KillTimer,来触发动画帧控制消息WM_TIMER,并且通过重载控件的窗口过程函数WndProc,来处理WM_TIMER消息。如果机器处理能力足够强,而且要求更高精度的时间间隔控制,那么可以通过利用API函数GetTickCount,使用自定义消息来进行控制。
本例中使用图像列表控件来控制各个图像帧,正常的和动画的各帧图像都保存在图像列表控件中,通过直接使用TImageList的方法GetBitmap得到所需的图像。当然也可以直接使用TImage的Picture成员来进行图像控制,处理过程大致如下:把按钮所需的全部图像构成一个整幅图像,首先放在Picture成员中保存起来,然后根据需要的图像帧进行图像剪切,得到所需的图像后,传递给Picture成员,并且通知控件重画,从而完成图像处理。
处理鼠标消息
//鼠标进入事件
void __fastcall TxyImage::CMMouseEnter(Messages::TMessage & Message)
{
//判断按钮所在窗口是否活动
if (GetParentForm(this)->Active)
{
if (FFrameList != NULL)
{
//显示动画的开始帧
SetBitmap(FFrameStart);
FCurFrame=FFrameStart;
//打开定时器
FTimer->Enabled=True;
}
if (FOnMouseEnter != NULL)
FOnMouseEnter;
}
}
//鼠标移出事件
void __fastcall TxyImage::CMMouseLeave(Messages::TMessage &Message)
{
//判断按钮所在窗口是否活动
if (GetParentForm(this)->Active)
{
if (FFrameList != NULL)
{
FTimer->Enabled=False;
SetBitmap(FFrameLeave);
FLabel->Font->Color=clBlue;
if (FLabelLayout)
FLabel->Left=Left+Width+5;
else
FLabel->Top=Top+Height+5;
}
if (FOnMouseLeave != NULL)
FOnMouseLeave;
}else//按钮所在窗口不活动时的处理
{
if (FTimer->Enabled)
{
if (FFrameList != NULL)
{
FTimer->Enabled=False;
SetBitmap(FFrameLeave);
}
if (FOnMouseLeave != NULL)
FOnMouseLeave;
}
}
}
需要注意的是:C++ Builder和Delphi处理鼠标移入、移出时的消息处理函数使用的消息,通常不是标准的Windows消息,它与Windows消息WM_MOUSEHOVER和WM_MOUSELEAVE有所区别,前者处理的范围要比后者要大。比如说,即使应用程序窗口不是活动的,这个应用程序也能获得CM_MOUSEENTER和CM_MOUSELEAVE,但是不能获得标准的Windows消息WM_MOUSEHOVER和WM_MOUSELEAVE。