WPF TextBox not accepting Input when in ElementHost in Window Forms
I finally figured it out after 2 days of head scatching...
The MFC Dialog window was taking the WM_CHAR
messages and preventing the control from handling the input. So in order to prevent this, I hook the HwndSource and whenever I receive the WM_GETDLGCODE
message I respond back with the types of input to accept, and then mark the event as handled.
I created my own TextBox in order to prevent having to fix every textbox (see Below):
/// <summary> /// Interop Enabled TextBox : This TextBox will properly handle WM_GETDLGCODE Messages allowing Key Input /// </summary> class IOTextBox : TextBox { private const UInt32 DLGC_WANTARROWS = 0x0001; private const UInt32 DLGC_WANTTAB = 0x0002; private const UInt32 DLGC_WANTALLKEYS = 0x0004; private const UInt32 DLGC_HASSETSEL = 0x0008; private const UInt32 DLGC_WANTCHARS = 0x0080; private const UInt32 WM_GETDLGCODE = 0x0087; public IOTextBox() : base() { Loaded += delegate { HwndSource s = HwndSource.FromVisual(this) as HwndSource; if (s != null) s.AddHook(new HwndSourceHook(ChildHwndSourceHook)); }; } IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_GETDLGCODE) { handled = true; return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL); } return IntPtr.Zero; } }
Check out my own question about this very same thing. in the end though, all you need is something like this:
Window window1 = new Window();ElementHost.EnableModelessKeyboardInterop(window1);window1.Show();
I have a similar issue with a wxWidgets parent window and embedded WPF TextBox controls. I found that although attaching ChildHwndSourceHook does solve the problem of not receiving keyboard input, I ended up with occasional duplicate space characters. It seems the WM_KEYDOWN message handles the space characters reliably, but a duplicate WM_CHAR message is also received for some of the spaces. To solve this I added the following clause to the body of the ChildHwndSourceHook function, which simply ignores the WM_CHAR space character:
const UInt32 WM_CHAR = 0x0102; if (msg == WM_CHAR) { // avoid duplicated spaces when parent window is a native window if (wParam.ToInt32() == 32) handled = true; }