TN062: Reflexo de mensagem para controles do Windows

ObservaçãoObservação

A seguinte nota técnica não foi atualizada desde que foi incluída pela primeira vez na documentação online.Como resultado, alguns procedimentos e tópicos podem estar desatualizado ou incorreto.As informações mais recentes, é recomendável que você procure o tópico de interesse no índice de documentação on-line.

Esta nota técnica descreve a reflexão de mensagem, um novo recurso no MFC 4.0.Ele também contém instruções para criar um simple controle reutilizável que usa a reflexão de mensagem.

Esta nota técnica não discute a reflexão de mensagem como ele se aplica a controles de ActiveX (anteriormente chamado de controles OLE).Consulte o artigo ActiveX controles: subclassificação um controle do Windows.

O que é o reflexo de mensagem?

Controles do Windows freqüentemente enviam mensagens de notificação para suas janelas pai.Por exemplo, muitos controles de enviar uma mensagem de notificação do controle de cor (WM_CTLCOLOR ou uma de suas variantes) a seus pais para permitir que o pai fornecer um pincel para pintar o plano de fundo do controle.

No Windows e no MFC antes da versão 4.0, a janela pai, normalmente uma caixa de diálogo é responsável pela manipulação dessas mensagens.Isso significa que o código para manipular a mensagem precisa ser da classe da janela pai e que ele tem que ser duplicada em cada classe precisa manipular a mensagem.Nesse caso, teria que cada caixa de diálogo que queria controles com planos de fundo personalizados manipular a mensagem de notificação do controle cor.Seria muito mais fácil de reutilizar código se uma classe de controle poderia ser escrita que trataria sua própria cor de plano de fundo.

No MFC 4.0, o mecanismo antigo ainda funciona — windows pai podem tratar mensagens de notificação.Além disso, no entanto, MFC 4.0 facilita a reutilização, fornecendo um recurso chamado "mensagem de reflexão" que permite que essas mensagens de notificação ser manipulado em janela de controle filho ou a janela pai ou em ambos.No exemplo de cor de plano de fundo de controle, agora você pode escrever uma classe de controle que define sua própria cor de fundo, manipulando o refletido WM_CTLCOLOR mensagem — tudo sem depender do pai.(Observe que como reflexão de mensagem é implementado pelo MFC, não pelo Windows, a classe de janela pai deve ser derivada de CWnd para reflexão mensagem funcione.)

Versões mais antigas do MFC foram algo semelhante a reflexão de mensagem, fornecendo funções virtuais para algumas mensagens, como mensagens de caixas de listagem de desenhado proprietário (WM_DRAWITEMe assim por diante).O novo mecanismo de reflexão de mensagem é generalizada e consistente.

Mensagem reflexão é compatível com o código escrito para versões do MFC antes de 4.0.

Se você tiver fornecido um manipulador para uma mensagem específica ou um intervalo de mensagens, na classe da janela de seu pai, ele substituirá refletem manipuladores de mensagens para a mesma mensagem fornecida não chamar a função de manipulador de classe base no seu próprio manipulador.Por exemplo, se você tratar WM_CTLCOLOR na sua classe de caixa de diálogo, sua manipulação substituirão quaisquer manipuladores de mensagens refletido.

Se, na sua classe de janela pai, você pode fornecer um manipulador para um determinado WM_NOTIFY mensagem ou um intervalo de WM_NOTIFY mensagens, o manipulador será chamado somente se o controle filho enviando essas mensagens não tem um manipulador de mensagem refletido por meio de ON_NOTIFY_REFLECT().Se você usar ON_NOTIFY_REFLECT_EX() em seu mapa da mensagem, seu manipulador de mensagem pode ou não permitir a janela pai para manipular a mensagem.Se retorna o manipulador FALSE, a mensagem será manipulada pelo pai, enquanto uma chamada retorna TRUE não aceita o pai lidar com ele.Observe a mensagem refletida é tratada antes da mensagem de notificação.

Quando um WM_NOTIFY mensagem é enviada, o controle é oferecido a primeira chance para lidar com ele.Se qualquer mensagem refletida é enviada, a janela pai tem a primeira chance para lidar com ele e o controle receberá a mensagem refletida.Para fazer isso, ele precisará de uma função de manipulador e uma entrada apropriada no mapa de mensagem de classe do controle.

