Arquitetura de entrada para interoperabilidade entre Windows Forms e WPF
Interoperabilidade entre WPF e Windows Forms requer que as duas tecnologias tenham o processamento de entrada de teclado apropriado. Este tópico descreve como essas tecnologias implementam processamento de teclado e de mensagens para permitir uma suave interoperação em aplicativos híbridos.
Este tópico contém as subseções a seguir:
Formulários sem janela restrita de mudança de foco e caixas de diálogo
Processamento de teclado e de mensagens pelo WindowsFormsHost
Processamento de teclado e de mensagens pelo ElementHost
Formulários sem janela restrita de mudança de foco e caixas de diálogo
Chame o método EnableWindowsFormsInterop no elemento WindowsFormsHost para abrir um formulário ou caixa de diálogo sem janela restrita de mudança de foco de um aplicativo baseado em WPF.
Chame o método EnableModelessKeyboardInterop no controle ElementHost para abrir uma página WPF sem janela restrita de mudança de foco em um aplicativo com base em Windows Forms.
Processamento de teclado e de mensagens pelo WindowsFormsHost
Quando hospedado por um aplicativo WPF, o processamento de teclado e de mensagens Windows Forms consiste de:
A classe WindowsFormsHost adquire mensagens do loop de mensagens WPF, que é implementado pela classe ComponentDispatcher.
A classe WindowsFormsHost cria um loop de mensages Windows Forms substituto para garantir que o processamento de teclado Windows Forms comum ocorra.
A classe WindowsFormsHost implementa a interface IKeyboardInputSink para coordenar o gerenciamento de foco com o WPF.
Os controles WindowsFormsHost registram a si próprios e iniciam seus loops de mensagens.
As seções a seguir descrevem essas partes do processo em mais detalhes.
Aquisição de mensagens do loop de mensagens do Windows Presentation Foundation
A classe ComponentDispatcher implementa o gerenciador de loop de mensagens para WPF. A classe ComponentDispatcher fornece ganchos para permitir que clientes externos filtrem mensagens antes do WPF processá-las.
A implementação de interoperação trata o evento ComponentDispatcher.ThreadFilterMessage, o qual permite que os controles Windows Forms processem mensagens antes dos controles WPF.
Loop de mensagens Windows Forms substituto
Por padrão, a classe System.Windows.Forms.Application contém o loop de mensagens principal para aplicativos Windows Forms. Durante a interoperação, o loop de mensagens Windows Forms não processa mensagens. Portanto, essa lógica deve ser reproduzida. O manipulador para o evento ComponentDispatcher.ThreadFilterMessage executa os seguintes passos:
Filtra a mensagem usando a interface IMessageFilter.
Chama o método Control.PreProcessMessage.
Converte e despacha a mensagem, se for necessário.
Passa a mensagem para o controle hospedeiro, se não houverem outros controles que processem a mensagem.
Implementação do IKeyboardInputSink
O loop de mensagens substituto trata do gerenciamento de teclado. Portanto, o método IKeyboardInputSink.TabInto é o único membro de IKeyboardInputSink que requer uma implementação na classe WindowsFormsHost.
Por padrão, a classe HwndHost retorna false para sua implementação de IKeyboardInputSink.TabInto. Isso impede que se passe de um controle WPF para um controle Windows Forms usando a tecla TAB.
A implementação de WindowsFormsHost do método IKeyboardInputSink.TabInto executa as seguintes etapas:
Localiza o primeiro ou último controle Windows Forms que está contido no controle WindowsFormsHost e que possa receber o foco. A opção de que controle selecionar depende de informações de percorrimento.
Define o foco para o controle e retorna true.
Se nenhum controle pode receber o foco, retorna false.
Registro de um WindowsFormsHost
Quando o manipulador de janela de um controle WindowsFormsHost é criado, o controle WindowsFormsHost chama um método estático interno que registra sua presença no loop de mensagens.
Durante o registro, o controle WindowsFormsHost examina o loop de mensagens. Se o loop de mensagem não foi iniciado, o manipulador de eventos ComponentDispatcher.ThreadFilterMessage será criado. Se considera que o loop de mensagens está sendo executado quando o manipulador de eventos ComponentDispatcher.ThreadFilterMessage está anexado.
Quando o manipulador de janela é destruído, o controle WindowsFormsHost remove a si próprio do registro.
Processamento de teclado e de mensagens pelo ElementHost
Quando hospedado por um aplicativo Windows Forms, o processamento de teclado e de mensagens WPF consiste de:
Implementações das interfaces HwndSource, IKeyboardInputSink e IKeyboardInputSite.
Teclas de direção e de tabulação.
Teclas de comando e teclas de caixa de diálogo.
Processamento de aceleradores Windows Forms .
As seções a seguir descrevem essas partes com mais detalhes.
Implementações de interfaces
Em Windows Forms, mensagens de teclado são roteadas para o manipulador de janela do controle que tem o foco. No controle ElementHost, essas mensagens são roteadas para o elemento hospedado. Para fazer isso, o controle ElementHost fornece uma instância de HwndSource. Se o controle ElementHost tiver o foco, a instância HwndSource roteia a maioria das entradas de teclado de modo que possam ser processadas pela classe InputManager do WPF.
A classe HwndSource implementa as interfaces IKeyboardInputSink e IKeyboardInputSite.
A interoperação de teclado depende de implementa-ser o método OnNoMoreTabStops para tratar pressionamentos da tecla TAB e das teclas de direção que movam o foco para fora dos elementos hospedados.
Teclas de direção e de tabulação.
A lógica de seleção do Windows Forms é mapeada para os métodos IKeyboardInputSink.TabInto e OnNoMoreTabStops para implementar navegação pela tecla TAB e pelas teclas de direção. A substituição do método Select realiza esse mapeamento.
Teclas de comando e teclas de caixa de diálogo.
Para dar a primeira oportunidade ao WPF de processar teclas de comando e de caixas de diálogo, o pré-processamento de comandos do Windows Forms é conectado ao método TranslateAccelerator. A substituição do método Control.ProcessCmdKey conecta as duas tecnologias.
Com o método TranslateAccelerator, os elementos hospedados podem manipular qualquer mensagem de teclas, como WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN ou WM_SYSKEYUP, incluindo as teclas de comando como TAB, ENTER, ESC e teclas de direção. Se uma mensagem de tecla não é lida, ela é enviada para aos predecessores do Windows Forms na hierarquia para manipulação.
Processamento de aceleradores
Para processar aceleradores corretamente o processamento de aceleração do Windows Forms deve estar conectado à classe AccessKeyManager do WPF. Além disso, todas as mensagens WM_CHAR devem ser roteadas corretamente para os elementos hospedados.
Como a implementação padrão do método TranslateChar de HwndSource retorna false, as mensagens WM_CHAR são processadas usando a seguinte lógica:
O método Control.IsInputChar é substituído para garantir que todas as mensagens WM_CHAR são encaminhadas para elementos hospedados.
Se a tecla ALT for pressionada, a mensagem é WM_SYSCHAR. Windows Forms não pré-processar esta mensagem por meio do IsInputChar método. Portanto, o método ProcessMnemonic é substituído para consultar o AccessKeyManager do WPF para um acelerador registrado. Se um acelerador registrado for encontrado, o AccessKeyManager o processará.
Se a tecla ALT não estiver pressionada, a classe InputManager do WPF processa a entrada não tratada. Se a entrada é um acelerador, o AccessKeyManager a processará. O evento PostProcessInput é tratado para mensagens WM_CHAR que não foram processadas.
Quando o usuário pressiona a tecla ALT, dicas visuais de aceleração são mostradas no formulário inteiro. Para dar suporte a esse comportamento todos os controles ElementHost no formulário ativo recebem mensagens WM_SYSKEYDOWN, independentemente de que controle tem o foco.
As mensagens são enviadas somente a controles ElementHost no formulário ativo.
Consulte também
Conceitos
Demonstra Passo a passo: Hospedagem de um controle Windows Presentation Foundation no Windows Forms
Visão geral sobre interoperabilidade entre WPF e Win32