其他语言

位置:IT落伍者 >> 其他语言 >> 浏览文章

特效处理:Delphi中制作特效菜单


发布日期:2023年09月23日
 
特效处理:Delphi中制作特效菜单
菜单是应用程序中常见的用户界面之一Delphi具有功能强大的菜单设计器可以很快地实现标准的菜单但有时候应用程序需要实现特定类型的菜单我们常用的如金山毒霸的弹出式菜单就是一例可以在菜单项里显示自己定义的图片自己设置的文字以及自设置的菜单项大小这种菜单称为自绘制菜单(Ownerdraw MenuItem)当然功能不止于此我们还可以实现更好的菜单下面就一起来做一个显示大图片和大文字的菜单吧!

程序思路

Delphi在绘制每个菜单时采用一个比较独特的方法首先Delphi会通过菜单的OwnerDraw属性来判定在菜单中是否允许自绘制菜单若OwnerDraw属性为真(TRUE)则Delphi首先会触发每个菜单项的OnMeasureItem事件来获取自绘制菜单项的大小(WidthHeight)然后触发OnDrawItem事件允许用户在这里绘制自己的菜单

实现菜单

第一步创建一个新的项目并添加相应的组件

启动Delphi新建一个应用此时出现一个窗体将其Name属性改为frmSample添加一个弹出式菜单到窗体frmSample并将此菜单Name属性设置为mnuOwnerDraw

设置窗体frmSample的PopupMenu属性为mnuOwnerDraw这时运行程序你会发现除了弹出式菜单仍然显示为空的菜单继续往窗体上添加一个TactionList对象双击以设计这一ActionList对象往其中增加一个Action对象并设置其Name属性为actSample往窗体上放置一个Label对象其Name属性为Label调整Label的字体大小以便在利用Label显示数据时可以清楚地观察到

现在往程序的变量声明部分(VAR)添加要用到的声明

ePic:TPicture;//用于装载程序要用到的图像

miSample:TMenuItem; //菜单项的声明用于动态生成菜单项

I:integer;//当多次右击键时记录右单击次数从而生成不同的菜单项

首先在程序的初始化部分初始化击键次数为

initialization

i:=;

第二步实现OnMeasureItem和OnDrawItem

往窗体frmSample的实现(Implementation)部分添加如下过程声明

AMeasureItem (Sender: TObject; ACanvas: TCanvas; var Width Height: Integer);

ADrawItem (Sender: TObject; ACanvas: TCanvas; ARect: TRect;Selected: Boolean);

往往手工输入比较麻烦比较现实的做法是利用菜单设计器添加一个菜单项设置其Name属性为A然后选择OnMeasureItem和 OnDrawItem事件双击即可Delphi会为你自动输入如上代码

往AMeasureItem中添加如下代码

Begin

Width: =; //设置菜单项的宽度

Height: =; //设置菜单项的高度

End;

往ADrawItem中添加如下代码

Begin

If I= then

begin

ePic:=TPictureCreate;//创建一个用于装载图片的Tpicture对象

ePicLoadFromFile(abmp);//从项目所在目录装载图片

acanvasDraw(arectLeftarectTopePicGraphic);//将图片在菜单项中绘制出来

acanvasFontSize:=;//设置菜单项的字体大小

acanvasFontColor:=clPurple; //设置菜单项字体颜色

acanvasTextOut(arectLeft+arectTop+A ); //在菜单项中输出文字A

end;

if i= then

begin

ePic:=TPictureCreate;//创建一个用于装载图片的Tpicture对象

ePicLoadFromFile(bbmp);//从项目所在目录装载图片

acanvasDraw(arectLeftarectTopePicGraphic);//将图片在菜单项中绘制出来

acanvasFontSize:=;//设置菜单项的字体大小

acanvasFontColor:=clblue;//设置菜单项字体颜色

acanvasTextOut(arectLeft+arectTop+B);//在菜单项中输出文字A

end;

if i= then

begin

ePic:=TPictureCreate;

ePicLoadFromFile(cbmp);

acanvasDraw(arectLeftarectTopePicGraphic);

acanvasFontSize:=;

acanvasFontColor:=clred;

acanvasTextOut(arectLeft+arectTop+C);

end;

End;

下面我们实现菜单项的在被单击时的行为即实现actSample对象的OnExcute事件如下所示

actSampleExecute(Sender: TObject);

begin

labelCaption:=inttostr(i);

end;

第三步将菜单项动态添加到菜单中

I:=I+;//计算程序中的击键次数

miSample:=TMenuItemCreate(form);//动态创建菜单项

miSampleOnClick :=actSampleOnExecute; //为菜单项添加动作

miSampleOnDrawItem := ADrawItem; //为菜单项设置显示方式

miSampleOnMeasureItem := aMeasureItem; //为菜单项设置大小

mnuOwnerDrawItemsInsert(miSample);//将菜单项添加到菜单中

程序效果

现在可以应用程序了你会发现只要你在窗体上单击右键窗体会有一个弹出式菜单显示出来而且每一个菜单项都随着右键单击次数的不同而不同当次数大于菜单显示为一系列的空菜单项但是不论何时你单击任何一个菜单项Label的都会显示你当前的右键在窗体上单击的次数值

程序加强

如果我们在程序中为我们所动态创建的每一个菜单项都实现不同的OnMeasureItem和OnDrawItem事件的话那么每一个菜单项都有自己的大小处理与显示处理那我们就可以实现一些更好的功能例如可以实现大小不同的菜单项第一个菜单项可以比较小以后的菜单项可以比较大同样还可以在一些菜单中实现更好的功能每个菜单显示自己图标和特定字体的文字

但是利用这种方法制作自定义菜单的功能还是受到了一定的限制我们只能对OnAdvancedDrawItemOnClickOnDrawItemOnMeasureItem等有限几个事件作出反应并对菜单项进行定制我们没有办法对鼠标事件作出反应利用鼠标事件当鼠标滑过菜单项时我们可以实现诸如加亮渐变或其他的菜单项显示技术显然这是十分有意义的

要实现上述技术我们需要从TcustomMenuItem中继承并定义一个新类并重新声明OnMouseMove事件并给出实现诸如加亮或渐变等技术的代码即可

上一篇:Delphi组件撰写常问问题分析

下一篇:Delphi中用TDD:一个简单的实现