Esta anotação técnica descreve Reflexo de mensagem, um novo recurso no MFC 4.0. Ele também contém instruções para criar um simple Controlarar reutilizável que usa mensagem reflexo.
Esta nota técnica não discute o reflexo de mensagem como ele se aplica a controles ActiveX (anteriormente chamado de controles OLE). Por favor, consulte o artigo controles ActiveX: subclassificação um Controlarar do Windows no Guia do programador do Visual C++.
O que é reflexo de mensagem?
Controles de Windows com freqüência enviam mensagens de notificação para suas janelas pai. Por exemplo, muitos controles de enviam uma mensagem de notificação de cor controle (WM_CTLCOLOR ou uma de suas variantes) para seu pai para permitir que o pai para fornecer um pincel de pintura de segundo plano do controle.
No Windows e no MFC anteriores à versão 4.0, o janela pai, muitas vezes, uma caixa de diálogo, é responsável pelo processamento dessas mensagens. Isso significa que o código para manipular a mensagem deve ser da classe da janela pai e que ela tem de ser repetido em todas as classes que precisam lidar com essa mensagem. No caso acima, cada caixa de diálogo que queria controles com fundos personalizados teria de lidar com a mensagem de notificação do Controlarar color. Seria muito mais fácil de reutilizar código se uma classe de controle poderia ser escrita que iria lidar com sua própria cor de plano de fundo.
No MFC 4.0, o mecanismo antigo ainda funciona — janelas pai podem tratar mensagens de notificação. Além disso, no entanto, MFC 4.0 facilita a reutilização, fornecendo um recurso chamado "mensagem da reflexão" que permite que essas mensagens de notificação para serem manipulados na janela de controle filho ou janela pai, ou em ambos. No exemplo de cor de plano de fundo de controle, agora você pode gravar uma classe de controle que define sua cor de plano de fundo por Manipulação o refletido mensagem WM_CTLCOLOR — tudo isso sem contar com o pai. (Note que uma vez que o reflexo de mensagem é implementado pelo MFC, não pelo Windows, a classe de janela pai deve ser derivada de CWnd para reflexo de mensagem para trabalhar).
Versões mais antigas do MFC fizeram algo semelhante para reflexão de mensagem, fornecendo funções virtuais para algumas mensagens, como mensagens para caixas de listagem desenhado proprietário (WM_DRAWITEMe assim por diante). O novo mecanismo de reflexo de mensagem é generalizada e consistente.
Reflexo de mensagem é compatível com o código escrito para versões do MFC anterior à 4.0.
Se você tiver fornecido um manipulador para uma mensagem específica ou para um intervalo de mensagens, na classe da sua janela pai, ele irá substituir refletido mensagem manipuladores para a mesma mensagem desde que você não chame a função de manipulador de classe base em seu próprio manipulador. Por exemplo, se você manipular WM_CTLCOLOR na sua classe de caixa de diálogo, seu tratamento irá substituir quaisquer manipuladores de mensagem refletido.
Se, na sua classe de janela pai, você fornecer um manipulador para uma mensagem WM_NOTIFY específica ou um intervalo de mensagens WM_NOTIFY , seu manipulador será chamado somente se o Controlarar filho enviando essas mensagens não tem um manipulador de mensagem refletido através de ON_NOTIFY_REFLECT(). Se você usar ON_NOTIFY_REFLECT_EX() em seu mapa da mensagem, o manipulador mensagem pode ou pode não permitir a janela pai para manipular a mensagem. Se o manipulador retorna TRUE, a mensagem será manipulada pelo pai, bem como, enquanto um chamar retorna falso não permite que o pai para segurá-lo. O refletido mensagem é feita antes da mensagem de notificação.
Quando é enviada uma mensagem WM_NOTIFY , o controle é oferecido a primeira oportunidade de lidar com isso. Se qualquer outra refletido mensagem é enviada, a janela pai tem a primeira chance de lidar com isso e o controle receberá o refletido mensagem. Para fazer isso, ele precisará de uma função de manipulador e uma entrada apropriada no mapa da mensagem do Controlarar classe.
A macro de mapa da mensagem para mensagens Refletido é um pouco diferente para notificações regulares: tem _REFLECT acrescentado ao seu nome usual. Por exemplo, para manipular uma mensagem WM_NOTIFY no pai, você use a macro ON_NOTIFY no mapa da mensagem do pai. Para manipular a mensagem refletido no Controlarar filho, use a macro ON_NOTIFY_REFLECT no mapa da mensagem do Controlarar filho. Em alguns casos, os parâmetros são diferentes, também. Anotação 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 a novo WM_NOTIFY mensagem.
Entradas mensagem-mapa e protótipos de função de manipulador de mensagens Refletido
Para manipular uma mensagem de notificação refletido Controlar, use a mensagem mapa macros e protótipos função listados na tabela a seguir.
ClassWizard geralmente pode adicionar estas entradas de mapa da mensagem para você e fornecer implementações de esqueleto função. Consulte Definindo um manipulador de mensagem para uma mensagem refletido no Guia do programador do Visual C++ para obter informações sobre como definir manipuladores para refletido mensagens.
Para converter o nome de mensagem para o nome da macro refletido, preceder ON_ e acrescentar _REFLECT. Por exemplo, WM_CTLCOLOR torna-se ON_WM_CTLCOLOR_REFLECT. (Para ver quais mensagens podem ser refletidas, fazer a conversão oposta sobre as entradas de macro na tabela abaixo).
As três exceções à regra acima são os seguintes:
Em todos os 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 documentadas sob o nome de função ou o nome da função com em anexado. Por exemplo, CtlColor documentada no OnCtlColor. Vários manipuladores de mensagem refletido precisam menos parâmetros do que os manipuladores de semelhantes em um janela pai. Apenas corresponder 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 void ) | afx_msg voidmemberFxn ( ); |
| ON_NOTIFY_REFLECT ( wNotifyCode, memberFxn void ) | afx_msg voidmemberFxn(NMHDR * pNotifyStruct, LRESULT * resultado ); |
| ON_UPDATE_COMMAND_UI_REFLECT ( memberFxn void ) | afx_msg voidmemberFxn(CCmdUI * pCmdUI ); |
| (ON_WM_CTLCOLOR_REFLECT) | afx_msg CtlColor HBRUSH (CDC * pDC, UINT nCtlColor ); |
| (ON_WM_DRAWITEM_REFLECT) | afx_msg void DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct ); |
| (ON_WM_MEASUREITEM_REFLECT) | afx_msg void MeasureItem (LPMEASUREITEMSTRUCT lpMeasureItemStruct ); |
| (ON_WM_DELETEITEM_REFLECT) | afx_msg void DeleteItem (VOIDLPDELETEITEMSTRUCT voidlpDeleteItemStruct ); |
| (ON_WM_COMPAREITEM_REFLECT) | int afx_msg CompareItem (LPCOMPAREITEMSTRUCT lpCompareItemStruct ); |
| (ON_WM_CHARTOITEM_REFLECT) | int afx_msg CharToItem (UINT nKey, UINT nIndex ); |
| (ON_WM_VKEYTOITEM_REFLECT) | int afx_msg VKeyToItem (UINT nKey, UINT nIndex ); |
| (ON_WM_HSCROLL_REFLECT) | afx_msg void HScroll (UINT voidnSBCodeUINT, UINT nPos ); |
| (ON_WM_VSCROLL_REFLECT) | afx_msg void VScroll (UINT voidnSBCodeUINT, UINT nPos ); |
| (ON_WM_PARENTNOTIFY_REFLECT) | afx_msg void ParentNotify (UINT , LPARAM da mensagem lParam ); |
O ON_NOTIFY_REFLECT e ON_CONTROL_REFLECT macros têm variações que permitem que mais de um objeto (por exemplo, o Controlarar e seu pai) para lidar com uma determinada mensagem.
| Entrada de mapa | Protótipo de função |
| ON_NOTIFY_REFLECT_EX ( wNotifyCode, memberFxn void ) | afx_msg BOOLmemberFxn(NMHDR * pNotifyStruct, LRESULT * resultado ); |
| ON_CONTROL_REFLECT_EX ( wNotifyCode, memberFxn void ) | afx_msg BOOLmemberFxn ( ); |
Manipulação refletido mensagens: Um exemplo de um Controlarar reutilizável
Este simple exemplo cria um Controlarar reutilizável chamado CYellowEdit . O controle funciona da mesma como um controle de edição regular, exceto que ele exibe texto preto sobre um fundo amarelo. É fácil adicionar funções de membro que permitam a CYellowEdit controle para exibir cores diferentes.
Para testar este exemplo, execute os seguintes passos:
Você deve ter um aplicativo que permite desenvolver o Controlarar reutilizável. Se você não tiver um aplicativo existente para usar, criar um aplicativo baseado em caixa de diálogo usando AppWizard.
CYellowEdit com base no CEdit. Deixe a caixa "Adicionar à Galeria de componente" verificada.CYellowEdit classe. Os dois primeiros serão COLORREF variáveis para manter a cor do texto e a cor de fundo. O terceiro será um objeto de CBrush que irá armazenar o pincel de pintura de segundo plano. O objeto de CBrush permite que você para criar o pincel uma vez, apenas referência a ele depois disso e para destruir o pincel automaticamente quando o CYellowEdit controle é destruído.CYellowEdit::CYellowEdit()
{
m_clrText = RGB (0, 0, 0);
m_clrBkgnd = RGB (255, 255, 0);
m_brBkgnd.CreateSolidBrush (m_clrBkgnd);
}
CYellowEdit classe. Observe que o sinal de igual na frente do nome de mensagem na lista de mensagens que você pode manipular indica que a mensagem é refletida. Isso é descrito em Definindo um manipulador de mensagem para uma mensagem refletido no Guia do programador do Visual C++.ClassWizard adiciona a seguinte função de macro e esqueleto de mapa da mensagem para você:
ON_WM_CTLCOLOR_REFLECT()
/ / Nota: outro código será entre....
HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) {
/ / TODO: alterar quaisquer atributos do DC aqui
/ / TODO: retornar um pincel não-NULL, se o
/ / manipulador do pai não deve ser chamado
retornar NULL;
}
pDC-gt;SetTextColor (m_clrText); / / texto
pDC - > SetBkColor (m_clrBkgnd); / / plano de fundo do texto
retornar m_brBkgnd; / / plano de fundo do ctl
CYellowEdit controle no arquivo de cabeçalho da caixa de diálogo.CYellowEdit Controlar classe para outros projetos.Técnico anotações por número |nbsp; &Notas técnicas por categoria