A macro de mapa da mensagem para mensagens refletidas é ligeiramente diferente para notificações regulares: ele tem _REFLECT acrescentado ao nome usual.Por exemplo, para tratar de um WM_NOTIFY mensagem no pai, use a macro ON_NOTIFY no mapa da mensagem do pai.Para manipular a mensagem refletida no controle filho, use o ON_NOTIFY_REFLECT macro no mapa da mensagem do controle filho.Em alguns casos, os parâmetros são diferentes, também.Observe que ClassWizard geralmente pode adicionar as entradas de mapa da mensagem para você e fornecer implementações de esqueleto função com parâmetros corretos.

Consulte TN061: ON_NOTIFY e WM_NOTIFY mensagens para obter informações sobre o novo WM_NOTIFY mensagem.

Entradas de mapa da mensagem e protótipos de função de manipulador de mensagens refletidos

Para manipular uma mensagem de notificação de controle refletido, use macros de mapa da mensagem e protótipos de função listados na tabela a seguir.

ClassWizard geralmente pode adicionar essas entradas de mapa da mensagem para você e fornecer implementações de esqueleto de função.Consulte definir um manipulador de mensagem para uma mensagem refletido para informações sobre como definir manipuladores de mensagens refletidas.

Para converter o nome da macro refletida do nome da mensagem, prepend on _ e acrescentar _REFLECT.Por exemplo, WM_CTLCOLOR se torna ON_WM_CTLCOLOR_REFLECT.(Para ver as mensagens que podem ser refletidas, fazer a conversão oposta nas entradas de macro na tabela abaixo).

As três exceções à regra acima são:

  • A macro WM_COMMAND notificações é ON_CONTROL_REFLECT.

  • A macro WM_NOTIFY reflexos é ON_NOTIFY_REFLECT.

  • A macro ON_UPDATE_COMMAND_UI reflexos é ON_UPDATE_COMMAND_UI_REFLECT.

Em cada um dos casos especiais acima, você deve especificar o nome da função de membro manipulador.Em outros casos, você deve usar o nome padrão para a função do manipulador.

O significado dos parâmetros e valores de retorno das funções estão documentados em nome da função ou o nome da função com em anteposto.Por exemplo, CtlColor documentado no OnCtlColor.Vários manipuladores de mensagem refletido precisam menos parâmetros que os manipuladores semelhantes em uma janela pai.Apenas correspondem aos nomes na tabela abaixo com os nomes dos parâmetros formais na documentação.

Entrada de mapa

Protótipo de função

ON_CONTROL_REFLECT( wNotifyCode, memberFxn )

afx_msg void memberFxn ( );

ON_NOTIFY_REFLECT( wNotifyCode, memberFxn )

afx_msg void memberFxn ( NMHDR * pNotifyStruct, LRESULT* result );

ON_UPDATE_COMMAND_UI_REFLECT (memberFxn)

afx_msg void memberFxn ( CCmdUI* pCmdUI );

(ON_WM_CTLCOLOR_REFLECT)

afx_msg HBRUSH CtlColor ( CDC* pDC, UINT nCtlColor );

(ON_WM_DRAWITEM_REFLECT)

afx_msg void DrawItem (LPDRAWITEMSTRUCTlpDrawItemStruct);

(ON_WM_MEASUREITEM_REFLECT)

afx_msg void MeasureItem (LPMEASUREITEMSTRUCTlpMeasureItemStruct);

(ON_WM_DELETEITEM_REFLECT)

afx_msg void DeleteItem (LPDELETEITEMSTRUCTlpDeleteItemStruct);

(ON_WM_COMPAREITEM_REFLECT)

int afx_msg CompareItem (LPCOMPAREITEMSTRUCTlpCompareItemStruct);

(ON_WM_CHARTOITEM_REFLECT)

afx_msg int CharToItem ( UINT nKey, UINT nIndex );

(ON_WM_VKEYTOITEM_REFLECT)

afx_msg int VKeyToItem ( UINT nKey, UINT nIndex );

(ON_WM_HSCROLL_REFLECT)

afx_msg void HScroll ( UINT nSBCode, UINT nPos );

