Текстовое поле WPF не принимает ввод, когда в ElementHost в оконных формах

мы разрабатываем элемент управления UI в WPF для использования в существующем Windows Forms / MFC application engine (Rhino 3D).

движок приложения предоставляет возможность создать "Dockbar", который по существу позволяет поместить элементы управления Windows Forms внутри дочернего окна, которое может стыковаться с интерфейсом движков.

Я пытаюсь поместить простое текстовое поле WPF внутри элемента управления ElementHost, который добавляется в Панель Dockbar. На первый взгляд это работает нормально; но после попытки ввести в текстовое поле только определенные последовательности фактически отображаются в текстовом поле. The удалить, BACKSPACE, скопировать, вставить и ВЫБОР ТЕКСТА работа. Если вы вводите A-Z, 1-9 и т. д. эти ключи не появляются.

я прочесал сеть и услышал о ElementHost.EnableModelessKeyboardInterop() но это относится только к окнам WPF, создаваемым из формы. Я только создаю WPF UserControls и размещение их в элементе управления ElementHost.

Я видел сообщение, в котором говорилось о диспетчере.Run (), и это работает, но нарушает остальную часть формы:

System.Windows.Threading.Dispatcher.Run();

на PreviewKeyUp, PreviewKeyDown, KeyUp и KeyDown события все огонь на текстовом поле, но, увы, текст не отображается в текстовом поле.

Я мало знаю о сообщениях Windows, но с помощью WinSpector я заметил, что нет WM_GETTEXT сообщения поступали из текстового поля (если они даже должны быть, я не знаю).

Я также создаю новый проект Windows Forms и сделал то же самое, и он отлично работает, поэтому должна быть проблема с тем, как окна создаются и закрепляются в 3D-движке Rhino.

вот пример кода, который не работает:

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);

4 ответов


я, наконец, понял это после 2 дней головной scatching...

диалоговое окно 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;
        }
    }

проверить мой вопрос об этом же. в конце концов, все, что вам нужно, это что-то вроде этого:

Window window1 = new Window();
ElementHost.EnableModelessKeyboardInterop(window1);
window1.Show();

Почему мое текстовое поле WPF" kinda " только для чтения?


У меня аналогичная проблема с родительским окном 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;
        }

нет необходимости создавать производное текстовое поле. Код для IOTextBox можно использовать в текстовых полях хостинга UserControl. Я успешно протестировали его с управления WPF используется для пользовательских разделе опции пакета VS2010.