簡介
僅僅使用一行簡單的程序,你就能夠使你的Windows窗體的所有菜單和上下文菜單具有office2003的菜單外觀。同樣地,你也可以只用一行程序,就能為你的菜單加上漂亮的圖標。本文實現的是一個具有該功能的組件。如果你想讓你的菜單恢復原來的外觀,也只須調用End方法即可。
組件的使用
要正確使用組件,必須先將你的組件加入到工具箱中。然後將該組件從工具箱中拖放放到form窗體中。這時會看到你的form的設計頁中多出了一個名為OfficeMenus1的圖標,說明已經將菜單組件加入到了form中。緊接著調用如下方法:
//開始顯示office 2003菜單 OfficeMenus1.Start( FormName ); 注:FormName為要改變菜單風格的窗口名稱。同樣,你也可以通過調用如下方法終止菜單的office2003風格,使之回到原始外觀:
// 改變菜單的外觀風格到原始狀態 OfficeMenus1.End();為菜單頂添加圖標也很簡單,只須為工程添加一個ImageList(圖像列表控件),然後將OfficeMenu組件的ImageList屬性更改為你添加的ImageList,使用如下代碼實現:
// 為菜單添加圖像 // OfficeMenus.AddPicture( MenuItem MenuItemToAddPictureTo, int ImageIndex ); OfficeMenus1.ImageList = imageList1; OfficeMenus1.AddPicture(menuItem2, 1);
可以看出,只須如此幾行代碼就能輕松讓你的菜單實現office2003風格。
組件的實現方法及原理
組件由三個類實現,這三個類分別為OfficeMenus,MainMenuItemDrawing和MenuItemDrawing,都位於命名空間Dev4Arabs中。由於實現代碼較長,所以在此只給出了組件實現的思路。
組件實現的第一步是從System.ComponentModel.Component類派生類OfficeMenus。定義如下:
public class OfficeMenus : System.ComponentModel.Component然後在類中定義兩靜態變量:
//圖像列表用來存儲菜單中用到的圖標
static ImageList _imageList;// 存儲圖片細節的一個名稱集合,NameValueCollection的詳細說明請查閱MSDN,該類主要用來使每個菜單的句柄與每個圖標形成一一對應的關系,以便後面繪制菜單頂的圖標時快速地找到某個菜單所對應的圖標。
static NameValueCollection picDetails = new NameValueCollection();接下來定義公共接口方法start和End。
公共接口方法Start的實現原理如下:
public void Start(Form form) { 先從Start傳入的參數中獲得該窗口的主菜單。接下來為每一個主菜單下的MenuItem添加MeasureItem事件 處理mainMenuItem_MeasureItem和DrawItem事件處理mainMenuItem_DrawItem, 將MenuItem的OwnerDraw屬性設置為true,並使用InitMenuItem(Menu mi)方法對每個MenuItem應用改變。 然後再從form參數中獲取該窗口的上下文菜單對象,對其調用InitMenuItem(Menu mi)應用改變。 最後循環查找窗口中包含的每個子控件的上下文菜單,對其應用改變。 System.Windows.Forms.MainMenu menu = form.Menu; foreach ( MenuItem mi in menu.MenuItems ) { mi.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(mainMenuItem_MeasureItem); mi.DrawItem += new System.Windows.Forms.DrawItemEventHandler(mainMenuItem_DrawItem); mi.OwnerDraw = true; InitMenuItem(mi); } ContextMenu cmenu = form.ContextMenu; if ( cmenu != null ) {InitMenuItem(cmenu);} foreach ( Control c in form.Controls ) { if ( c.ContextMenu != null ) InitMenuItem(c.ContextMenu);} catch {} }
End方法與這類似,只須將InitMenuItem換為UninitMenuItem,這裡就不再舉出了。具體實現代碼請到http://www.codeproject.com/cs/menu/MhOffice2003Menus.asp下載。
為每個菜單應用改變的InitMenuItem方法的實現如下:
private void InitMenuItem(Menu mi) { 循環查找mi中的每個MenuItem,為其添加MeasureItem事件處理menuItem_MeasureItem和 DrawItem事件處理menuItem_DrawItem(注意,此處的事件處理方法名稱與Start中對 主菜單的事件處理方法名稱不同),並將OwnerDraw屬性設置為true。使用遞歸調用對每個查找 到的MenuItem調用InitMenuItem方法,這樣便可以對菜單項下的所有級別的子菜單項都應用到改變。 }UninitMenuItem的定義與此類似。
本文示例代碼或素材下載