(ON_WM_VSCROLL_REFLECT)

afx_msg void VScroll ( UINT nSBCode, UINT nPos );

(ON_WM_PARENTNOTIFY_REFLECT)

afx_msg void ParentNotify ( UINT message, LPARAM lParam );

O ON_NOTIFY_REFLECT e ON_CONTROL_REFLECT macros tem variações que permitem que mais de um objeto (como o controle e seu pai) para lidar com uma determinada mensagem.

Entrada de mapa

Protótipo de função

ON_NOTIFY_REFLECT_EX( wNotifyCode, memberFxn )

afx_msg BOOL memberFxn ( NMHDR * pNotifyStruct, LRESULT* result );

ON_CONTROL_REFLECT_EX( wNotifyCode, memberFxn )

afx_msg BOOL memberFxn ( );

Tratamento Reflected mensagens: Um exemplo de um controle reutilizável

Este simple exemplo cria um controle reutilizável, chamado CYellowEdit.O controle funciona como um controle de edição regular, exceto que ele exibe texto preto em um fundo amarelo.Seria fácil adicionar funções de membro que permitem a CYellowEdit controle para exibir cores diferentes.

Para testar o exemplo cria um controle reutilizável

  1. Crie uma nova caixa de diálogo em um aplicativo existente.Para obter mais informações, consulte o editor de diálogo tópico.

    Você deve ter um aplicativo desenvolver o controle reutilizável.Se você não tiver um aplicativo existente para usar, crie um aplicativo baseado em diálogo usando AppWizard.

  2. Com seu projeto carregado no Visual C++, use ClassWizard para criar uma nova classe chamada CYellowEdit com base em CEdit.

  3. Adicionar três variáveis de membro para seu CYellowEdit classe.Os dois primeiros serão COLORREF variáveis para manter a cor do texto e a cor de plano de fundo.O terceiro será um CBrush objeto manterá o pincel para pintar o plano de fundo.O CBrush object permite você pincel uma vez, simplesmente o referenciando depois de criar e destruir o pincel automaticamente quando o CYellowEdit controle é destruído.

  4. Inicialize as variáveis de membro escrevendo o construtor da seguinte maneira:

    CYellowEdit::CYellowEdit()
    {
       m_clrText = RGB( 0, 0, 0 );
       m_clrBkgnd = RGB( 255, 255, 0 );
       m_brBkgnd.CreateSolidBrush( m_clrBkgnd );
    }
    
  5. Usar ClassWizard, adicionar um manipulador para o refletido WM_CTLCOLOR mensagem para seu CYellowEdit classe.Observe que o sinal de igual na frente do nome da mensagem na lista de mensagens, que você pode manipular indica que a mensagem é refletida.Isso é descrito em definir um manipulador de mensagem para uma mensagem refletido.

    ClassWizard adiciona a seguinte função de macro e esqueleto de mapa da mensagem para você:

    ON_WM_CTLCOLOR_REFLECT()
    
    // Note: other code will be in between....
    
    HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
    {
       // TODO: Change any attributes of the DC here
    
       // TODO: Return a non-NULL brush if the
       //   parent's handler should not be called
       return NULL;
    }
    
  6. Substitua o corpo da função com o código a seguir.O código especifica a cor do texto, a cor de plano de fundo do texto e a cor de fundo para o resto do controle.

       pDC->SetTextColor( m_clrText );   // text
       pDC->SetBkColor( m_clrBkgnd );   // text bkgnd
       return m_brBkgnd;            // ctl bkgnd
    
  7. Criar um controle de edição na caixa de diálogo e, em seguida, anexá-lo a uma variável de membro clicando duas vezes no controle de edição enquanto pressiona uma tecla de controle.Na caixa de diálogo Adicionar membro variável, o nome da variável de término e escolha "Controle" para a categoria, em seguida, "CYellowEdit" para o tipo de variável.Não se esqueça de definir a ordem de tabulação na caixa de diálogo.Além disso, certifique-se de incluir o arquivo de cabeçalho para o CYellowEdit controle no arquivo de cabeçalho da caixa de diálogo.

  8. Criar e executar seu aplicativo.Controle de edição terá um fundo amarelo.

Consulte também

Outros recursos

Notas técnicas por número

Notas técnicas por categoria