End() 即可還原原生風格。
OfficeMenus.dll) 加入工具箱。OfficeMenus1 元件實例。OfficeMenus1.Start(this);OfficeMenus1.End();OfficeMenus1.ImageList = imageList1;OfficeMenus1.AddPicture(menuItem2, 1);OfficeMenus:繼承 Component,管理全域設定與生命週期。MainMenuItemDrawing:繪製頂層選單列(如「檔案」、「編輯」)。MenuItemDrawing:繪製子選單與右鍵選單項目。命名空間:Dev4Arabs
static ImageList _imageList; // 圖示集合
static NameValueCollection picDetails = new NameValueCollection();
// 對應:選單控制碼 Handle → 圖示索引
MainMenu 與 ContextMenu。MenuItem:foreach (MenuItem mi in menu.MenuItems)
{
mi.MeasureItem += MainMenuItem_MeasureItem;
mi.DrawItem += MainMenuItem_DrawItem;
mi.OwnerDraw = true; // 關鍵:啟用自繪
InitMenuItem(mi); // 遞迴處理子選單
}
ContextMenu 同樣處理。設定 OwnerDraw = true 後,Windows 會發送兩個關鍵事件:
MeasureItem:計算選單項目寬高(對應 Win32 WM_MEASUREITEM)。DrawItem:實際繪製外觀(對應 Win32 WM_DRAWITEM)。| 類別 | 負責範圍 | 關鍵方法 |
|---|---|---|
| MainMenuItemDrawing | 主選單列項目 | DrawMenuItem():繪製懸浮/選取矩形、文字 |
| MenuItemDrawing | 子選單、右鍵選單 | DrawMenuItem():繪製背景、核取方塊、文字、圖示 |
public void AddPicture(MenuItem mi, int index)
{
picDetails.Add(mi.Handle.ToString(), index.ToString());
}
public static Bitmap GetItemPicture(MenuItem mi)
{
if (_imageList == null) return null;
string[] idx = picDetails.GetValues(mi.Handle.ToString());
return idx == null ? null : (Bitmap)_imageList.Images[Convert.ToInt32(idx[0])];
}
.NET GDI+ 讓自繪比 MFC/Win32 簡單許多。難點在於 MeasureItem/DrawItem 事件中依據狀態(懸浮、選取、分隔線、核取方塊、圖示區域)進行精確繪製。完整原始碼可參考 CodeProject 專案 MhOffice2003Menus。