程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> .NET中的自繪機制

.NET中的自繪機制

編輯:vc教程

  每次 Microsoft 推出象 Office 或者 Visual Studio 這樣拳頭產品的新版本時,都會推出一些新的特性,其中包括了新的菜單樣式(Menu Style)。當新的菜單樣式以各自的方式集成到成品中後,第三方的開發商便會掀起一陣模仿浪潮,利用一些定制控件和組件來仿效它。如果你正在使用這些產品,那麼你惟有升級到新版本才能享受提供的新的特性。否則,你的應用程序將繼續使用大約十年前隨 Windows 95 上市時的那種 Windows 經典菜單用戶界面。

  雖然 Microsoft 在其主要產品中定期更新菜單樣式,但其可用來定制應用程序的菜單 API 卻自 Windows 3.x 和 文件管理器以來一直沒有發生太大的變化。從 Win16 平台開始,應用程序就已經可以有權自已繪制一個個的菜單項來實現自定義菜單。這種技術今天稱作自繪(Owner-drawing),並已大量用於其它一些系統組件與控件上,包括列表框、按鈕和組合框。

  Figure 1 自繪控件

  自定義控件的繪圖在 Win16 和 Win32 平台下是很無聊的事情。從功能上講並不是特別復雜,但是代碼的編寫和維護著實令人討厭。在本期欄目中,我將深入研究 .NET框架為窗口菜單提供的自繪機制。最終目的是創建一個自定義的組件——只要你將它拖放到某個 Windows 窗體的組件托盤(Component Tray)上,它就允許你按照給定的主題定制菜單的外觀。作為例子,我將混合使用 Visual Studio.NET 和 Office 2003 的菜單樣式。如 Figure 1 所示,一旦你理解了 .NET 中的自繪控件,那麼你也能完成這個示例。 

  自定義菜單的顯示

  在.NET框架中,與窗口菜單相關的類包括 MainMenu、ContextMenu 和 MenuItem,這些類都是從公共類——Menu 類派生而來 的。某個窗體的最頂層菜單總是一個 MainMenu 類實例。應用程序的菜單包括了一個彈出式菜單的列表,每個彈出式菜單又由若干個菜單項和子菜單組成。ContextMenu 類對應動態上下文菜單,應用程序中所有活動可見的對象都可以顯示這樣的一個菜單。 上下文菜單是一個獨立的子菜單,並且沒有辦法與頂層菜單顯示的其它子菜單區分開來。最後,MenuItem對象則對應在MainMenu 或者 ContextMenu 對象 內顯示的某個獨立的菜單項。總之,任何.NET框架下的菜單都是一個 MenuItem 對象集合——無論它在哪裡、以及如何被顯示。

  Win32平台下的自繪功能比較容易通過其 MenuItem 類為數不多的屬性和事件來實現。如果你已是一位熟練的 Win32 程序員,你應該賞識.NET下自繪編程模型 的簡捷與效率。如果你從未接觸過 Win32的自繪控件,你將無法想象它會有多痛苦。再回到.NET的自繪菜單,只要你簡單地把在 MenuItems 屬性中找到的每一個MenuItem對象的 OwnerDraw 屬性設置為真(TRUE)即可。此外,每個 MenuItem 對象都能處理一對事件-DrawItem 和 MeasureItem,它們 收集用於 Win32 平台的底層信息。下面的Visual Basic.NET 代碼演示了如何將一個菜單項變成自繪菜單項。

Sub MakeItemOwnerDraw(ByVal item As MenuItem)
item.OwnerDraw = True
AddHandler item.DrawItem, AddressOf StdDrawItem
AddHandler item.MeasureItem, AddressOf StdMeasureItem
End Sub
  在繪制菜單之前,當菜單需要知道某個菜單項的大小時,便觸發 MeasureItem 事件,當菜單需要繪制特定項目時,則觸發 DrawItem 事件 。Windows 使菜單足夠大以適應最大的菜單項。MeasureItem 事件處理函數根據給定的菜單字體大小計算並返回菜單項的文本大小,而 DrawItem 事件處理函數則將 某些菜單文本及其位圖、花哨的背景,甚或是你想在菜單上顯示的任何東西繪制在給定的Graphics對象上。

  重寫窗體菜單

  重寫某個窗體菜單,使之更多彩、更直觀的步驟很簡單:只要設置每個 MenuItem 對象的OwnerDraw 屬性為True,並為關鍵事件編寫適當的事件處理函數。怎樣 以最佳方式實現這些呢?你會選擇從Menu或MainMenu類派生一個新的類嗎?甚至創建一個新的組件與這些缺省的菜單對象集並肩運行?

  就我所知,最簡單的方法是創建一個新的包含一個初始化方法的外部類——我稱其為 GraphicMenu。它這個初始化方法使用一個指向你所希望定制的菜單的引用 作為參數,將其所有子菜單項的自繪標志打開。這個方法的缺點在於始終需要一個對 初始化程序(initializer )的顯式調用。更重要的是,你將無法 得到 Visual Studio .NET設計器的任何支持。最終,這個菜單在運行時只有一個自繪外觀。在本文中,我將全面描述這種方法。

本文示例代碼或素材下載

  • 首頁
  • 上一頁
  • 1
  • 2
  • 3
  • 下一頁
  • 尾頁
  • 共3頁
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved