Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
A nota técnica a seguir 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 desatualizados ou incorretos. Para obter as informações mais recentes, é recomendável que você pesquise o tópico de interesse no índice de documentação online.
Esta nota técnica descreve a reflexão da mensagem, um novo recurso no MFC 4.0. Ele também contém instruções para criar um controle reutilizável simples que usa reflexão de mensagem.
Esta nota técnica não discute a reflexão de mensagens, pois se aplica aos controles ActiveX (anteriormente chamados de controles OLE). Consulte o artigo Controles ActiveX: subclasse de um controle do Windows.
O que é reflexão de mensagem
Frequentemente, os controles do Windows enviam mensagens de notificação para suas janelas pai. Por exemplo, muitos controles enviam uma mensagem de notificação de cor do controle (WM_CTLCOLOR ou uma de suas variantes) para os pais para permitir que o pai forneça um pincel para pintar a tela de fundo do controle.
No Windows e no MFC antes da versão 4.0, a janela pai, geralmente uma caixa de diálogo, é responsável por lidar com essas mensagens. Isso significa que o código para lidar com a mensagem precisa estar na classe da janela pai e que ela precisa ser duplicada em todas as classes que precisam lidar com essa mensagem. No caso acima, todas as caixas de diálogo que quisessem controles com planos de fundo personalizados teriam que lidar com a mensagem de notificação da cor do controle. Seria muito mais fácil reutilizar o código se uma classe de controle pudesse ser escrita que manipulasse sua própria cor de plano de fundo.
No MFC 4.0, o mecanismo antigo ainda funciona – as janelas pai podem manipular as mensagens de notificação. Além disso, o MFC 4.0 facilita a reutilização fornecendo um recurso chamado "reflexão de mensagem", que permite que essas mensagens de notificação sejam manipuladas na janela do controle filho, na janela pai ou em ambos. No exemplo de cor da tela de fundo do controle, agora você pode escrever uma classe de controle que define a própria cor da tela de fundo manipulando a mensagem WM_CTLCOLOR refletida, tudo sem depender do pai. (Observe que, uma vez que a reflexão da mensagem é implementada pelo MFC, não pelo Windows, a classe de janela pai deve ser derivada de CWnd para que a reflexão da mensagem funcione.)
Versões mais antigas do MFC fizeram algo semelhante à reflexão de mensagens, fornecendo funções virtuais para algumas mensagens, como mensagens para caixas de listagem desenhadas pelo proprietário (WM_DRAWITEM e assim por diante). O novo mecanismo de reflexão de mensagem é generalizado e consistente.
A reflexão de mensagem é compatível com código escrito para versões do MFC anteriores à 4.0.
Se você forneceu um manipulador para uma mensagem específica ou para um intervalo de mensagens, na classe da janela pai, ele substituirá os manipuladores de mensagens refletidas pela mesma mensagem se você não chamar a função de manipulador da classe base em seu manipulador. Por exemplo, se você manipular WM_CTLCOLOR em sua classe de caixa de diálogo, sua manipulação substituirá todos os manipuladores de mensagens refletidos.
Se, em sua classe de janela pai, você fornecer um manipulador para uma mensagem WM_NOTIFY específica ou um intervalo de mensagens WM_NOTIFY, o manipulador será chamado somente se o controle filho que envia essas mensagens não tiver um manipulador de mensagens refletido por meio de ON_NOTIFY_REFLECT(). Se você usar ON_NOTIFY_REFLECT_EX() no mapa de mensagens, o manipulador de mensagens poderá ou não permitir que a janela pai manipule a mensagem. Se o manipulador retornar FALSE, a mensagem também será tratada pelo pai, enquanto uma chamada que retorna TRUE não permite que o pai a manipule. Observe que a mensagem refletida é tratada antes da mensagem de notificação.
Quando uma mensagem WM_NOTIFY é enviada, o controle tem a primeira oportunidade de lidar com ela. Se qualquer outra mensagem refletida for enviada, a janela pai terá a primeira chance de manipulá-la 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 mensagens de classe do controle.
A macro de mapa de mensagens para mensagens refletidas é ligeiramente diferente das notificações regulares: _REFLECT é acrescentado ao seu nome habitual. Por exemplo, para manipular uma mensagem WM_NOTIFY no pai, use a macro ON_NOTIFY no mapa de mensagens do pai. Para manipular a mensagem refletida no controle filho, use a macro ON_NOTIFY_REFLECT no mapa de mensagens do controle filho. Em alguns casos, os parâmetros também são diferentes. Observe que o ClassWizard geralmente pode adicionar as entradas de mapa de mensagens para você e fornecer implementações de função esqueleto com parâmetros corretos.
Consulte TN061: mensagens de ON_NOTIFY e WM_NOTIFY para obter informações sobre a nova mensagem de WM_NOTIFY.
Entradas de mapa de mensagens e protótipos de função de manipulador para mensagens refletidas
Para lidar com uma mensagem de notificação de controle refletida, use as macros de mapa de mensagens e os protótipos de função listados na tabela abaixo.
Geralmente, ClassWizard pode adicionar essas entradas de mapa de mensagens para você e fornecer implementações de função esqueleto. Consulte Definir um Manipulador de Mensagens para uma Mensagem Refletida para obter informações sobre como definir manipuladores para mensagens refletidas.
Para converter do nome da mensagem para o nome da macro refletida, acrescente ON_ e acrescente _REFLECT. Por exemplo, WM_CTLCOLOR se torna ON_WM_CTLCOLOR_REFLECT. (Para ver quais mensagens podem ser refletidas, faça a conversão oposta nas entradas de macro na tabela abaixo.)
As três exceções à regra acima são as seguintes:
A macro ON_CONTROL_REFLECT é utilizada para notificações de WM_COMMAND.
A macro para reflexões de WM_NOTIFY é ON_NOTIFY_REFLECT.
A macro para reflexões de ON_UPDATE_COMMAND_UI é ON_UPDATE_COMMAND_UI_REFLECT.
Em cada um dos casos especiais acima, você precisa especificar o nome da função membro do manipulador. Nos outros casos, você deve usar o nome padrão para sua função de manipulador.
Os significados dos parâmetros e valores de retorno das funções são documentados sob o nome da função ou o nome da função precedido por On. Por exemplo, CtlColor está documentado em OnCtlColor. Vários manipuladores de mensagens refletidas precisam de menos parâmetros do que os manipuladores semelhantes em uma janela pai. Basta corresponder os nomes na tabela abaixo com os nomes dos parâmetros formais na documentação.
| Entrada do mapa | Protótipo de função |
|---|---|
ON_CONTROL_REFLECT(wNotifyCode,memberFxn) |
afx_msg nulomemberFxn( ); |
ON_NOTIFY_REFLECT(wNotifyCode,memberFxn) |
afx_msg nulomemberFxn( NMHDR*pNotifyStruct, LRESULT*resultado); |
ON_UPDATE_COMMAND_UI_REFLECT(memberFxn) |
afx_msg nulomemberFxn( CCmdUI*pCmdUI); |
| ON_WM_CTLCOLOR_REFLECT( ) |
afx_msg HBRUSH CtlColor ( CDC*pDC, UINTnCtlColor); |
| 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( ) |
afx_msg int CompareItem ( LPCOMPAREITEMSTRUCTlpCompareItemStruct); |
| ON_WM_CHARTOITEM_REFLECT( ) |
afx_msg int CharToItem ( UINTnKey, UINTnIndex); |
| ON_WM_VKEYTOITEM_REFLECT( ) |
afx_msg int VKeyToItem ( UINTnKey, UINTnIndex); |
| ON_WM_HSCROLL_REFLECT( ) |
afx_msg HScroll nulo (UINTnSBCode, UINTnPos); |
| ON_WM_VSCROLL_REFLECT( ) |
afx_msg VScroll nulo ( UINTnSBCode, UINTnPos); |
| ON_WM_PARENTNOTIFY_REFLECT( ) |
afx_msg void ParentNotify ( UINTmessage, LPARAMlParam); |
As macros ON_NOTIFY_REFLECT e ON_CONTROL_REFLECT têm variações que permitem que mais de um objeto (como o controle e seu pai) manipule uma determinada mensagem.
| Entrada do mapa | Protótipo de função |
|---|---|
ON_NOTIFY_REFLECT_EX(wNotifyCode,memberFxn) |
AFX_MSG BOOLmemberFxn( NMHDR*pNotifyStruct, LRESULT*resultado); |
ON_CONTROL_REFLECT_EX(wNotifyCode,memberFxn) |
AFX_MSG BOOLmemberFxn( ); |
Manipulando mensagens refletidas: um exemplo de um controle reutilizável
Este exemplo simples cria um controle reutilizável chamado CYellowEdit. O controle funciona da mesma forma que um controle de edição regular, exceto pelo fato de exibir texto preto em um plano de fundo amarelo. Seria fácil adicionar funções de membro que permitiriam que o CYellowEdit controle exibisse cores diferentes.
Para experimentar o exemplo que cria um controle reutilizável
Crie uma nova caixa de diálogo em um aplicativo existente. Para obter mais informações, consulte o tópico do editor de diálogo .
Você deve ter um aplicativo no qual desenvolver o controle reutilizável. Se você não tiver um aplicativo existente para usar, crie um aplicativo baseado em caixa de diálogo usando AppWizard.
Com seu projeto carregado no Visual C++, use ClassWizard para criar uma nova classe chamada
CYellowEditcom base emCEdit.Adicione três variáveis de membro à sua
CYellowEditclasse. As duas primeiras serão variáveis COLORREF para manter a cor do texto e a cor da tela de fundo. O terceiro será umCBrushobjeto que conterá o pincel para pintar a tela de fundo. OCBrushobjeto permite que você crie o pincel uma vez, apenas referenciando-o depois disso e destrua o pincel automaticamente quando oCYellowEditcontrole é destruído.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); }Usando ClassWizard, adicione um manipulador para a mensagem de WM_CTLCOLOR refletida à sua
CYellowEditclasse. 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 na definição de um manipulador de mensagens para uma mensagem refletida.ClassWizard adiciona a seguinte macro de mapa de mensagens e função esqueleto 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; }Substitua o corpo da função pelo código a seguir. O código especifica a cor do texto, a cor da tela de fundo do texto e a cor da tela de fundo para o restante do controle.
pDC->SetTextColor(m_clrText); // text pDC->SetBkColor(m_clrBkgnd); // text bkgnd return m_brBkgnd; // ctl bkgndCrie um controle de edição na caixa de diálogo e anexe-o a uma variável de membro clicando duas vezes no controle de edição enquanto mantém uma tecla de controle pressionada. Na caixa de diálogo Adicionar Variável de Membro, conclua o nome da variável e escolha "Control" para a categoria e, 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
CYellowEditcontrole no arquivo de cabeçalho da caixa de diálogo.Compile e execute seu aplicativo. O controle de edição terá um plano de fundo amarelo.