| 用Delphi制作個性化的菜單 www.netgocn.com原創(chuàng) 在應(yīng)用程序編寫中,使用個性化的菜單可以美化界面,展示個性風彩。例如3721網(wǎng)站推出的《3721網(wǎng)絡(luò)特快》應(yīng)用程序中的菜單就是一例。從其Windows編程的角度來說它僅是一個自繪式菜單而已。本文就使用Delphi制作這樣的個性化菜單作出說明(本文以Delphi4.0為例),制作一個可以有背景圖、鼠標在上移動選擇時的背景色有漸變色效果的彩色菜單。 一、關(guān)于Delphi中的自繪式菜單 要將Delphi的菜單(TMainMenu?或TPopupMenu)控件(Component)設(shè)為自繪式,有兩種不同的情況: ????①?如果菜單上沒有圖標(即,沒有設(shè)定其Images屬性),則必須將菜單控件的OwnerDraw屬性設(shè)為True,菜單為自繪式。 ????②?菜單上有圖標(即,已設(shè)定其Images屬性),菜單為自繪式。 在此,我們必須首先把準備將其制作成有個性特征的菜單設(shè)為自繪式。 二、關(guān)于背景的重繪 通常Windows程序的標準菜單,在其被下拉或彈出時,鼠標在上移動時出現(xiàn)的選擇條背景是一單一的顏色,現(xiàn)在我們要將其重繪為有漸變色效果的背景,另外如果要在其背景上繪制圖形(您見過這樣的菜單嗎?),則應(yīng)先繪圖、后繪漸變的背景。這些繪制工作的完成只需簡單使用Delphi提供的畫布(Canvas)對象。 三、關(guān)于重繪圖標 如果菜單上有圖標,則最好為各菜單項指定ImageIndex索引號,而不要使用其Bitmap屬性。這樣在為各菜單項指定了ImageIndex索引號后,可以直接用其TImageList的Draw方法在同一個畫布上繪制相應(yīng)的圖標。 四、關(guān)于重繪菜單文本 ????在重繪菜單時,為了不破壞其背景,應(yīng)將文本的背景模式設(shè)為透明,這要用到一個Windows?API函數(shù)SetBkMode(),其在C++中定義的原形如下: ????????????int?SetBkMode( ?????????????????????????HDC?hdc, ?????????????????????????int?iBkMode? //?flag?specifying?background?mode ??????????????????????????); ????????其中:hdc?–?是繪圖設(shè)備句柄,在Delphi中可為Tcanvas的Handle屬性; ??????????????iBkMode?–?指定的背景模式標識符,有OPAQUE 和TRANSPARENT兩個 ????????????????????????常量取值,取TRANSPARENT時,為透明模式。 設(shè)置了背景模式后,可以使用TCanvas的TextOut方法繪制菜單文本。 五、響應(yīng)自繪式菜單的OnDrawItem事件 ????為菜單項的OnDrawItem事件添加代碼,完成想要完成的重繪工作,如下所示(M_Item1_1是菜單項名稱):
procedure?TForm1.M_Item1_1DrawItem(Sender:?TObject;?ACanvas:?TCanvas; ??????????????????????????????????ARect:?TRect;?Selected:?Boolean); ????begin ???????//調(diào)用自定義過程--重繪菜單項 ???????DrawItem(TMenuItem(Sender),?ACanvas,?ARect,Selected); ????end; 六、二個示例 ㈠ 以下是實現(xiàn)上述個性化菜單的自定義過程DrawItem的一個示例的代碼。但需作如下說明: ① 在其Delphi工程的主窗口上有一個TCoolBar控件CoolBar1,其上又放了一個TToolBar控件,并且TCoolBar的Bitmap屬性不為空(即為其指定了圖象)。 ② 主窗口上有一個TPopupMenu?控件PopupMenu1、一個TImageList控件ImageList1,其PopupMenu1的Images屬性等于ImageList1。 ③ TToolBar的Transparent屬性為True,并且上面的工具按鈕的MenuItem屬性分別與相應(yīng)的菜單項相關(guān)聯(lián)(注意,這是用工具條、工具按鈕和彈出式菜單制作主菜單的方法,應(yīng)將工具按鈕的Grouped屬性全部設(shè)為True)。 代碼如下: procedure?TForm1.DrawItem(Item:TMenuItem;?ACanvas:?TCanvas;?ARect:?TRect;? ?????????????????????????Selected:?Boolean); var ??dc,y,i,j,xb,xe:integer; begin ??//設(shè)置字體和其前景色 ??ACanvas.Font?:=?Screen.IconFont; ??SetBkMode(ACanvas.Handle,TRANSPARENT);??//設(shè)背景為透明
??//根椐菜單寬度計算漸變背景色的填充色增量;當菜單寬度大于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);??//必須重設(shè)背景模式為透明 ?????ACanvas.TextOut(ARect.Left+20,ARect.Top+4,Item.Caption);//front?color,which?is?white?font ??end; end; 在各菜單項的OnDrawItem事件處(如五所示)均調(diào)用此過程,運行程序可以看到一個有背景圖、所選菜單項左邊有一個圖標且背景色是由紅到黃漸變的菜單。 ㈡ 以下是實現(xiàn)上述個性化菜單的自定義過程DrawItem的另一個示例的代碼。為一個有圖標的彈出式菜單,不作過多的說明了。 procedure?TForm1.DrawItem(Item:TMenuItem;?ACanvas:?TCanvas;?ARect:?TRect;?Selected:?Boolean); var ??i,xb:integer; begin ??//設(shè)置字體和其前景色 ??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; 同理,應(yīng)在各菜單項的OnDrawItem事件處均調(diào)用此過程。
七、小結(jié) 使用自繪式菜單,對整個菜單進行全面的重繪,可以任其想象發(fā)揮,繪出五顏六色的個性化菜單,極大地豐富程序界面。 注:用此方法較率較低,不適合做要求較高的軟件。高級的做法是全部使用WindowsAPI和消息。 需要示例示源代碼的,請到www.netgocn.com留言,一定給你。 |