2009-05-07 15 views
19

Stiamo sviluppando un controllo dell'interfaccia utente in WPF da consumare all'interno di un motore di applicazione Windows Form/MFC esistente (Rhino 3D).WPF TextBox che non accetta Input quando si trova in ElementHost in Window Form

Il motore dell'applicazione espone la possibilità di creare una "Dockbar" che essenzialmente consente di inserire i controlli di Windows Form all'interno di una finestra secondaria che può ancorare all'interfaccia di Engines.

Sto tentando di inserire un semplice TextBox WPF all'interno di un controllo ElementHost, che viene aggiunto alla Dockbar. Questo sembra funzionare bene a prima vista; ma dopo aver tentato di digitare nel TextBox solo alcune sequenze appaiono effettivamente nel TextBox. Il DELETE, BACKSPACE, COPIA, PASTA, e selezione del testo lavoro. Se si digita A-Z, 1-9, ecc. Questi tasti non vengono visualizzati.

Ho perlustrato la rete, e ho sentito parlare la ElementHost.EnableModelessKeyboardInterop(), ma questo vale solo per WPF di Windows viene creato dal modulo. Sto solo creando UserControls di WPF e li sto ospitando nel controllo ElementHost.

ho visto un post, che ha parlato del Dispatcher.Run(), ed è una sorta di opere, ma rompe il resto del modulo:

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

Il PreviewKeyUp, PreviewKeyDown, TastoSu e gli eventi KeyDown si attivano tutti sul TextBox, ma purtroppo non viene visualizzato alcun testo nel TextBox.

Non so molto sui messaggi di Windows, ma usando WinSpector ho notato che nessun messaggio WM_GETTEXT proveniva dal TextBox (se anche dovessero essere non lo so).

Ho anche creato un nuovo progetto Windows Form e ho fatto la stessa cosa e funziona perfettamente, quindi deve essere un problema con il modo in cui le finestre vengono create e ancorate nel motore di Rhino 3D.

Ecco il codice di esempio che non funziona:

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

risposta

19

ho finalmente capito che dopo 2 giorni di scatching testa ...

La finestra di dialogo MFC stava prendendo il WM_CHAR messaggi e impedendo al controllo di gestire l'input. Quindi, per evitare ciò, collego HwndSource e ogni volta che ricevo il messaggio WM_GETDLGCODE, rispondo con i tipi di input da accettare, quindi contrassegno l'evento come gestito.

ho creato il mio TextBox al fine di evitare di dover risolvere ogni testo (vedi sotto):

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

Grazie, questo era esattamente ciò di cui avevo bisogno. L'ho inserito in UserControl, come suggerito da IvanH di seguito. Funziona come un fascino! –

+0

Grazie! Questo è diventato un problema per noi oggi e questo lo ha risolto rapidamente! –

9

Partenza alla mia domanda su questa stessa cosa.Alla fine, però, tutto ciò che serve è qualcosa di simile:

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

Why is my WPF textbox "kinda" readonly?

+3

In realtà nella mia domanda ho affermato che la tua soluzione non si applica, io non sono una finestra, sono un UserControl all'interno di un ElementHost, all'interno di una finestra di dialogo MFC ... –

+3

Your right, my bad. L'ho meritato per non aver prestato molta attenzione. – Russ

6

Ho un problema simile con una finestra padre wxWidgets ed embedded controlli TextBox WPF. Ho scoperto che sebbene il collegamento di ChildHwndSourceHook risolva il problema di non ricevere input da tastiera, ho finito con occasionali caratteri di spazio duplicato. Sembra che il messaggio WM_KEYDOWN gestisca i caratteri dello spazio in modo affidabile, ma per alcuni spazi viene anche ricevuto un messaggio WM_CHAR duplicato. Per risolvere questo ho aggiunto il seguente clausola al corpo della funzione ChildHwndSourceHook, che ignora semplicemente il carattere spazio 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

Uomo, mi hai salvato la vita, dopo 1 giorno di debug ... Ho un problema simile con il tasto invio, a volte è stato inviato due volte. WM_KEYDOWN - WM_CHAR - WM_KEYUP, questo era l'ordine. "Mangiare" l'aspetto di WM_CHAR per Invio non causa problemi se non risolvere il problema del raddoppiamento. – Zotyi

5

Non è necessario creare TextBox derivata. Il codice per IOTextBox può essere utilizzato in un UserControl che ospita caselle di testo. L'ho provato con successo con il controllo WPF utilizzato per la pagina delle opzioni personalizzate utilizzata nel pacchetto VS2010.

Problemi correlati