WinForm 控制項鍵盤訊息處理剖析(轉)

來源:互聯網
上載者:User

標籤:

一直想整理鍵盤事件的調用順序,剛好看見園子裡的這篇文章,寫的不錯,就轉載了:http://www.cnblogs.com/tedzhao/archive/2010/09/07/1820557.html

在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控制項對於鍵盤訊息的處理,分析了訊息預先處理以及處理兩個階段的各個函數。在進行三方控制項的開發中可以根據需要重載這些函數,另外也可從其設計以及實現思路中獲得更多啟發。

      WinForm 控制項鍵盤訊息處理剖析(轉)

      聯繫我們

      該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

      如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

      A Free Trial That Lets You Build Big!

      Start building with 50+ products and up to 12 months usage for Elastic Compute Service

      • Sales Support

        1 on 1 presale consultation

      • After-Sales Support

        24/7 Technical Support 6 Free Tickets per Quarter Faster Response

      • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.