Question

Nous développons actuellement un contrôle d'interface utilisateur dans WPF à utiliser dans un moteur d'application Windows Forms / MFC existant (Rhino 3D).

Le moteur d'application expose la possibilité de créer un " Dockbar " qui vous permet essentiellement de placer des contrôles Windows Forms dans une fenêtre enfant pouvant s’ancrer dans l’interface Engines.

J'essaie de placer une simple zone de texte WPF dans un contrôle ElementHost, qui est ajouté au Dockbar. Cela semble bien fonctionner à première vue; mais après avoir tenté de taper dans la zone de texte, seules certaines séquences apparaissent dans la zone de texte. Les travaux SUPPRIMER , RETOUR ARRIÈRE , COPY , COLLER et SÉLECTION DE TEXTE . Si vous tapez A-Z, 1-9, etc., ces touches ne s'affichent pas.

J'ai parcouru le réseau et entendu parler de ElementHost.EnableModelessKeyboardInterop () , mais cela ne s'applique qu'aux fenêtres WPF créées à partir du formulaire. Je crée seulement WPF UserControls et les héberge dans le contrôle ElementHost.

J'ai vu un article qui parlait de Dispatcher.Run (), et cela fonctionne, mais casse le reste du formulaire:

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

Les événements PreviewKeyUp , PreviewKeyDown , KeyUp et KeyDown sont tous déclenchés par la zone de texte, mais hélas non. le texte apparaît dans la zone de texte.

Je ne connais pas grand chose aux messages Windows, mais en utilisant WinSpector, j’ai remarqué qu’aucun message WM_GETTEXT ne provenait de la zone de texte (même s’ils devraient l'être, je ne sais pas).

J'ai également créé un nouveau projet Windows Forms et fait la même chose. Cela fonctionne bien. Cela doit donc être un problème de création et d’ancrage des fenêtres dans le moteur 3D de Rhino.

Voici l'exemple de code qui ne fonctionne pas:

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);
Était-ce utile?

La solution

Je l'ai finalement compris après 2 jours de maux de tête ...

La fenêtre de dialogue MFC recevait les messages WM_CHAR et empêchait le contrôle de gérer les entrées. Donc, pour éviter cela, j'attache le HwndSource et chaque fois que je reçois le message WM_GETDLGCODE , je réponds avec les types d'entrées à accepter, puis marque l'événement comme géré. .

J'ai créé ma propre zone de texte afin d'éviter de devoir corriger tous les champs de texte (voir ci-dessous):

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

Autres conseils

Consultez ma propre question à propos de cette même chose. en fin de compte, tout ce dont vous avez besoin est quelque chose comme ceci:

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

Pourquoi ma zone de texte WPF " kinda " en lecture seule?

J'ai un problème similaire avec une fenêtre parent wxWidgets et des contrôles WPF TextBox incorporés. J'ai constaté que, bien que la connexion de ChildHwndSourceHook résolve le problème de la non entrée au clavier, je me suis retrouvé avec des espaces dupliqués occasionnels. Il semble que le message WM_KEYDOWN traite les espaces de manière fiable, mais un message WM_CHAR en double est également reçu pour certains des espaces. Pour résoudre ce problème, j'ai ajouté la clause suivante au corps de la fonction ChildHwndSourceHook, qui ignore simplement le caractère d'espace 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;
        }

Il n'est pas nécessaire de créer une zone de texte dérivée. Le code pour IOTextBox peut être utilisé dans un UserControl hébergeant des zones de texte. Je l'ai testé avec succès avec le contrôle WPF utilisé pour la page d'options personnalisées utilisée dans le package VS2010.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top