Windows Form 和 WPF 互通性輸入架構
WPF 與 Windows Forms 之間的互通需要這兩種技術都有適當的鍵盤輸入處理。 本主題描述這些技術如何實作鍵盤和訊息處理,以在混合式應用程式中啟用順暢的交互操作。
本主題包含下列子章節:
無模式表單和對話方塊
WindowsFormsHost 鍵盤和訊息處理
ElementHost 鍵盤和訊息處理
無模式表單和對話方塊
EnableWindowsFormsInterop在 元素上 WindowsFormsHost 呼叫 方法,以從 WPF 型應用程式開啟無模式表單或對話方塊。
EnableModelessKeyboardInterop呼叫 控制項上的 ElementHost 方法,以在 Windows Forms 型應用程式中開啟無模式 WPF 頁面。
WindowsFormsHost 鍵盤和訊息處理
以 WPF 為基礎的應用程式裝載時,Windows Forms 鍵盤和訊息處理包含下列專案:
類別 WindowsFormsHost 會從 WPF 訊息迴圈取得訊息,而 WPF 訊息迴圈是由 類別實作 ComponentDispatcher 。
類別 WindowsFormsHost 會建立 Surrogate Windows Forms 訊息迴圈,以確保會發生一般的 Windows Forms 鍵盤處理。
類別 WindowsFormsHost 會實作 介面, IKeyboardInputSink 以與 WPF 協調焦點管理。
控制項 WindowsFormsHost 會自行註冊並啟動其訊息迴圈。
下列各節將更詳細地說明程式的這些部分。
從 WPF 訊息迴圈取得訊息
類別 ComponentDispatcher 會實作 WPF 的訊息迴圈管理員。 類別 ComponentDispatcher 提供勾點,可讓外部用戶端在 WPF 處理訊息之前篩選訊息。
交互操作實作會處理 ComponentDispatcher.ThreadFilterMessage 事件,這可讓 Windows Forms 控制項在 WPF 控制項之前處理訊息。
Surrogate Windows Forms 訊息迴圈
根據預設,類別 System.Windows.Forms.Application 包含 Windows Forms 應用程式的主要訊息迴圈。 在交互操作期間,Windows Forms 訊息迴圈不會處理訊息。 因此,必須重現此邏輯。 事件的處理常式 ComponentDispatcher.ThreadFilterMessage 會執行下列步驟:
使用 IMessageFilter 介面篩選訊息。
如果需要,翻譯並分派訊息。
如果沒有其他控制項處理訊息,請將訊息傳遞至主控控制項。
IKeyboardInputSink 實作
Surrogate 訊息迴圈會處理鍵盤管理。 因此,方法 IKeyboardInputSink.TabInto 是唯 IKeyboardInputSink 一需要 類別中實作 WindowsFormsHost 的成員。
根據預設,類別 HwndHost 會 false
傳回其實 IKeyboardInputSink.TabInto 作。 這可防止將 TAB 鍵從 WPF 控制項移至 Windows Forms 控制項。
方法 WindowsFormsHost 的實作 IKeyboardInputSink.TabInto 會執行下列步驟:
尋找控制項所包含的 WindowsFormsHost 第一個或最後一個 Windows Forms 控制項,而且可以接收焦點。 控制項選擇取決於周遊資訊。
將焦點設定為 控制項,並傳
true
回 。如果沒有控制項可以接收焦點,則傳
false
回 。
WindowsFormsHost 註冊
建立控制項的 WindowsFormsHost 視窗控制碼時, WindowsFormsHost 控制項會呼叫內部靜態方法,以註冊訊息迴圈的存在。
在註冊期間, WindowsFormsHost 控制項會檢查訊息迴圈。 如果訊息迴圈尚未啟動,則會 ComponentDispatcher.ThreadFilterMessage 建立事件處理常式。 附加事件處理常式時 ComponentDispatcher.ThreadFilterMessage ,訊息迴圈會被視為正在執行。
當視窗控制碼終結時, WindowsFormsHost 控制項會從註冊中移除本身。
ElementHost 鍵盤和訊息處理
由 Windows Forms 應用程式裝載時,WPF 鍵盤和訊息處理包含下列各項:
索引標籤和方向鍵。
命令索引鍵和對話方塊索引鍵。
Windows Forms 加速器處理。
下列各節將更詳細地說明這些部分。
介面實作
在 Windows Forms 中,鍵盤訊息會路由傳送至具有焦點之控制項的視窗控制碼。 在 控制項中 ElementHost ,這些訊息會路由傳送至裝載的專案。 若要達成此目的, ElementHost 控制項會提供 HwndSource 實例。 ElementHost如果控制項有焦點,實例會 HwndSource 路由傳送大部分的鍵盤輸入,以便 WPF InputManager 類別處理它。
類別 HwndSource 會實作 IKeyboardInputSink 和 IKeyboardInputSite 介面。
鍵盤交互操作依賴實 OnNoMoreTabStops 作 方法來處理 TAB 鍵和方向鍵輸入,以將焦點移出託管元素。
索引標籤和方向鍵
Windows Forms 選取邏輯會對應至 IKeyboardInputSink.TabInto 和 OnNoMoreTabStops 方法,以實作 TAB 鍵和方向鍵流覽。 覆寫 Select 方法會完成此對應。
命令索引鍵和對話方塊索引鍵
若要讓 WPF 第一次有機會處理命令索引鍵和對話方塊索引鍵,Windows Forms 命令前置處理會連線到 TranslateAccelerator 方法。 覆寫 方法會 Control.ProcessCmdKey 連接這兩種技術。
TranslateAccelerator使用 方法,裝載的專案可以處理任何索引鍵訊息,例如WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN或WM_SYSKEYUP,包括 TAB、ENTER、ESC 和方向鍵等命令鍵。 如果未處理金鑰訊息,則會傳送 Windows Forms 上階階層來處理。
加速器處理
若要正確處理快速鍵,Windows Forms 加速器處理必須連線到 WPF AccessKeyManager 類別。 此外,所有WM_CHAR訊息都必須正確地路由傳送至裝載的元素。
由於 方法的預設 HwndSource 實作 TranslateChar 會 false
傳回 ,因此會使用下列邏輯來處理WM_CHAR訊息:
系統會 Control.IsInputChar 覆寫 方法,以確保所有WM_CHAR訊息都會轉送至主控元素。
如果按下 ALT 鍵,訊息就會WM_SYSCHAR。 Windows Forms 不會透過 IsInputChar 方法預先處理此訊息。 因此,會 ProcessMnemonic 覆寫 方法,以查詢已註冊的加速器的 WPF AccessKeyManager 。 如果找到已註冊的加速器, AccessKeyManager 請加以處理。
如果未按下 ALT 鍵,WPF InputManager 類別會處理未處理的輸入。 如果輸入是加速器,則會 AccessKeyManager 處理它。 針對 PostProcessInput 未處理的訊息,會處理事件WM_CHAR。
當使用者按下 ALT 鍵時,整個表單上會顯示快速鍵視覺提示。 為了支援此行為,使用中表單上的所有 ElementHost 控制項都會接收WM_SYSKEYDOWN訊息,而不論哪一個控制項都有焦點。
訊息只會傳送至 ElementHost 使用中表單中的控制項。