WPF TextBox在Window窗体中的ElementHost中不接受输入

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)

为什么我的WPF文本框"有点"只读?

  • 实际上在我的问题中,我说你的解决方案不适用,我不是一个窗口,我是一个ElementConost内的UserControl,在MFC对话窗口内...... (3认同)
  • 你的权利,我的坏.我当之无愧,因为没有密切关注. (3认同)

Ian*_*Ian 7

我有一个与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)


Iva*_*anH 6

没有必要创建派生的TextBox.IOTextBox的代码可以在UserControl托管文本框中使用.我已成功使用WPF控件对其进行测试,该控件用于VS2010包中使用的自定义选项页面.