Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O mapeamento de mensagens no MFC fornece uma maneira eficiente de direcionar mensagens do Windows para uma instância de objeto C++ apropriada. Exemplos de destinos de mapa de mensagens MFC incluem classes de aplicativo, classes de documento e exibição, classes de controle e assim por diante.
Os mapas de mensagens MFC tradicionais são declarados usando a macro BEGIN_MESSAGE_MAP para declarar o início do mapa de mensagens, uma entrada de macro para cada método de classe do manipulador de mensagens e, finalmente, a macro END_MESSAGE_MAP para declarar o fim do mapa de mensagens.
Uma limitação com a macro BEGIN_MESSAGE_MAP ocorre quando ela é usada em conjunto com uma classe que contém argumentos de modelo. Quando usada com uma classe de modelo, essa macro causará um erro em tempo de compilação devido aos parâmetros de modelo ausentes durante a expansão da macro. A macro BEGIN_TEMPLATE_MESSAGE_MAP foi projetada para permitir que classes contendo um único argumento de modelo declarem seus próprios mapas de mensagem.
Exemplo
Considere um exemplo em que a classe MFC CListBox é estendida para fornecer sincronização com uma fonte de dados externa. A classe fictícia é declarada CSyncListBox da seguinte forma:
// Extends the CListBox class to provide synchronization with
// an external data source
template <typename CollectionT>
class CSyncListBox : public CListBox
{
public:
CSyncListBox();
virtual ~CSyncListBox();
afx_msg void OnPaint();
afx_msg void OnDestroy();
afx_msg LRESULT OnSynchronize(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
// ...additional functionality as needed
};
A CSyncListBox classe é modelada em um único tipo que descreve a fonte de dados com a qual será sincronizada. Ele também declara três métodos que participarão do mapa de mensagens da classe: OnPaint, OnDestroy, e OnSynchronize. O OnSynchronize método é implementado da seguinte forma:
template <class CollectionT>
LRESULT CSyncListBox<CollectionT>::OnSynchronize(WPARAM, LPARAM lParam)
{
CollectionT* pCollection = (CollectionT*)(lParam);
ResetContent();
if (pCollection != NULL)
{
INT nCount = (INT)pCollection->GetCount();
for (INT n = 0; n < nCount; n++)
{
CString s = StringizeElement(pCollection, n);
AddString(s);
}
}
return 0L;
}
A implementação acima permite que a CSyncListBox classe seja especializada em qualquer tipo de classe que implemente o GetCount método, como CArray, CListe CMap. A StringizeElement função é uma função de modelo prototipada pelo seguinte:
// Template function for converting an element within a collection
// to a CString object
template<typename CollectionT>
CString StringizeElement(CollectionT* pCollection, INT iIndex);
Normalmente, o mapa de mensagens para esta classe seria definido como:
BEGIN_MESSAGE_MAP(CSyncListBox, CListBox)
ON_WM_PAINT()
ON_WM_DESTROY()
ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)
END_MESSAGE_MAP()
onde LBN_SYNCHRONIZE é uma mensagem de usuário personalizada definida pelo aplicativo, como:
#define LBN_SYNCHRONIZE (WM_USER + 1)
O mapa de macro acima não será compilado, devido ao fato de que a especificação do modelo para a CSyncListBox classe estará faltando durante a expansão da macro. A macro BEGIN_TEMPLATE_MESSAGE_MAP resolve isso incorporando o parâmetro de modelo especificado no mapa de macro expandido. O mapa de mensagens para esta classe torna-se:
BEGIN_TEMPLATE_MESSAGE_MAP(CSyncListBox, CollectionT, CListBox)
ON_WM_PAINT()
ON_WM_DESTROY()
ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)
END_MESSAGE_MAP()
O seguinte demonstra o uso de exemplo da classe CSyncListBox usando um objeto CStringList:
void CSyncListBox_Test(CWnd* pParentWnd)
{
CSyncListBox<CStringList> ctlStringLB;
ctlStringLB.Create(WS_CHILD | WS_VISIBLE | LBS_STANDARD | WS_HSCROLL,
CRect(10, 10, 200, 200), pParentWnd, IDC_MYSYNCLISTBOX);
// Create a CStringList object and add a few strings
CStringList stringList;
stringList.AddTail(_T("A"));
stringList.AddTail(_T("B"));
stringList.AddTail(_T("C"));
// Send a message to the list box control to synchronize its
// contents with the string list
ctlStringLB.SendMessage(LBN_SYNCHRONIZE, 0, (LPARAM)& stringList);
// Verify the contents of the list box by printing out its contents
INT nCount = ctlStringLB.GetCount();
for (INT n = 0; n < nCount; n++)
{
TCHAR szText[256];
ctlStringLB.GetText(n, szText);
TRACE(_T("%s\n"), szText);
}
}
Para completar o teste, a StringizeElement função deve ser especializada para trabalhar com a CStringList classe:
template<>
CString StringizeElement(CStringList* pStringList, INT iIndex)
{
if (pStringList != NULL && iIndex < pStringList->GetCount())
{
POSITION pos = pStringList->GetHeadPosition();
for (INT i = 0; i < iIndex; i++)
{
pStringList->GetNext(pos);
}
return pStringList->GetAt(pos);
}
return CString(); // or throw, depending on application requirements
}
Ver também
BEGIN_TEMPLATE_MESSAGE_MAP
Tratamento e mapeamento de mensagens