Windows Form 和 WPF 互通性輸入架構

更新:2007 年 11 月

若要讓 WPF 與 Windows Form 兩者之間互通,這兩項技術都必須具有適當的鍵盤輸入處理。本主題說明這些技術如何實作鍵盤與訊息處理,以在混合應用程式中順利達到互通性。

本主題包含下列子章節:

  • 非強制回應表單與對話方塊

  • WindowsFormsHost 鍵盤與訊息處理

  • ElementHost 鍵盤與訊息處理

非強制回應表單與對話方塊

呼叫 WindowsFormsHost 項目的 EnableWindowsFormsInterop 方法,以從 WPF 架構應用程式開啟非強制回應 (Modeless) 表單或對話方塊。

呼叫 ElementHost 控制項的 EnableModelessKeyboardInterop 方法,以在 Windows Form 架構應用程式中開啟非強制回應 WPF 頁面。

WindowsFormsHost 鍵盤與訊息處理

當由 WPF 架構應用程式裝載時,Windows Form 鍵盤與訊息處理包含下列步驟:

下列章節將進一步說明程序中的這些部分。

從 Windows Presentation Foundation 訊息迴圈取得訊息

ComponentDispatcher 類別會實作 WPF 的訊息迴圈管理員。ComponentDispatcher 類別會提供攔截 (Hook),讓外部用戶端可在 WPF 處理訊息前先篩選訊息。

互通性實作 (Implementation) 會處理 ComponentDispatcher.ThreadFilterMessage 事件,讓 Windows Form 控制項可在 WPF 控制項之前處理訊息。

Surrogate Windows Form 訊息迴圈

根據預設,System.Windows.Forms.Application 類別包含 Windows Form 應用程式的主要訊息迴圈。在互通期間,Windows Form 訊息迴圈不會處理訊息。因此,必須重現這個邏輯。ComponentDispatcher.ThreadFilterMessage 事件的處理常式會執行下列步驟:

  1. 使用 IMessageFilter 介面篩選訊息。

  2. 呼叫 Control.PreProcessMessage 方法。

  3. 視需要轉譯和分派訊息。

  4. 將訊息傳送至裝載控制項 (若無其他控制項可以處理訊息)。

IKeyboardInputSink 實作

Surrogate 訊息迴圈會負責處理鍵盤管理。因此,IKeyboardInputSink.TabInto 方法是唯一需要在 WindowsFormsHost 類別中實作的 IKeyboardInputSink 成員。

根據預設,HwndHost 類別會針對其 IKeyboardInputSink.TabInto 實作傳回 false。如此可防止透過 Tab 鍵從 WPF 控制項移至 Windows Form 控制項。

IKeyboardInputSink.TabInto 方法的 WindowsFormsHost 實作會執行下列步驟:

  1. 尋找 WindowsFormsHost 控制項所包含且可接收焦點的第一個或最後一個 Windows Form 控制項。控制項的選擇是根據周遊資訊而定。

  2. 將焦點設到控制項上,並傳回 true。

  3. 如果沒有控制項可接收焦點,則傳回 false。

WindowsFormsHost 註冊

當建立 WindowsFormsHost 控制項的視窗控制代碼 (Window Handle) 時,WindowsFormsHost 控制項會呼叫可以將自己註冊到訊息迴圈中的內部靜態方法。

在註冊期間,WindowsFormsHost 控制項會檢查訊息迴圈。如果訊息迴圈尚未啟動,則會建立 ComponentDispatcher.ThreadFilterMessage 事件處理常式。附加 ComponentDispatcher.ThreadFilterMessage 事件處理常式後,訊息迴圈會被視為執行中。

當視窗控制代碼被終結時,WindowsFormsHost 控制項即會將自己從註冊中移除。

ElementHost 鍵盤與訊息處理

當由 Windows Form 應用程式裝載時,WPF 鍵盤與訊息處理包含下列項目:

下列章節將進一步說明這些部分。

介面實作

在 Windows Form 中,鍵盤訊息會傳送至具有焦點之控制項的視窗控制代碼。在 ElementHost 控制項中,這些訊息會傳送至裝載的項目。為了完成這項作業,ElementHost 控制項會提供 HwndSource 執行個體。如果 ElementHost 控制項具有焦點,HwndSource 執行個體即會傳送大部分的鍵盤輸入,使其可由 WPFInputManager 類別處理。

HwndSource 類別會實作 IKeyboardInputSinkIKeyboardInputSite 介面。

若要與鍵盤互通,必須實作 OnNoMoreTabStops 方法,以處理可以將焦點移出裝載的項目的 TAB 鍵與方向鍵。

Tab 切換與方向鍵

Windows Form 選取邏輯會對應至 IKeyboardInputSink.TabIntoOnNoMoreTabStops 方法,以實作 TAB 鍵與方向鍵巡覽。覆寫 Select 方法即可達成此對應。

命令鍵與對話方塊按鍵

為了提供 WPF 先處理命令鍵與對話方塊按鍵的機會,Windows Form 命令處理已連接至 TranslateAccelerator 方法。覆寫 Control.ProcessCmdKey 方法即可連接至這兩項技術。

透過 TranslateAccelerator 方法,受裝的載項目可以處理任何按鍵訊息,如 WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN 或 WM_SYSKEYUP,包括 TAB、ENTER、ESC 與方向鍵等命令鍵。如果沒有處理按鍵訊息,則會將其傳送至 Windows Form 祖系階層以進行處理。

快速鍵處理

若要正確處理快速鍵,Windows Form 快速鍵處理必須已連接至 WPFAccessKeyManager 類別。此外,所有 WM_CHAR 訊息也都必須正確傳送至裝載的項目。

由於 TranslateChar 方法的 HwndSource 預設實作會傳回 false,因此 WM_CHAR 訊息會以下列邏輯進行處理:

  • 覆寫 Control.IsInputChar 方法,以確保所有 WM_CHAR 訊息都會轉寄至裝載的項目。

  • 如果按下 ALT 鍵,則訊息為 WM_SYSCHAR。Windows Form 不會透過 IsInputChar 方法前置處理這個訊息。因此,ProcessMnemonic 方法會被覆寫,以向 WPFAccessKeyManager 查詢已註冊的快速鍵。如果找到已註冊的快速鍵,則 AccessKeyManager 會加以處理。

  • 如果未按 ALT 鍵,則 WPFInputManager 類別會處理未處理的輸入。如果輸入的是快速鍵,則 AccessKeyManager 會加以處理。如果是未處理的 WM_CHAR 訊息,則會處理 PostProcessInput 事件。

當使用者按 ALT 鍵時,整個表單上都會顯示快速鍵視覺提示。為了支援這項行為,無論哪個控制項具有焦點,作用中表單上所有的 ElementHost 控制項都會接收 WM_SYSKEYDOWN 訊息。

訊息只會傳送至作用中表單內的 ElementHost 控制項。

請參閱

概念

逐步解說:在 Windows Presentation Foundation 中裝載 Windows Form 複合控制項

逐步解說:在 Windows Form 中裝載 Windows Presentation Foundation 控制項

WPF 和 Win32 互通性概觀

參考

EnableWindowsFormsInterop

EnableModelessKeyboardInterop

ElementHost

WindowsFormsHost