Jas*_*son 20 wpf interop textbox elementhost
我们正在开发WPF中的UI控件,以便在现有的Windows Forms/MFC应用程序引擎(Rhino 3D)中使用.
应用程序引擎公开了创建"Dockbar"的能力,它实际上允许您将Windows窗体控件放在可以停靠到Engines接口的子窗口中.
我试图将一个简单的WPF TextBox放在一个ElementHost控件中,该控件被添加到Dockbar中.乍一看似乎工作得很好; 但在尝试输入TextBox后,只有某些序列实际显示在TextBox中.该DELETE,BACKSPACE,COPY,PASTE,并选择文本的工作.如果您键入AZ,1-9等,则这些键不会显示.
我有SCOURED网,并听说过,ElementHost.EnableModelessKeyboardInterop()但这仅适用于从表单创建的WPF Windows.我只创建WPF UserControls并在ElementHost控件中托管它们.
我看到一篇关于Dispatcher.Run()的帖子,它有点工作但是打破了表单的其余部分:
System.Windows.Threading.Dispatcher.Run();
Run Code Online (Sandbox Code Playgroud)
该PreviewKeyUp,PreviewKeyDown,KEYUP和的KeyDown事件的所有火上的文本框,但很可惜没有文字在文本框中显示出来.
我对Windows消息了解不多,但是使用WinSpector我注意到没有WM_GETTEXT消息来自TextBox(如果它们甚至应该是我不知道的话).
我还创建了一个新的Windows窗体项目,并在那里做了同样的事情,它工作正常,所以它必须是如何在Rhino 3D引擎中创建和停靠窗口的问题.
以下是不起作用的示例代码:
ElementHost el = new ElementHost();
System.Windows.Controls.TextBox t = new System.Windows.Controls.TextBox();
t.Width = 100;
t.Text = "TEST";
el.Child = t;
panel1.Controls.Add(el);
Run Code Online (Sandbox Code Playgroud)
Jas*_*son 22
经过2天的头部散射,我终于想通了......
MFC对话窗口正在捕获WM_CHAR消息并阻止控件处理输入.所以为了防止这种情况,我挂钩了HwndSource,每当收到WM_GETDLGCODE消息时,我都会回复接受的输入类型,然后将事件标记为已处理.
我创建了自己的TextBox,以防止必须修复每个文本框(见下文):
/// <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;
}
}
Run Code Online (Sandbox Code Playgroud)
Rus*_*uss 10
看看我自己关于这个问题的问题.最后,你需要的只是这样的:
Window window1 = new Window();
ElementHost.EnableModelessKeyboardInterop(window1);
window1.Show();
Run Code Online (Sandbox Code Playgroud)
我有一个与wxWidgets父窗口和嵌入式WPF TextBox控件类似的问题.我发现虽然附加ChildHwndSourceHook确实解决了没有接收键盘输入的问题,但我最终偶尔会出现重复的空格字符.似乎WM_KEYDOWN消息可靠地处理空格字符,但是对于某些空格也接收到重复的WM_CHAR消息.为了解决这个问题,我在ChildHwndSourceHook函数的主体中添加了以下子句,它只是忽略了WM_CHAR空格字符:
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;
}
Run Code Online (Sandbox Code Playgroud)
没有必要创建派生的TextBox.IOTextBox的代码可以在UserControl托管文本框中使用.我已成功使用WPF控件对其进行测试,该控件用于VS2010包中使用的自定义选项页面.