2009-05-07 15 views
19

Estamos desarrollando un control de interfaz de usuario en WPF para ser consumido dentro de un motor de aplicación Windows Forms/MFC (Rhino 3D).WPF TextBox no acepta la entrada cuando está en ElementHost en Window Forms

El motor de aplicaciones expone la capacidad de crear una "Barra Dock" que esencialmente le permite colocar controles de Windows Forms dentro de una ventana secundaria que puede acoplarse a la Interfaz de motores.

Estoy tratando de poner un WPF TextBox simple dentro de un control ElementHost, que se agrega a la Dockbar. Esto parece funcionar bien a primera vista; pero después de intentar escribir en el TextBox, solo ciertas secuencias aparecen en el TextBox. El BORRAR, RETROCESO, COPIA, PASTA, y selección de texto trabajo. Si escribe A-Z, 1-9, etc. esas teclas no aparecen.

HE ASEGURADO la red, y he oído hablar de ElementHost.EnableModelessKeyboardInterop(), pero esto solo se aplica a Windows WPF que se está creando a partir del formulario. Solo estoy creando UserControls de WPF y alojándolos en el control ElementHost.

vi un poste que habló sobre el Dispatcher.Run(), y que tipo de obras, pero rompe el resto de la forma:

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

El PreviewKeyUp, PreviewKeyDown, KeyUp y KeyDown todos los eventos se disparan en el TextBox, pero desafortunadamente no aparece texto en el TextBox.

No sé mucho sobre los mensajes de Windows, pero al usar WinSpector noté que no venían mensajes WM_GETTEXT del TextBox (si es que deberían ser, no 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 las ventanas se crean y se acoplan dentro del motor 3D de Rhino.

Aquí es el código de ejemplo 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); 

Respuesta

19

finalmente lo he descubierto después de 2 días de scatching cabeza ...

La ventana de diálogo MFC estaba tomando el WM_CHAR mensajes y evitar que el control maneje la entrada. Para evitar esto, conecto el HwndSource y cada vez que recibo el mensaje WM_GETDLGCODE respondo de nuevo con los tipos de entrada para aceptar, y luego marcó el evento como manejado.

He creado mi propio cuadro de texto con el fin de evitar tener que fijar cada caja 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; 
     } 
    } 
+0

Gracias, esto era exactamente lo que necesitaba. Lo puse en UserControl, como lo sugirió IvanH a continuación. ¡Funciona de maravilla! –

+0

Gracias! Esto surgió como un problema para nosotros hoy, ¡y esto lo resolvió rápidamente! –

9

Compruebe hacia fuera mi propia pregunta acerca de esto mismo.en el final, sin embargo, todo lo que necesita es algo como esto:

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

Why is my WPF textbox "kinda" readonly?

+3

En realidad en mi pregunta dije que su solución no se aplica, no soy una ventana, soy un UserControl dentro de ElementHost, dentro de una ventana de diálogo de MFC ... –

+3

Su derecho, mi mal. Me lo merecía por no prestar mucha atención. – Russ

6

Tengo un problema similar con una ventana primaria wxWidgets y controles TextBox de WPF embebidos. Descubrí que aunque conectar ChildHwndSourceHook resuelve el problema de no recibir información del teclado, terminé con caracteres de espacios duplicados ocasionales. Parece que el mensaje WM_KEYDOWN maneja los caracteres de espacio de manera confiable, pero también se recibe un mensaje WM_CHAR duplicado para algunos de los espacios. Para resolver este añadí 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; 
     } 
+0

Hombre, me salvaste la vida, después de 1 día de depurar ... Tengo un problema similar con la tecla enter, a veces fue enviado dos veces. WM_KEYDOWN - WM_CHAR - WM_KEYUP, esta fue la orden. "Comer" el WM_CHAR para la apariencia de Enter no causa ningún problema excepto solucionar el problema de duplicación. – Zotyi

5

No es necesario para crear TextBox derivada. El código para IOTextBox se puede usar en un UserControl hosting de cuadros de texto. Lo probé con éxito con el control WPF utilizado para la página de opciones personalizadas utilizada en el paquete VS2010.

Cuestiones relacionadas