首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

.NET 自繪機制深度解析:MenuItem.OwnerDraw + DrawItem/MeasureItem 事件打造 Office/VS 風格選單

     編輯:VC 教學

.NET Framework (WinForms) 提供了極為優雅的自繪模型:**將 MenuItem.OwnerDraw = true,訂閱 DrawItem 與 MeasureItem 事件**,即可完全接管選單項渲染,無需 MFC 那樣複雜的訊息映射與結構體解析。本文深度解析 .NET 選單架構 (MainMenu/ContextMenu/MenuItem)、自繪事件模型,並規劃一個可拖放設計器的 GraphicMenu 元件雛形。

.NET 選單物件模型

  • Menu:公共基類。
  • MainMenu:表單頂層選單列。
  • ContextMenu:右鍵彈出選單。
  • MenuItem:單個選單項 (可巢狀形成子選單)。
  • 所有選單本質都是 MenuItem 集合,無論顯示位置。

圖一:自繪控制項示意

自繪啟用與事件模型 (VB.NET 範例)

Sub MakeItemOwnerDraw(ByVal item As MenuItem)
    item.OwnerDraw = True
    AddHandler item.DrawItem, AddressOf StdDrawItem
    AddHandler item.MeasureItem, AddressOf StdMeasureItem
End Sub

兩大核心事件職責

事件觸發時機開發者任務
MeasureItem選單需計算項目尺寸時 (彈出前)根據字體/圖示/文字計算 e.ItemWidth, e.ItemHeight 並賦值
DrawItem選單需繪製特定項目時在 e.Graphics 上繪製背景、圖示、文字、選中態、勾選框等

MeasureItemEventArgs / DrawItemEventArgs 封裝了 Win32 底層 MEASUREITEMSTRUCT / DRAWITEMSTRUCT,提供強型別屬性 (Font, Graphics, Bounds, State 等),極大降低開發難度。

元件化設計思路:GraphicMenu 外部初始化器

而非繼承 MainMenu,作者建議建立獨立類別 GraphicMenu,提供 Initialize(Menu targetMenu) 方法:

  1. 遞迴遍歷 targetMenu.MenuItems 所有層級項目。
  2. 將每個 MenuItem.OwnerDraw = true。
  3. 統一訂閱 DrawItem/MeasureItem 至內部處理器。
  4. 內部處理器依據「主題」 (Office 2003 藍/銀/橄欖、VS.NET 風格) 繪製。

缺點: 需顯式呼叫 Initialize,設計器不支援預覽 (運行時才見效果)。

優點: 與現有選單結構解耦、可動態切換主題、單一職責原則。

繪製邏輯關鍵點 (DrawItem 內部)

  • e.DrawBackground():一鍵繪製系統預設背景 (含選中藍、勾選框區),可選用。
  • e.State 旗標判斷:DrawItemState.Selected, Disabled, Checked, Default, HotLight, Focus, NoAccelerator 等。
  • 文字繪製:e.Graphics.DrawString(text, font, brush, bounds, stringFormat),StringFormat 控制置中/靠右/省略號。
  • 圖示繪製:e.Graphics.DrawImage(image, rect) 或 ImageList.Draw。
  • 高解析度支援:e.Graphics 基於 GDI+,原生支援抗鋸齒、Alpha 混合、向量縮放。

MFC vs .NET 自繪體驗對比

維度MFC (C++).NET WinForms
啟用方式MF_OWNERDRAW + 訊息映射MenuItem.OwnerDraw = true + 事件訂閱
尺寸計算OnMeasureItem 手寫 MEASUREITEMSTRUCTMeasureItem 事件 e.ItemWidth/Height
繪製介面CDC* + DRAWITEMSTRUCT 指標Graphics 物件 + DrawItemEventArgs
狀態判斷位元旗標 ODS_SELECTED 等列舉 DrawItemState 旗標
圖形能力GDI (線/矩形/文字/位圖)GDI+ (漸層/路徑/抗鋸齒/Alpha/轉換)
設計器支援無 (純代碼)可建立元件拖放設計器 (本文目標)

下一步展望

作者計劃後續文章實現完整的 GraphicMenu 元件:設計器支援、主題序列化、動畫展開、鍵盤導航輔助等。.NET 的自繪模型讓這些進階功能的開發門檻大幅降低。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved