Windows Forms e arquitetura de entrada da interoperabilidade do WPF

A interoperação entre o WPF e o Windows Forms requer que ambas as tecnologias tenham o processamento de entrada de teclado apropriado. Este tópico descreve como essas tecnologias implementam o processamento de mensagens e teclado para permitir uma interoperação suave em aplicativos híbridos.

Este tópico contém as seguintes subseções:

  • Formulários sem janela restrita e caixas de diálogo

  • Processamento de mensagens e teclado de WindowsFormsHost

  • Processamento de mensagens e teclado de ElementHost

Formulários sem janela restrita e caixas de diálogo

Chame o EnableWindowsFormsInteropWindowsFormsHost método no elemento para abrir um formulário sem janela restrita ou uma caixa de diálogo de um aplicativo baseado em WPF.

Chame o EnableModelessKeyboardInteropElementHost método no controle para abrir uma página WPF sem janela restrita em um aplicativo baseado no Windows Forms.

Processamento de mensagens e teclado de WindowsFormsHost

Quando hospedado por um aplicativo baseado em WPF, o teclado do Windows Forms e o processamento de mensagens consistem no seguinte:

As seções a seguir descrevem essas etapas do processo em mais detalhes.

Adquirindo mensagens do loop de mensagens do WPF

A ComponentDispatcher classe implementa o gerenciador de loop de mensagem para WPF. A ComponentDispatcher classe fornece ganchos para permitir que clientes externos filtrem mensagens antes que o WPF as processe.

A implementação de interoperação manipula o evento, o que permite que os controles do Windows Forms processem mensagens antes dos ComponentDispatcher.ThreadFilterMessage controles WPF.

Loop de mensagens substituto dos Windows Forms

Por padrão, a System.Windows.Forms.Application classe contém o loop de mensagem principal para aplicativos do Windows Forms. Durante a interoperação, o loop de mensagem do Windows Forms não processa mensagens. Portanto, essa lógica deve ser reproduzida. O manipulador do ComponentDispatcher.ThreadFilterMessage evento executa as seguintes etapas:

  1. Filtra a mensagem usando a IMessageFilter interface.

  2. Chama o método Control.PreProcessMessage.

  3. Converte e envia a mensagem, se necessário.

  4. Passa a mensagem para o controle de host, se nenhum outro controle processar a mensagem.

Implementação de IKeyboardInputSink

O loop de mensagens substituto trata do gerenciamento do teclado. Portanto, o método é o IKeyboardInputSink.TabInto único IKeyboardInputSink membro que requer uma implementação na WindowsFormsHost classe.

Por padrão, a HwndHost classe retorna false para sua IKeyboardInputSink.TabInto implementação. Isso impede a tabulação de um controle WPF para um controle Windows Forms.

A WindowsFormsHost implementação do IKeyboardInputSink.TabInto método executa as seguintes etapas:

  1. Localiza o primeiro ou o último controle do Windows Forms contido pelo WindowsFormsHost controle e que pode receber foco. A escolha do controle depende de informações de passagem.

  2. Define o foco para o controle e retorna true.

  3. Se nenhum controle puder receber o foco, retorna false.

Registro de WindowsFormsHost

Quando o identificador de janela para um controle é criado, o controle chama um WindowsFormsHost método estático interno que registra sua presença para o WindowsFormsHost loop de mensagem.

Durante o registro, o controle examina o WindowsFormsHost loop de mensagem. Se o loop de mensagem não tiver sido iniciado, o ComponentDispatcher.ThreadFilterMessage manipulador de eventos será criado. O loop de mensagem é considerado em execução quando o ComponentDispatcher.ThreadFilterMessage manipulador de eventos é anexado.

Quando a alça da janela é destruída, o WindowsFormsHost controle se remove do registro.

Processamento de mensagens e teclado de ElementHost

Quando hospedado por um aplicativo do Windows Forms, o teclado WPF e o processamento de mensagens consistem no seguinte:

As seções a seguir descrevem essas partes em mais detalhes.

Implementações de interfaces

No Windows Forms, as mensagens de teclado são roteadas para o identificador de janela do controle que tem foco. ElementHost No controle, essas mensagens são roteadas para o elemento hospedado. Para fazer isso, o ElementHost controle fornece uma HwndSource instância. Se o ElementHost controle tiver foco, a instância roteia a HwndSource maioria das entradas do teclado para que possa ser processada pela classe WPF InputManager .

A HwndSource classe implementa as IKeyboardInputSink interfaces e IKeyboardInputSite .

A interoperação do teclado depende da implementação do método para manipular a entrada de tecla TAB e tecla de seta que move o OnNoMoreTabStops foco para fora dos elementos hospedados.

Teclas de direção e tabulação

A lógica de seleção do Windows Forms é mapeada para os IKeyboardInputSink.TabInto métodos e para implementar a navegação por tabulação e OnNoMoreTabStops tecla de seta. A substituição do Select método realiza esse mapeamento.

Teclas de comando e teclas de caixa de diálogo

Para dar ao WPF a primeira oportunidade de processar chaves de comando e chaves de diálogo, o pré-processamento de comandos do Windows Forms está conectado ao TranslateAccelerator método. Substituir o Control.ProcessCmdKey método conecta as duas tecnologias.

Com o TranslateAccelerator método, os elementos hospedados podem manipular qualquer mensagem de chave, como WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN ou WM_SYSKEYUP, incluindo teclas de comando, como TAB, ENTER, ESC e teclas de seta. Se uma mensagem de chave não for manipulada, ela será enviada até a hierarquia ancestral do Windows Forms para manipulação.

Processamento do acelerador

Para processar aceleradores corretamente, o processamento do acelerador do Windows Forms deve estar conectado à classe WPF AccessKeyManager . Além disso, todas as mensagens WM_CHAR devem ser encaminhadas corretamente para os elementos hospedados.

Como a implementação padrão HwndSource do TranslateChar método retorna false, WM_CHAR mensagens são processadas usando a seguinte lógica:

  • O Control.IsInputChar método é substituído para garantir que todas as mensagens WM_CHAR sejam encaminhadas para elementos hospedados.

  • Se a tecla ALT estiver pressionada, a mensagem será WM_SYSCHAR. Windows Forms não pré-processa essa mensagem por meio do IsInputChar método. Portanto, o método é substituído para consultar o ProcessMnemonic WPF AccessKeyManager para um acelerador registrado. Se um acelerador registrado for encontrado, AccessKeyManager processe-o.

  • Se a tecla ALT não for pressionada, a classe WPF InputManager processará a entrada não tratada. Se a entrada for um acelerador, o AccessKeyManager processa. O PostProcessInput evento é manipulado para mensagens WM_CHAR que não foram processadas.

Quando o usuário pressiona a tecla ALT, indicações visuais do acelerador são mostradas em todo o formulário. Para oferecer suporte a esse comportamento, todos os ElementHost controles no formulário ativo recebem mensagens de WM_SYSKEYDOWN, independentemente de qual controle tem foco.

As mensagens são enviadas somente para ElementHost controles no formulário ativo.

Confira também