C#改寫(xiě)WM_GETTEXT處理例程
在向大家詳細(xì)介紹C#改寫(xiě)WM_GETTEXT處理例程之前,首先讓大家了解下MDI應(yīng)用,然后全面介紹C#改寫(xiě)WM_GETTEXT處理例程。
如果你用 MFC 編寫(xiě)過(guò)多文檔界面(MDI)Windows 程序,那么肯定知道:如果父窗口標(biāo)題為“PCaption”,子窗口標(biāo)題為“CCaption”,那么每當(dāng)子窗口***化并處于激活狀態(tài)時(shí),子窗口標(biāo)題一般都會(huì)與父窗口標(biāo)題合二為一,變成“PCaption-[CCaption]”。 這是一種 MDI 的默認(rèn)行為。用 C# 編寫(xiě)多文檔界面程序也不例外。很多用戶都不喜歡這種缺省特性,往往想用定制的窗口標(biāo)題取而代之。以及將示范如何在C#程序中定制和修改MDI應(yīng)用的窗口標(biāo)題。
如果用MFC來(lái)編程,只要改寫(xiě)框架窗口類(lèi)的虛函數(shù) CFrameWnd::OnUpdateFrameTitle 即可。那么在微軟的 .NET 框架中如何用C#實(shí)現(xiàn)相同的功能呢?首先,我們必須理解 MDI 本身是如何通過(guò) Windows 核心 API 來(lái)實(shí)現(xiàn)自己的行為特性的,其實(shí)這與MFC或者.NET的公共語(yǔ)言運(yùn)行時(shí)(CLR)沒(méi)有什么關(guān)系。在創(chuàng)建MDI應(yīng)用時(shí),框架及其子窗口有各自專(zhuān)門(mén)的窗口過(guò)程,DefFrameProc 和 DefMDIChildProc,一個(gè)處理各種 WM_MDIXXX 消息以及其它類(lèi)似 WM_SIZE, WM_SYSCOMMAND 的消息,另一個(gè)實(shí)現(xiàn) MDI 行為。
如果用純 C 代碼編寫(xiě),那么必須自己負(fù)責(zé)用 DefFrameProc 和 DefMDIChildProc 創(chuàng)建窗口;在 MFC 中則使用 CMDIFrameWnd/CMDIChildWnd;.NET 框架平臺(tái)里則設(shè)置 Form.IsMdiContainer 和 Form.MdiParent,不管用哪種方式,其核心都是 user kernel,尤其是 DefFrameProc,當(dāng) MDI 子窗口***化時(shí),它會(huì)聯(lián)接父子窗口的標(biāo)題文本來(lái)產(chǎn)生主窗口標(biāo)題串。理解了這一點(diǎn),下面我來(lái)示范如何改寫(xiě)MDI。這個(gè)例子的原始版本來(lái)自 MSDN 庫(kù)中用C#寫(xiě)的 Scribble MDI(用 “scribble sample”搜索一下即可找到)。基本思路是首先在 Scribble 例子的 MainWindow 中改寫(xiě) WM_GETTEXT 消息處理例程,必須添加兩個(gè)數(shù)據(jù)成員:NormalText 和 MaximizedText,用它們來(lái)保存常態(tài)和***化狀態(tài)的標(biāo)題 :
- // in Scribble.cs, MainWindow class
- private String NormalText = "Scribble2";
- private String MaximizedText = "Window is now maximized";
- //如果想讓其它類(lèi)存取這兩個(gè)成員,那么可以通過(guò)屬性機(jī)制代替數(shù)據(jù)成員
- private String normaltext;
- public String NormalText
- {
- get { return normaltext; }
- set { normaltext = value; }
- }
因?yàn)樵诶映绦蛑?MainWindow 是唯一一個(gè)存取該字符串的類(lèi),所以沒(méi)有必要使用屬性機(jī)制。有了這兩個(gè)新的數(shù)據(jù)成員,你要做的只是C#改寫(xiě)WM_GETTEXT處理例程,返回子窗口***化狀態(tài)以及常態(tài)時(shí)的標(biāo)題文本。那么如何C#改寫(xiě)WM_GETTEXT處理例程呢?
Windows.Forms 提供了一些 處理 WM_XXX 消息的虛擬函數(shù),如 OnResize/WM_SIZE等,但是恰恰缺少與 WM_GETTEXT 相關(guān)東東(OnGetText/WM_GETTEXT)。不要擔(dān)心,沒(méi)有虛函數(shù),我們總是可以改寫(xiě)包羅萬(wàn)象的 WndProc 處理例程。為此必須知道所處理的消息ID,也就是 WM_GETTEXT 的消息 ID = 0x000D,有人會(huì)問(wèn),你是怎么知道這個(gè)消息的 ID 是 0x000D 啊,很簡(jiǎn)單,一種方法是運(yùn)行 SPY 獲取,另一種方法是直接查找Windows SDK 中的 winuser.h 頭文件。一旦你能深入到 WndProc 這一層次編寫(xiě)代碼,那么你基本上能用 C 語(yǔ)言寫(xiě)程序了,因?yàn)?Win32 API 和其它語(yǔ)言之間所有東東通過(guò) WPARAMs 和 LPARAMs 參數(shù)傳遞的,包括字符串在內(nèi)。對(duì)于 WM_GETTEXT 來(lái)說(shuō),Message.LParam 是指向 char* 的指針,Message.WParam 是該指針長(zhǎng)度。也就是說(shuō)你必須完成將文本串拷貝到調(diào)用者的緩沖里。好在這并不是太難,下面是程序代碼:
- public class MainWindow : System.Windows.Forms.Form
- {
- private String NormalText = "Scribble2";
- private String MaximizedText = "Window is now maximized";
- // Handle WM_GETTEXT: Return maximized or
- // normal text, depending on
- // state of active MDI child window.
- protected override void WndProc(ref Message m)
- {
- const int WM_GETTEXT = 0x000D;
- if (m.Msg==WM_GETTEXT) {
- Form active = this.ActiveMdiChild;
- String s = active!=null &&
- active.WindowState==FormWindowState.Maximized ? MaximizedText :
- NormalText;
- char[] c = s.ToCharArray();
- IntPtr buf = m.LParam;
- int len = c.Length;
- Marshal.Copy(c, 0, buf, Math.Min((int)m.WParam, len));
- m.Result = (IntPtr)len;
- return;
- }
- base.WndProc(ref m)
- }
- ......
- // rest of MainWindow unchanged from Scribble sample
- }
【編輯推薦】


















