wpf interop textbox elementhost

WPF TextBox no acepta entrada cuando está en ElementHost en formularios de ventana



interop (4)

Echa un vistazo a mi propia pregunta sobre esta misma cosa. Al final, sin embargo, todo lo que necesitas es algo como esto:

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

¿Por qué mi cuadro de texto WPF es "un poco" de solo lectura?

Estamos desarrollando un control de UI en WPF para ser consumido dentro de un motor de aplicación de Windows Forms / MFC existente (Rhino 3D).

El motor de la aplicación expone la capacidad de crear un "Dockbar" que esencialmente le permite colocar los controles de Windows Forms dentro de una ventana secundaria que puede acoplarse a la interfaz de los motores.

Estoy intentando colocar un simple TextBox de WPF dentro de un control ElementHost, que se agrega a la barra de acoplamiento. Esto parece funcionar bien a primera vista; pero después de intentar escribir en el TextBox solo se muestran ciertas secuencias en el TextBox. El trabajo DELETE , BACKSPACE , COPY , PASTE y SELECTING TEXT . Si escribe AZ, 1-9, etc. esas teclas no aparecen.

He SCOURED the net, y he oído hablar de ElementHost.EnableModelessKeyboardInterop() pero esto solo se aplica a Windows WPF que se crea a partir del formulario. Solo estoy creando WPF UserControls y los hospedé en el control ElementHost.

Vi un post que hablaba de Dispatcher.Run (), y funciona, pero rompe el resto del formulario:

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

Los eventos PreviewKeyUp , PreviewKeyDown , KeyUp y KeyDown se activan en el TextBox, pero desgraciadamente no aparece ningún texto en el TextBox.

No sé mucho sobre los mensajes de Windows, pero al usar WinSpector noté que no venía ningún mensaje WM_GETTEXT desde el TextBox (si es que deberían estarlo, no lo sé).

También creo un nuevo proyecto de Windows Forms e hice lo mismo allí y funciona bien, por lo que debe ser un problema con la forma en que se crean y se acoplan las ventanas dentro del motor Rhino 3D.

Aquí está el código de muestra que no funciona:

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


Finalmente lo resolví después de 2 días de rascarme la cabeza ...

La ventana de diálogo de MFC estaba tomando los mensajes WM_CHAR e impidiendo que el control maneje la entrada. Así que para evitar esto, engancho el HwndSource y cada vez que recibo el mensaje WM_GETDLGCODE respondo con los tipos de entrada para aceptar, y luego marco el evento como manejado.

Creé mi propio TextBox para evitar tener que arreglar cada cuadro de texto (ver más abajo):

/// <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; } }


No es necesario crear TextBox derivado. El código para IOTextBox se puede utilizar en un cuadro de texto de alojamiento UserControl. Lo he probado con éxito con el control WPF utilizado para la página de opciones personalizadas utilizada en el paquete VS2010.


Tengo un problema similar con la ventana principal de wxWidgets y los controles incrustados WPF TextBox. Descubrí que aunque adjuntar ChildHwndSourceHook resuelve el problema de no recibir la entrada del teclado, terminé con caracteres de espacio duplicados ocasionales. Parece que el mensaje WM_KEYDOWN maneja los caracteres del espacio de manera confiable, pero también se recibe un mensaje WM_CHAR duplicado para algunos de los espacios. Para resolver esto, agregué la siguiente cláusula al cuerpo de la función ChildHwndSourceHook, que simplemente ignora el carácter de espacio 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; }