Condividi tramite


Architettura di input per l'interoperabilità di Windows Form e WPF

L'interoperabilità tra WPF e Windows Form richiede che entrambe le tecnologie abbiano l'elaborazione dell'input da tastiera appropriata. Questo argomento descrive in che modo queste tecnologie implementano l'elaborazione di tastiera e messaggi per consentire l'interoperabilità uniforme nelle applicazioni ibride.

Questo argomento contiene le sottosezioni seguenti:

  • Moduli e finestre di dialogo non modali

  • L'elaborazione della tastiera e dei messaggi di WindowsFormsHost

  • Elaborazione della tastiera e dei messaggi di ElementHost

Moduli e finestre di dialogo non modali

Chiamare il metodo EnableWindowsFormsInterop sull'elemento WindowsFormsHost per aprire una finestra o una finestra di dialogo senza blocco da un'applicazione basata su WPF.

Chiamare il metodo EnableModelessKeyboardInterop sul controllo ElementHost per aprire una pagina WPF senza finestra di dialogo in un'applicazione basata su Windows Forms.

Elaborazione della tastiera e dei messaggi in WindowsFormsHost

Se ospitato da un'applicazione basata su WPF, l'elaborazione di tastiera e messaggi di Windows Form è costituita dai seguenti elementi:

Le sezioni seguenti descrivono queste parti del processo in modo più dettagliato.

Acquisizione di messaggi dal ciclo di messaggi WPF

La classe ComponentDispatcher implementa la gestione cicli di messaggi per WPF. La classe ComponentDispatcher fornisce hook per consentire ai client esterni di filtrare i messaggi prima che WPF li elabora.

L'implementazione dell'interoperabilità gestisce l'evento ComponentDispatcher.ThreadFilterMessage, che consente ai controlli Windows Form di elaborare i messaggi prima dei controlli WPF.

Ciclo di messaggi surrogato di Windows Forms

Per impostazione predefinita, la classe System.Windows.Forms.Application contiene il ciclo di messaggi primario per le applicazioni Windows Form. Durante l'interoperabilità, il ciclo di messaggi di Windows Form non elabora i messaggi. Pertanto, questa logica deve essere riprodotta. Il gestore per l'evento ComponentDispatcher.ThreadFilterMessage esegue i passaggi seguenti:

  1. Filtra il messaggio usando l'interfaccia IMessageFilter.

  2. Chiama il metodo Control.PreProcessMessage.

  3. Converte e invia il messaggio, se necessario.

  4. Passa il messaggio al controllo host, se nessun altro controllo elabora il messaggio.

Implementazione di IKeyboardInputSink

Il ciclo di messaggi surrogati gestisce la gestione della tastiera. Pertanto, il metodo IKeyboardInputSink.TabInto è l'unico membro IKeyboardInputSink che richiede un'implementazione nella classe WindowsFormsHost.

Per impostazione predefinita, la classe HwndHost restituisce false per l'implementazione IKeyboardInputSink.TabInto. Ciò impedisce la tabulazione da un controllo WPF a un controllo Windows Forms.

L'implementazione WindowsFormsHost del metodo IKeyboardInputSink.TabInto esegue i passaggi seguenti:

  1. Trova il primo o l'ultimo controllo Windows Forms contenuto nel controllo WindowsFormsHost e in grado di ricevere lo stato attivo. La scelta del controllo dipende dalle informazioni di attraversamento.

  2. Imposta lo stato attivo sul controllo e restituisce true.

  3. Se nessun controllo può ricevere lo stato attivo, restituisce false.

Registrazione di WindowsFormsHost

Quando viene creato l'handle della finestra per un controllo WindowsFormsHost, il controllo WindowsFormsHost chiama un metodo statico interno che registra la sua presenza per il ciclo di messaggi.

Durante la registrazione, il controllo WindowsFormsHost esamina il ciclo di messaggi. Se il ciclo di messaggi non è stato avviato, viene creato il gestore eventi ComponentDispatcher.ThreadFilterMessage. Il ciclo di messaggi viene considerato in esecuzione quando il gestore eventi ComponentDispatcher.ThreadFilterMessage è collegato.

