I found a link online that sub-clases TextBox and allows keystrokes original post
I change things slightly but it is pretty much the same. It is not fully tested but keypresses are going into the textboxes.
class TextInput : 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 TextInput()
{
Loaded += delegate
{
var s = PresentationSource.FromVisual(this) as HwndSource;
s?.AddHook(ChildHwndSourceHook);
};
}
static IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg,
IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg != WM_GETDLGCODE) return IntPtr.Zero;
handled = true;
return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL);
}
}
Another angle is to create sub-class of the element host and to add the code there. That way if there is any further hook customization you can adjust in one place and it will cascade to all your wpf controls.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Interop;
using Automated.ToolWindow;
namespace Automated
{
public class MyElementHost : ElementHost
{
protected override void Dispose(bool disposing)
{
if (_contentControl != null)
{
_contentControl.Loaded -= OnContentControlOnLoaded;
_contentControl = null;
}
base.Dispose(disposing);
}
private ContentControl _contentControl;
// Hide the child element.
public new UIElement Child
{
get { return base.Child; }
set
{
_contentControl = new ContentControl();
_contentControl.Loaded += OnContentControlOnLoaded;
_contentControl.Content = value;
base.Child = _contentControl;
}
}
private void OnContentControlOnLoaded(object sender, RoutedEventArgs e)
{
var s = PresentationSource.FromVisual(_contentControl) as HwndSource;
s?.AddHook(ChildHwndSourceHook);
}
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;
static IntPtr ChildHwndSourceHook(IntPtr hwnd,
int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg != WM_GETDLGCODE) return IntPtr.Zero;
handled = true;
return new IntPtr(DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_HASSETSEL);
}
}
}
My code to add the host looks like this after the implementation.
ElementHost = new MyElementHost()
{
Child = new RootXamlControl()
};
TaskPanes.Add(_host.TaskPanes.Add((int) ElementHost.Handle, "",
TaskPaneCaption, "Auto"));
Side note, if you are writing a COM AddIn and don't pay attention to memory management you will receive a whole new appreciation for people who had to care about garbage collection. Spoken from a C#.Net developer!