TN006: Mapas de mensagem

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

O problema

Microsoft Windows implementa o que são essencialmente funções virtuais nas classes de janela usando seu mecanismo de mensagens. Devido ao grande número de mensagens envolvidos, fornecendo uma função virtual separada para cada mensagem do Windows resulta em uma vtable proibitivamente grande.

Além disso, uma vez que o número de mensagens do Windows pelo sistema muda com o tempo, e uma vez que um aplicativo específico pode querer definir algumas mensagens do Windows de seu próprio, o mecanismo mensagem-mapa fornece 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 de switch usada em programas tradicionais de Windows para lidar com mensagens enviadas para uma janela. Um mapeamento de mensagens para funções de membro pode ser definido para que quando uma mensagem está a ser tratado por uma janela, a função de membro apropriado é chamada automaticamente. Esse recurso de mapa de Mensagemens foi projetado para ser semelhante a funções virtuais mas tem benefícios adicionais não é possíveis com funções virtuais do C++.

Definição de um mapa da mensagem

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

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:

classe CMyW&nd: CMyParentWndClass pública
{
 nbsp;  / / minhas coisas...

protegido:
    //{{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 / /}} parênteses são necessários para ClassWizard.

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

Entre essas duas macros chamadas é uma entrada para cada mensagem deve ser tratado por este mapa da mensagem. Cada mensagem do Windows padrão tem uma macro do formulário ON_WM_xxx (onde xxx é o nome da mensagem) que gera uma entrada para essa 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 tipos. Estas assinaturas podem ser encontradas no arquivo AFXWIN.H na declaração de CWnd. Cada um é marcado com a palavra afx_msg para fácil identificação.

&Notanbsp;  ClassWizard exige que você use a palavra-chave afx_msg 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". Isto é seguido pelo nome da mensagem de Windows com o WM _ removidos e somente a primeira letra de cada palavra em maiúscula. A ordem dos parâmetros é wParam seguido por LOWORD (lParam) então HIWORD(lParam). Parâmetros não utilizados não são passados. Os identificadores que são encapsulados por classes MFC são convertidos em ponteiros para os objetos adequados do MFC. O exemplo a seguir mostra como manipular a mensagem WM_PAINT e fazer com que o CMyWnd:: OnPaint função para ser chamado

BEGI&N_MESSAGE_MAP (CMyWnd, CMyParentWndClass)
 nbsp;  //{{AFX_MSG_MAP(CMyWnd)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

A tabela de mapa de mensagem deve ser definida fora do escopo de qualquer definição de função ou classe. Ele não deve ser colocado dentro de um bloco de "C" extern.

&Notanbsp;  ClassWizard irão editar as entradas de mapa de mensagem que são encontradas entre o / / {{e / /}} colchete de comentário.

Mensagens do Windows definidos pelo usuário

Mensagens definidas pelo usuário podem ser incluídas em um mapa da mensagem usando a macro ON_MESSAGE . Essa macro aceita um número de mensagem e uma função de membro do formulário:

nbsp;   / / inside a declaração de classe
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

Por exemplo:
    # define WM_MYMESSAGE (WM_USER + 100)

BEGI&N_MESSAGE_MAP (CMyWnd, CMyParentWndClass)
    ON_MESSAGE (WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()

Neste exemplo, podemos estabelecer um manipulador para uma mensagem personalizada com uma identificação de mensagem Windows derivada o padrão WM_USER base para mensagens definidas pelo usuário. Você pode chamar esse manipulador com código tais como:

PWnd CWnd * =...;
pWnd-gt;SendMessage(WM_MYMESSA&GE)

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

&Notanbsp;  ClassWizard não tem suporte para inserir ON_MESSAGE rotinas de manipulador da interface do usuário ClassWizard: você deve inseri-los manualmente do editor do Visual C++. Assim que entrar, ClassWizard analisará essas entradas e permitem que você procure-os assim como quaisquer outras entradas mensagem-mapa.

Registrado mensagens do Windows

O :: RegisterWindowMessage função é usada para definir uma Novo janela mensagem que é garantida que ser exclusivo em todo o sistema. A macro ON_REGISTERED_MESSAGE é usada para lidar com essas mensagens. Essa macro aceita um nome de um próximo variável UINT que contém os windows registrados mensagem ID. Por exemplo

classe CMyWnd: CMyParentWndClass pública
{
público:
 nbsp;  CMyWnd();

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

DECLARE_MESSAGE_MAP()
};

estático UI&NT 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 de ID da mensagem do Windows registrada (WM_FIND no exemplo acima) deve ser uma variável próximo por causa da forma que ON_REGISTERED_MESSAGE é implementada.

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

&Notanbsp;  ClassWizard não tem suporte para inserir ON_REGISTERED_MESSAGE rotinas de manipulador da interface do usuário ClassWizard, você deve inseri-los manualmente do editor de texto. Assim que entrar, ClassWizard analisará essas entradas e permitem que você procure-os assim como quaisquer outras entradas mensagem-mapa.

Mensagens de comando

Mensagens de comando de menus e aceleradores são tratadas em mapas de mensagem com a macro ON_COMMAND . Essa macro aceita um ID de comando, bem como uma função de membro. Somente a mensagem WM_COMMAND específica com um wParam igual para o comando especificado que ID é manipulado pela função de membro especificado na entrada do mapa da mensagem. Funções de membro de manipulador de comando usam sem parâmetros e retornam void. A macro tem a forma:

 ON_COMMAND (id, memberFxn)

Comando Atualizar mensagens forem roteadas através do mesmo mecanismo como manipuladores de ON_COMMAND . A macro ON_UPDATE_COMMAND_UI é usada em vez disso. Funções de membro de manipulador de comando atualização tomar um simples parâmetro, um ponteiro para um objeto de CCmdUI e retornam void. A macro tem a forma

ON_UPDATE_COMMAND_UI (id, memberFxn)

Um formulário estendido de manipuladores de mensagem de comando está disponível para usos avançados. A macro ON_COMMAND_EX é usada em vez disso e fornece um superconjunto da funcionalidade ON_COMMAND . Funções de membro de manipulador de comando estendido tomar um simples parâmetro, um UINT que contém a identificação de comando e retornam um BOOL. O retorno BOOL deve ser TRUE para indicar que o comando tiver sido Tratado, caso contrário o roteamento continuará a outros objetos de destino de comando.

Exemplos das formas acima:

Também está disponível para uso avançado é ON_COMMAND_RANGE e ON_COMMAND_RANGE_EX que permitem que você manipular uma variedade de comandos com um único manipulador de comandos. Consulte a documentação do produto para obter mais informações sobre essas macros.

&Notanbsp;  ClassWizard oferece suporte à criação ON_COMMAND e ON_UPDATE_COMMAND_UI manipuladores, mas ele não suporte criar ON_COMMAND_EX ou ON_COMMAND_RANGE manipuladores. No entanto, Assistente de classe analisará e permitem-lhe explorar todas as variantes de manipulador de comando três.

Mensagens de notificação de Controlarar

Mensagens que são enviadas de controles filho para uma janela tem um extra bit de informações na sua mensagem de mapeiam a entrada: ID. do Controlarar O manipulador de mensagem especificado em uma entrada de mapa de mensagem é chamado somente se (1) o código de notificação de Controlarar (alta palavra de lParam), tais como BN_CLICKED, coincide com o código de notificação especificado na entrada mensagem-mapa e identificação (2) controle (wParam) corresponde à identificação de Controlarar especificada na entrada mensagem-mapa.

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

ON_CONTROL (wNotificationCode, identificação, memberFxn)

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

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

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

Técnico anotações por número |nbsp; &Notas técnicas por categoria

Index