TN006: Mapas de mensagem

Esta anotação descreve o recurso de mapa de mensagem do MFC.

O problema

Microsoft Windows implementa funções virtuais nas classes de janela usam o recurso de mensagens.Devido ao grande número de mensagens envolvidos, fornecer uma função virtual separada para cada mensagem do Windows criaria uma vtable proibitivamente grande.

Porque o número de mensagens do Windows definidas pelo sistema muda ao longo do tempo e mapas de mensagem porque os aplicativos podem definir suas próprias mensagens do Windows, fornecem um nível de indireção que impede que alterações na interface quebra código existente.

Visão Geral

MFC fornece uma alternativa para a instrução switch que foi usada em programas baseados no Windows tradicionais mensagens enviadas para uma janela.O mapeamento de mensagens para métodos pode ser definido para que quando uma mensagem é recebida por uma janela, o método apropriado é chamado automaticamente.Esse recurso de mapa da mensagem é projetado para se parecer com funções virtuais mas tem benefícios adicionais não é possíveis com funções virtuais do C++.

Definindo um mapa da mensagem

O DECLARE_MESSAGE_MAP macro declara três membros de uma classe.

  • Um conjunto particular de AFX_MSGMAP_ENTRY entradas denominadas _messageEntries.

  • Protegidos AFX_MSGMAP estrutura chamada messageMap que aponta para o _messageEntries matriz.

  • Chamada de função virtual protegido por uma GetMessageMap que retorna o endereço do messageMap.

Essa macro deve ser colocada na declaração de qualquer classe usando mapas de mensagem.Por convenção, é no final da declaração da classe.Por exemplo:

class CMyWnd : public CMyParentWndClass
{
    // my stuff...

protected:
    //{{AFX_MSG(CMyWnd)
    afx_msg void OnPaint();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

Este é o formato gerado pelo AppWizard e ClassWizard quando criarem novas classes.O / / {{e / /}} colchetes são necessários para ClassWizard.

Tabela do mapa da mensagem é definida usando um conjunto de macros que se expandem para entradas de mapa da mensagem.Uma tabela começa com uma BEGIN_MESSAGE_MAP chamada de macro, que define a classe que é tratada por esse mapa da mensagem e a classe pai à qual mensagens sem tratamento são passados.A tabela termina com o END_MESSAGE_MAP chamada de macro.

Entre essas duas macro chamadas é uma entrada para cada mensagem deve ser tratado por esse mapa da mensagem.Cada mensagem do Windows padrão tem uma macro do formulário ON_WM_MESSAGE_NAME que gera uma entrada para a mensagem.

Uma assinatura de função padrão tiver sido definida para descompactar os parâmetros de cada mensagem do Windows e fornecendo segurança de tipo.Essas assinaturas podem ser encontradas no arquivo Afxwin.h na declaração de CWnd.Cada um é marcado com a palavra-chave afx_msg para fácil identificação.

ObservaçãoObservação

ClassWizard exige que você use o afx_msg palavra-chave em suas declarações de manipulador de mapa de mensagem.

Essas assinaturas de função foram derivadas usando uma simple convenção.O nome da função sempre começa com "On".Isso é seguido pelo nome da mensagem de Windows com o "WM de _" removido e a primeira letra de cada palavra em maiúscula.A ordem dos parâmetros é wParam seguido de LOWORD(lParam), em seguida, HIWORD(lParam).Parâmetros não utilizados não são passados.Os identificadores delimitados por classes MFC são convertidos em ponteiros para os objetos adequados do MFC.O exemplo a seguir mostra como para manipular a WM_PAINT mensagem e fazer com que o CMyWnd::OnPaint função a ser chamada:

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

A tabela de mapa da mensagem deve ser definida fora do escopo de qualquer definição de função ou classe.Não deve ser colocado em bloco extern "C".

ObservaçãoObservação

ClassWizard modificará as entradas de mapa de mensagem que ocorrem entre o / / {{e / /}} colchete de comentário.

Mensagens do Windows definidos pelo usuário

As mensagens definidas pelo usuário podem ser incluídas em um mapa da mensagem usando o ON_MESSAGE macro.Essa macro aceita um número de mensagem e um método do formulário:

    // inside the class declaration
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

    #define WM_MYMESSAGE (WM_USER + 100)

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()

Neste exemplo, podemos estabelecer um manipulador para uma mensagem personalizada que tenha uma identificação de mensagem Windows derivada do padrão WM_USER base para mensagens definidas pelo usuário.O exemplo a seguir mostra como chamar esse manipulador:

CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);

O intervalo de mensagens definidas pelo usuário que usar essa abordagem deve estar no intervalo de WM_USER para 0x7fff.

ObservaçãoObservação

ClassWizard não oferece suporte à inserção de ON_MESSAGE rotinas de manipulador da interface do usuário ClassWizard.Você deverá inseri-los manualmente do editor do Visual C++.ClassWizard irá analisar essas entradas e permitem que você procure-os assim como quaisquer outras entradas de mapa da mensagem.

Registrado mensagens do Windows

O RegisterWindowMessage função é usada para definir uma nova mensagem de janela que é garantida que ser exclusivo em todo o sistema.A macro ON_REGISTERED_MESSAGE é usado para tratar essas mensagens.Essa macro aceita um nome de um UINT NEAR variável que contém a ID da mensagem windows registrado.Por exemplo

class CMyWnd : public CMyParentWndClass
{
public:
    CMyWnd();

