用Delphi制作個性化的菜單
- 發布于:2024-02-15
- 共 188 人圍觀
一、關于Delphi中的自繪式菜單
要將Delphi的菜單(TMainMenu 或TPopupMenu)控件(Component)設為自繪式,有兩種不同的情況:
① 如果菜單上沒有圖標(即,沒有設定其Images屬性),則必須將菜單控件的OwnerDraw屬性設為True,菜單為自繪式。
② 菜單上有圖標(即,已設定其Images屬性),菜單為自繪式。
在此,我們必須首先把準備將其制作成有個性特征的菜單設為自繪式。
二、關于背景的重繪
通常Windows程序的標準菜單,在其被下拉或彈出時,鼠標在上移動時出現的選擇條背景是一單一的顏色,現在我們要將其重繪為有漸變色效果的背景,另外如果要在其背景上繪制圖形(您見過這樣的菜單嗎?),則應先繪圖、后繪漸變的背景。這些繪制工作的完成只需簡單使用Delphi提供的畫布(Canvas)對象。
三、關于重繪圖標
如果菜單上有圖標,則最好為各菜單項指定ImageIndex索引號,而不要使用其Bitmap屬性。這樣在為各菜單項指定了ImageIndex索引號后,可以直接用其TImageList的Draw方法在同一個畫布上繪制相應的圖標。
四、關于重繪菜單文本
在重繪菜單時,為了不破壞其背景,應將文本的背景模式設為透明,這要用到一個Windows API函數SetBkMode(),其在C++中定義的原形如下:
int SetBkMode(
HDC hdc,
int iBkMode // flag specifying background mode
);
其中:hdc – 是繪圖設備句柄,在Delphi中可為Tcanvas的Handle屬性;
iBkMode – 指定的背景模式標識符,有OPAQUE 和TRANSPARENT兩個
常量取值,取TRANSPARENT時,為透明模式。
設置了背景模式后,可以使用TCanvas的TextOut方法繪制菜單文本。
五、響應自繪式菜單的OnDrawItem事件
為菜單項的OnDrawItem事件添加代碼,完成想要完成的重繪工作,如下所示(M_Item1_1是菜單項名稱):
procedure TForm1.M_Item1_1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin //調用自定義過程--重繪菜單項
DrawItem(TMenuItem(Sender), ACanvas, ARect,Selected);
end;
六、二個示例
㈠ 以下是實現上述個性化菜單的自定義過程DrawItem的一個示例的代碼。但需作如下說明:
① 在其Delphi工程的主窗口上有一個TCoolBar控件CoolBar1,其上又放了一個TToolBar控件,并且TCoolBar的Bitmap屬性不為空(即為其指定了圖象)。
② 主窗口上有一個TPopupMenu 控件PopupMenu1、一個TImageList控件ImageList1,其PopupMenu1的Images屬性等于ImageList1。
③ TToolBar的Transparent屬性為True,并且上面的工具按鈕的MenuItem屬性分別與相應的菜單項相關聯(注意,這是用工具條、工具按鈕和彈出式菜單制作主菜單的方法,應將工具按鈕的Grouped屬性全部設為True)。
代碼如下:
procedure TForm1.DrawItem(Item:TMenuItem; ACanvas: TCanvas; ARect: TRect;
Selected: Boolean);
var
dc,y,i,j,xb,xe:integer;
begin
//設置字體和其前景色
ACanvas.Font := Screen.IconFont;
SetBkMode(ACanvas.Handle,TRANSPARENT); //設背景為透明
//根椐菜單寬度計算漸變背景色的填充色增量;當菜單寬度大于256時沒有漸變較果
dc:=ACanvas.ClipRect.Right-ACanvas.ClipRect.Left;
dc:=(256 div dc);
dc:=dc*256;
//計算漸變背景色的填充起點
xb:=ARect.Left + ImageList1.Width+2;
//計算漸變背景色的填充終點
xe:=ARect.Right-xb;
//繪制背景圖
ACanvas.StretchDraw(Rect(0,0,ACanvas.ClipRect.Right,ACanvas.ClipRect.Bottom),
CoolBar1.Bitmap);//非平輔方式繪制
//繪制菜單項文本
for j:=0 to Item.Parent.Count -1 do
begin
y:=19*j+4;
ACanvas.TextOut(ARect.Left+20,y,Item.Parent.Items[j].Caption);//front color is black font
end;
//繪制當前選擇的菜單項
if Selected then begin
for i:=0 to xe do begin
ACanvas.Brush.Color := $002222FF+i*dc; //背景的填充色,$002222FF為起始色
ACanvas.FillRect(Rect(xb,ARect.Top,xb+1,ARect.Bottom));
inc(xb);
end;
ImageList1.Draw(ACanvas,ARect.Left+1,ARect.Top+1,0,true); //在左邊繪制圖標
ACanvas.Font.Color:=clWhite; //被選中時的字體前景色是白色
SetBkMode(ACanvas.Handle,TRANSPARENT); //必須重設背景模式為透明
ACanvas.TextOut(ARect.Left+20,ARect.Top+4,Item.Caption);//front color,which is white font
end;
end;
在各菜單項的OnDrawItem事件處(如五所示)均調用此過程,運行程序可以看到一個有背景圖、所選菜單項左邊有一個圖標且背景色是由紅到黃漸變的菜單。
㈡ 以下是實現上述個性化菜單的自定義過程DrawItem的另一個示例的代碼。為一個有圖標的彈出式菜單,不作過多的說明了。
procedure TForm1.DrawItem(Item:TMenuItem; ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
var
i,xb:integer;
begin
//設置字體和其前景色
ACanvas.Font := Screen.IconFont;
ACanvas.Brush.Color := clBtnFace;
ACanvas.FillRect(ARect);
ACanvas.TextOut(ARect.Left+20,ARect.Top+4,Item.Caption);
if Selected then begin
//繪制當前選擇的菜單項
xb:=0;
for i:=0 to ARect.Right do begin
ACanvas.Brush.Color :=clTeal+i*$100;//gradient back color
ACanvas.FillRect(Rect(xb,ARect.Top,xb+1,ARect.Bottom));
inc(xb);
end;
ACanvas.Font.Color:=clWhite;//被選中時的字體前景色是白色
SetBkMode(ACanvas.Handle,TRANSPARENT);
ACanvas.TextOut(ARect.Left+20,ARect.Top+4,Item.Caption);
end;
ImageList1.Draw(ACanvas,ARect.Left+1,ARect.Top+1,Item.ImageIndex,true);//繪制左邊的圖標
end;
同理,應在各菜單項的OnDrawItem事件處均調用此過程。
七、小結
使用自繪式菜單,對整個菜單進行全面的重繪,可以任其想象發揮,繪出五顏六色的個性化菜單,極大地豐富程序界面。
此外,用此方法雖然簡單但較率較低,不適合做要求較高的軟件。高級的做法是全部使用WindowsAPI和消息。
標簽: