Compartilhar via


Arquitetura de entrada de interoperabilidade do Windows Forms e 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 teclado e mensagens para habilitar a interoperação suave em aplicativos híbridos.

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

  • Formulários não Modais e Caixas de Diálogo

  • Processamento de mensagens e teclado do WindowsFormsHost

  • Processamento de mensagens e teclado ElementHost

Formulários Sem Moldura e Caixas de Diálogo

Chame o método EnableWindowsFormsInterop no elemento WindowsFormsHost para abrir um formulário de modelagem ou caixa de diálogo de um aplicativo baseado em WPF.

Chame o método EnableModelessKeyboardInterop no controle ElementHost para abrir uma página do WPF modeless em um aplicativo baseado em Windows Forms.

Processamento de mensagens e teclado do WindowsFormsHost

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

As seções a seguir descrevem essas partes do processo com mais detalhes.

Adquirindo mensagens do Loop de Mensagens do WPF

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 que o WPF as processe.

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

Loop de mensagens substituto dos Windows Forms

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

  1. Filtra a mensagem usando a interface IMessageFilter.

  2. Chama o método Control.PreProcessMessage.

  3. Converte e expedi a mensagem, se ela for necessária.

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

Implementação de IKeyboardInputSink

O loop de mensagem alternativa manipula o gerenciamento de teclado. Portanto, o método IKeyboardInputSink.TabInto é o único membro 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 a tabulação de um controle WPF para um controle do Windows Forms.

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

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

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

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

Registro do WindowsFormsHost

Quando o identificador de janela para um controle do tipo 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 mensagem. Se o loop de mensagem não tiver sido iniciado, o manipulador de eventos ComponentDispatcher.ThreadFilterMessage será criado. O loop de mensagem é considerado em execução quando o manipulador de eventos ComponentDispatcher.ThreadFilterMessage é anexado.

Quando o identificador da janela é destruído, o controle WindowsFormsHost se remove automaticamente do registro.

Processamento de mensagens e teclado ElementHost

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

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

Implementações de interface

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

A classe HwndSource implementa as interfaces IKeyboardInputSink e IKeyboardInputSite.

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

Teclas tabbing e seta

A lógica de seleção do Windows Forms é mapeada para os métodos IKeyboardInputSink.TabInto e OnNoMoreTabStops para implementar a navegação com TAB e teclas de seta. Sobrescrever o método Select executa 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 comando do Windows Forms está conectado ao método TranslateAccelerator. Sobrescrever o método Control.ProcessCmdKey conecta as duas tecnologias.

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

Processamento de acelerador

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

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

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

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

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

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

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

Consulte também