    //{{AFX_MSG(CMyWnd)
    afx_msg LRESULT OnFind(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

static UINT NEAR WM_FIND = RegisterWindowMessage("COMMDLG_FIND");

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_REGISTERED_MESSAGE(WM_FIND, OnFind)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

A variável da ID de mensagem do Windows registrada (WM_FIND neste exemplo) deve ser um NEAR variável devido dos ON_REGISTERED_MESSAGE é implementada.

O intervalo de mensagens definidas pelo usuário que usar essa abordagem será no intervalo 0xC000 a 0xFFFF.

ObservaçãoObservação

ClassWizard não oferece suporte à inserção de ON_REGISTERED_MESSAGE rotinas de manipulador da interface do usuário ClassWizard.Você deverá inseri-los manualmente do editor de texto.ClassWizard irá analisar essas entradas e permitem que você procure-os assim como quaisquer outras entradas de mapa da mensagem.

Mensagens de comando

Mensagens de comando de menus e Aceleradores são tratadas em mapas de mensagem com o ON_COMMAND macro.Essa macro aceita um ID de comando e um método.Somente a específica WM_COMMAND mensagem tem um wParam igual ao comando especificado ID é manipulada pelo método especificado na entrada de mapa da mensagem.Funções de membro de manipulador de comando não aceitar parâmetros e retornar void.A macro tem a seguinte forma:

ON_COMMAND(id, memberFxn)

Comando atualizar mensagens são roteadas pelo mesmo mecanismo, mas usar o ON_UPDATE_COMMAND_UI macro em vez disso.Funções de membro de manipulador de atualização de comando levar um único parâmetro, um ponteiro para um CCmdUI de objeto e retornar void.A macro tem a forma

ON_UPDATE_COMMAND_UI(id, memberFxn)

Os usuários avançados podem usar o ON_COMMAND_EX macro, que é um formulário estendido de manipuladores de mensagem de comando.A macro fornece um superconjunto da ON_COMMAND funcionalidade.Funções de membro de manipulador de comando estendido levar um único parâmetro, um UINT que contém a ID de comando e retornar um BOOL.O valor de retorno deve ser TRUE para indicar que o comando foi tratado.Caso contrário, o roteamento continuará a outros objetos de destino de comando.

Exemplos dessas formas:

  • Resource.h interna (normalmente gerado pelo Visual C++)

    #define    ID_MYCMD      100
    #define    ID_COMPLEX    101
    
  • Dentro da declaração de classe

    afx_msg void OnMyCommand();
    afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
    afx_msg BOOL OnComplexCommand(UINT nID);
    
  • Dentro da definição de mapa da mensagem

    ON_COMMAND(ID_MYCMD, OnMyCommand)
    ON_UPDATE_COMMAND_UI(ID_MYCMD, OnUpdateMyCommand)
    ON_COMMAND_EX(ID_MYCMD, OnComplexCommand)
    
  • No arquivo de implementação

    void CMyClass::OnMyCommand()
    {
        // handle the command
    }
    
    void CMyClass::OnUpdateMyCommand(CCmdUI* pCmdUI)
    {
        // set the UI state with pCmdUI
    }
    
    BOOL CMyClass::OnComplexCommand(UINT nID)
    {
        // handle the command
        return TRUE;
    }
    

Usuários avançados podem lidar com uma variedade de comandos usando um único manipulador de comandos: ON_COMMAND_RANGE ou ON_COMMAND_RANGE_EX.Consulte a documentação do produto para obter mais informações sobre essas macros.

ObservaçãoObservação

ClassWizard oferece suporte à criação de ON_COMMAND e ON_UPDATE_COMMAND_UI manipuladores, mas não oferece suporte a criação de ON_COMMAND_EX ou ON_COMMAND_RANGE manipuladores.No entanto, o Assistente de classe analisar e permitem que você procurar todas as variantes de manipulador de comando quatro.

Mensagens de notificação de controle

Mapeiam de mensagens que são enviadas de controles filho em uma janela tem um extra bit de informações na sua mensagem de entrada: identificação. do controleO manipulador de mensagem especificado em uma entrada de mapa de mensagem é chamado somente se as seguintes condições forem verdadeiras:

  • O código de notificação de controle (palavra alta de lParam), como BN_CLICKED, coincide com o código de notificação especificado na entrada do mapa da mensagem.

  • A ID do controle (wParam) corresponde à identificação do controle especificada na entrada de mapa da mensagem.

Mensagens de notificação de controle personalizado podem usar o ON_CONTROL macro para definir uma entrada de mapa de mensagem com um código de notificação personalizada.Esta macro tem a forma

ON_CONTROL(wNotificationCode, id, memberFxn)

Para uso avançado de ON_CONTROL_RANGE pode ser usado para manipular uma notificação de controle específico de um intervalo de controles com o mesmo manipulador.

ObservaçãoObservação

ClassWizard não oferece suporte para a criação de um ON_CONTROL ou ON_CONTROL_RANGE manipulador da interface do usuário.Você deverá inseri-los manualmente com o editor de texto.ClassWizard irá analisar essas entradas e permitem que você procure-os assim como quaisquer outras entradas de mapa da mensagem.

Controles comuns do Windows usar mais poderoso WM_NOTIFY para notificações de controle complexos.Esta versão do MFC tem suporte direto para esta nova mensagem usando o ON_NOTIFY e ON_NOTIFY_RANGE macros.Consulte a documentação do produto para obter mais informações sobre essas macros.

Consulte também

Outros recursos

Notas técnicas por número

Notas técnicas por categoria