菜單是應用程序中常見的用戶界面之一
Delphi具有功能強大的菜單設計器
可以很快地實現標准的菜單
但有時候
應用程序需要實現特定類型的菜單
我們常用的如金山毒霸的彈出式菜單就是一例
可以在菜單項裡顯示自己定義的圖片
自己設置的文字以及自設置的菜單項大小
這種菜單稱為自繪制菜單(Owner
draw MenuItem)當然
功能不止於此
我們還可以實現更好的菜單
下面就一起來做一個顯示大圖片和大文字的菜單吧!
一
程序思路
Delphi在繪制每個菜單時
采用一個比較獨特的方法
首先
Delphi會通過菜單的OwnerDraw屬性來判定在菜單中是否允許自繪制菜單
若OwnerDraw屬性為真(TRUE)
則Delphi首先會觸發每個菜單項的OnMeasureItem事件來獲取自繪制菜單項的大小(Width
Height)
然後觸發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:=TPicture
Create;//創建一個用於裝載圖片的Tpicture對象
ePic
LoadFromFile(
a
bmp
);//從項目所在目錄裝載圖片
acanvas
Draw(arect
Left
arect
Top
ePic
Graphic); //將圖片在菜單項中繪制出來
acanvas
Font
Size:=
;//設置菜單項的字體大小
acanvas
Font
Color:=clPurple; //設置菜單項字體顏色
acanvas
TextOut(arect
Left+
arect
Top+
A
); //在菜單項中輸出文字A
end;
if i=
then
begin
ePic:=TPicture
Create; //創建一個用於裝載圖片的Tpicture對象
ePic
LoadFromFile(
b
bmp
); //從項目所在目錄裝載圖片
acanvas
Draw(arect
Left
arect
Top
ePic
Graphic); //將圖片在菜單項中繪制出來
acanvas
Font
Size:=
; //設置菜單項的字體大小
acanvas
Font
Color:=clblue; //設置菜單項字體顏色
acanvas
TextOut(arect
Left+
arect
Top+
B
); //在菜單項中輸出文字A
end;
if i=
then
begin
ePic:=TPicture
Create;
ePic
LoadFromFile(
c
bmp
);
acanvas
Draw(arect
Left
arect
Top
ePic
Graphic);
acanvas
Font
Size:=
;
acanvas
Font
Color:=clred;
acanvas
TextOut(arect
Left+
arect
Top+
C
);
end;
End;
下面我們實現菜單項的在被單擊時的行為
即實現actSample對象的OnExcute事件
如下所示
actSampleExecute(Sender: TObject);
begin
label
Caption:=inttostr(i);
end;
第三步
將菜單項動態添加到菜單中
I:=I+
;//計算程序中的擊鍵次數
miSample:=TMenuItem
Create(form
); //動態創建菜單項
miSample
OnClick :=actSample
OnExecute; //為菜單項添加動作
miSample
OnDrawItem := ADrawItem; //為菜單項設置顯示方式
miSample
OnMeasureItem := aMeasureItem; //為菜單項設置大小
mnuOwnerDraw
Items
Insert(
miSample); //將菜單項添加到菜單中
三
程序效果
現在可以應用程序了
你會發現
只要你在窗體上單擊右鍵
窗體會有一個彈出式菜單顯示出來
而且每一個菜單項都隨著右鍵單擊次數的不同而不同
當次數大於
時
菜單顯示為一系列的空菜單項
但是
不論何時你單擊任何一個菜單項
Label的都會顯示你當前的右鍵在窗體上單擊的次數值
四
程序加強
如果我們在程序中為我們所動態創建的每一個菜單項都實現不同的OnMeasureItem和OnDrawItem事件的話
那麼
每一個菜單項都有自己的大小處理與顯示處理
那我們就可以實現一些更好的功能
例如
可以實現大小不同的菜單項
第一個菜單項可以比較小
以後的菜單項可以比較大
同樣還可以在一些菜單中實現更好的功能
如
每個菜單顯示自己圖標和特定字體的文字
但是
利用這種方法制作自定義菜單的功能還是受到了一定的限制
我們只能對OnAdvancedDrawItem
OnClick
OnDrawItem
OnMeasureItem等有限幾個事件作出反應並對菜單項進行定制
我們沒有辦法對鼠標事件作出反應
利用鼠標事件
當鼠標滑過菜單項時
我們可以實現諸如加亮
漸變或其他的菜單項顯示技術
顯然這是十分有意義的
要實現上述技術
我們需要從TcustomMenuItem中繼承並定義一個新類並重新聲明OnMouseMove事件
並給出實現諸如加亮或漸變等技術的代碼即可
From:http://tw.wingwit.com/Article/program/Delphi/201311/8434.html