Quando l'handle della finestra viene eliminato definitivamente, il controllo WindowsFormsHost rimuove se stesso dalla registrazione.

Elaborazione di messaggi e tastiera in ElementHost

Se ospitato da un'applicazione Windows Forms, l'elaborazione della tastiera e dei messaggi WPF è costituita dagli elementi seguenti:

Le sezioni seguenti descrivono queste parti in modo più dettagliato.

Implementazioni dell'interfaccia

In Windows Form i messaggi della tastiera vengono indirizzati all'handle della finestra del controllo con stato attivo. Nel controllo ElementHost questi messaggi vengono indirizzati all'elemento ospitato. A tale scopo, il controllo ElementHost fornisce un'istanza di HwndSource. Se il controllo ElementHost ha lo stato attivo, l'istanza di HwndSource instrada la maggior parte dell'input da tastiera in modo che possa essere elaborato dalla classe WPF InputManager.

La classe HwndSource implementa le interfacce IKeyboardInputSink e IKeyboardInputSite.

L'interoperabilità della tastiera si basa sull'implementazione del metodo OnNoMoreTabStops per gestire l'input del tasto TAB e del tasto freccia che sposta lo stato attivo fuori dagli elementi ospitati.

Tasti Tab e tasti freccia

La logica di selezione di Windows Forms viene mappata ai metodi IKeyboardInputSink.TabInto e OnNoMoreTabStops per implementare la navigazione tramite tabulazione e i tasti freccia. L'override del metodo Select esegue questo mapping.

Chiavi di comando e chiavi della finestra di dialogo

Per consentire a WPF di elaborare chiavi di comando e tasti di dialogo, la pre-elaborazione dei comandi di Windows Form è connessa al metodo TranslateAccelerator. L'override del metodo Control.ProcessCmdKey connette le due tecnologie.

Con il metodo TranslateAccelerator, gli elementi ospitati possono gestire qualsiasi messaggio di tastiera, ad esempio WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN o WM_SYSKEYUP, inclusi i tasti di comando, ad esempio TAB, INVIO, ESC e frecce direzionali. Se un messaggio chiave non viene gestito, viene inviato alla gerarchia predecessore di Windows Form per la gestione.

Elaborazione tramite acceleratore

Per elaborare correttamente gli acceleratori, l'elaborazione degli acceleratori di Windows Forms deve essere connessa alla classe WPF AccessKeyManager. Inoltre, tutti i messaggi WM_CHAR devono essere indirizzati correttamente agli elementi ospitati.

Poiché l'implementazione HwndSource predefinita del metodo TranslateChar restituisce false, i messaggi WM_CHAR vengono elaborati usando la logica seguente:

  • Viene eseguito l'override del metodo Control.IsInputChar per assicurarsi che tutti i messaggi WM_CHAR vengano inoltrati agli elementi ospitati.

  • Se viene premuto IL tasto ALT, il messaggio viene WM_SYSCHAR. Windows Form non esegue la pre-elaborazione del messaggio tramite il metodo IsInputChar. Di conseguenza, il metodo ProcessMnemonic viene sovrascritto per interrogare il AccessKeyManager WPF per un acceleratore registrato. Se viene trovato un acceleratore registrato, AccessKeyManager lo elabora.

  • Se il tasto ALT non viene premuto, la classe wpf InputManager elabora l'input non gestito. Se l'input è un acceleratore, il AccessKeyManager lo elabora. L'evento PostProcessInput viene gestito per i messaggi WM_CHAR non elaborati.

Quando l'utente preme il tasto ALT, i segnali visivi dell'acceleratore vengono visualizzati nell'intero form. Per supportare questo comportamento, tutti i controlli ElementHost nel form attivo ricevono i messaggi WM_SYSKEYDOWN, indipendentemente dal controllo attivo.

I messaggi vengono inviati solo ai controlli ElementHost nel modulo attivo.

Vedere anche