Windows Forms and WPF Interoperability Input Architecture
Interoperation between the WPF and Windows Forms requires that both technologies have the appropriate keyboard input processing. This topic describes how these technologies implement keyboard and message processing to enable smooth interoperation in hybrid applications.
This topic contains the following subsections:
Modeless Forms and Dialog Boxes
WindowsFormsHost Keyboard and Message Processing
ElementHost Keyboard and Message Processing
When hosted by a WPF-based application, Windows Forms keyboard and message processing consists of the following:
The WindowsFormsHost class creates a surrogate Windows Forms message loop to ensure that ordinary Windows Forms keyboard processing occurs.
The WindowsFormsHost controls register themselves and start their message loops.
The following sections describe these parts of the process in more detail.
Acquiring Messages from the Windows Presentation Foundation Message Loop
The interoperation implementation handles the ComponentDispatcher.ThreadFilterMessage event, which enables Windows Forms controls to process messages before WPF controls.
Surrogate Windows Forms Message Loop
By default, the System.Windows.Forms.Application class contains the primary message loop for Windows Forms applications. During interoperation, the Windows Forms message loop does not process messages. Therefore, this logic must be reproduced. The handler for the ComponentDispatcher.ThreadFilterMessage event performs the following steps:
The surrogate message loop handles keyboard management. Therefore, the IKeyboardInputSink.TabInto method is the only IKeyboardInputSink member that requires an implementation in the WindowsFormsHost class.
Finds the first or last Windows Forms control that is contained by the WindowsFormsHost control and that can receive focus. The control choice depends on traversal information.
Sets focus to the control and returns true.
If no control can receive focus, returns false.
During registration, the WindowsFormsHost control examines the message loop. If the message loop has not been started, the ComponentDispatcher.ThreadFilterMessage event handler is created. The message loop is considered to be running when the ComponentDispatcher.ThreadFilterMessage event handler is attached.
When the window handle is destroyed, the WindowsFormsHost control removes itself from registration.
When hosted by a Windows Forms application, WPF keyboard and message processing consists of the following:
Tabbing and arrow keys.
Command keys and dialog box keys.
Windows Forms accelerator processing.
The following sections describe these parts in more detail.
In Windows Forms, keyboard messages are routed to the window handle of the control that has focus. In the ElementHost control, these messages are routed to the hosted element. To accomplish this, the ElementHost control provides an HwndSource instance. If the ElementHost control has focus, the HwndSource instance routes most keyboard input so that it can be processed by the WPF InputManager class.
Keyboard interoperation relies on implementing the OnNoMoreTabStops method to handle TAB key and arrow key input that moves focus out of hosted elements.
Tabbing and Arrow Keys
The Windows Forms selection logic is mapped to the IKeyboardInputSink.TabInto and OnNoMoreTabStops methods to implement TAB and arrow key navigation. Overriding the Select method accomplishes this mapping.
Command Keys and Dialog Box Keys
To give WPF the first opportunity to process command keys and dialog keys, Windows Forms command preprocessing is connected to the TranslateAccelerator method. Overriding the Control.ProcessCmdKey method connects the two technologies.
With the TranslateAccelerator method, the hosted elements can handle any key message, such as WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP, including command keys, such as TAB, ENTER, ESC, and arrow keys. If a key message is not handled, it is sent up the Windows Forms ancestor hierarchy for handling.
To process accelerators correctly, Windows Forms accelerator processing must be connected to the WPF AccessKeyManager class. Additionally, all WM_CHAR messages must be correctly routed to hosted elements.
The Control.IsInputChar method is overridden to ensure that all WM_CHAR messages are forwarded to hosted elements.
If the ALT key is pressed, the message is WM_SYSCHAR. Windows Forms does not preprocess this message through the IsInputChar method. Therefore, the ProcessMnemonic method is overridden to query the WPF AccessKeyManager for a registered accelerator. If a registered accelerator is found, AccessKeyManager processes it.
If the ALT key is not pressed, the WPF InputManager class processes the unhandled input. If the input is an accelerator, the AccessKeyManager processes it. The PostProcessInput event is handled for WM_CHAR messages that were not processed.
When the user presses the ALT key, accelerator visual cues are shown on the whole form. To support this behavior, all ElementHost controls on the active form receive WM_SYSKEYDOWN messages, regardless of which control has focus.
Messages are sent only to ElementHost controls in the active form.