轉帖|其它|編輯:郝浩|2010-10-26 14:20:39.000|閱讀 785 次
概述:在WinForm控件上我們可以看到很多關于鍵盤消息處理的方法,比如OnKeyDown, OnKeyPress, ProcessCmdKey, ProcessDialogKey,IsInputKey等等,那么這些方法是如何被組織的,每一個方法的具體含義又是什么哪?Win32的鍵盤消息又是如何到達控件上的這些方法的,本文將著重闡述這些問題,對.Net WinForm控件的鍵盤消息處理過程進行剖析。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
在WinForm控件上我們可以看到很多關于鍵盤消息處理的方法,比如OnKeyDown, OnKeyPress, ProcessCmdKey, ProcessDialogKey,IsInputKey等等,那么這些方法是如何被組織的,每一個方法的具體含義又是什么哪?Win32的鍵盤消息又是如何到達控件上的這些方法的,本文將著重闡述這些問題,對.Net WinForm控件的鍵盤消息處理過程進行剖析。
1. WinForm消息循環
大家都知道WinForm也是依賴于底層的消息機制的,通常我們的WinForm應用程序會以如下方式啟動:
Application.Run(new Form());
上面的代碼將會在當前線程啟動一個消息循環,并且顯示指定窗體。
反編譯Application類的Run方法,我們可以看到這一點:
public static void Run(Form mainForm)
{
ThreadContext.FromCurrent().RunMessageLoop(-1,new ApplicationContext(mainForm));
}
啟動消息循環之后,操作系統就會將用戶對于當前應用程序的UI輸入轉換為Windows消息發給當前線程進行處理。本文的重點不在于講述Windows消息機制,而在于底層消息到達.Net這一層后,WinForm控件是如何處理的。
2. 消息處理
從上面可以看到通過ThreadContext類型的RunMessageLoop方法,構建了消息循環。那么對于一個特定的Windows消息,ThreadContext又是如何處理的哪?
分析ThreadContext的代碼可以發現其調用關系如下:
在LocalModalMessageLoop方法中我們就可以看到對于Windows消息的處理了:
private bool LocalModalMessageLoop()
{
// ...
if(!PreTranslateMessage(ref msg))
{
// ...
UnsafeNativeMethods.TranslateMessage(ref msg);
UnsafeNativeMethods.DispatchMessage(ref msg);
}
// ...
}
可以發現對于一個特定的Windows消息,分為兩個階段進行處理:
PreTranslateMessage
DispatchMessage
WinForm控件消息的處理將從這兩個地方開始。
2.1 PreTranslateMessage
PreTranslateMessage提供了一個時機,來決定是否應該Dispatch這個消息,如果返回值為False,這個消息才會派發給WinForm控件。
PreTranslateMessage分為兩個層次,第一優先調用當前應用程序的IMessageFilter來進行處理,用戶可以在這一層進行消息預處理或者消息過濾。如果沒有被過濾掉,調用當前控件的PreProcessMessage方法進行消息預處理。
Control類型的PreProcessMessage處理流程如下:
對于WM_KeyDown消息,其預處理Control類上有三個時機:ProcessCmdKey,IsInputKey以及ProcessDialogKey;對于WM_KeyChar消息,其預處理有兩個時機:IsInputChar和ProcessDialogChar。
ProcessCmdKey默認用來處理快捷鍵以及菜單快捷鍵,此方法會遞歸調用父控件。如果返回值為False,繼續調用IsInputKey,決定是否引發KeyDown事件。如果不是InputKey,調用ProcessDialogKey來檢查該鍵是否為導航鍵,或者進行一些特別的處理,此方法會遞歸調用父控件的處理。
IsInputChar決定輸入字符是否為普通字符,如果返回值為True會引發KeyPress事件。返回值為False會調用ProcessDialogChar,ProcessDialogChar默認用來處理Mnemonic鍵,例如控件的文本為"&OK", 對于Char"O"的處理。
2.2 DispatchMessage
如果PreTranslateMessage沒有過濾掉該Windows消息的話,該消息將會派發到控件,交由控件的WndProc函數進行處理。
下圖是控件的處理流程:
消息到達WnProc之后,會交由ProcessKeyMessage,ProcessKeyPreview以及ProcessKeyEventArgs處理。每一個方法都會返回一個Boolean值,表明控件是否已經處理了該消息。
ProcessKeyMessage會處理所有由WndProc過來的所有鍵消息,首先會調用父控件的ProcessKeyPreview函數,如果返回True,表明父控件已經處理。否則調用ProcessKeyEventArgs來觸發控件的KeyDown,KeyPress,KeyUp事件。
3. 結語
本文著重講述了WinForm控件對于鍵盤消息的處理,分析了消息預處理以及處理兩個階段的各個函數。在進行三方控件的開發中可以根據需要重載這些函數,另外也可從其設計以及實現思路中獲得更多啟發。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客轉載