Compartilhar via


Como: Criar um MAP de mensagens de uma classe de modelo

Mapeamento de mensagem no MFC oferece uma maneira eficiente para direcionar as mensagens do Windows a uma instância de objeto C++ apropriada.Classes do aplicativo, documento e exibição de classes, classes de controle e assim por diante são exemplos de MFC mensagem MAP de destinos.

Mapas de mensagem MFC tradicionais são declarados usando o BEGIN_MESSAGE_MAP macro para declarar o início do MAP da mensagem, uma entrada de macro para cada método de classe do manipulador de mensagens e, finalmente, o END_MESSAGE_MAP macro para declarar o participante do MAP da mensagem.

Uma limitação com o BEGIN_MESSAGE_MAP macro ocorre quando ele é usado em conjunto com uma classe que contém argumentos de modelo. Quando usado com uma classe de modelo, essa macro causará um erro de time de compilar devido aos parâmetros de modelo ausentes durante a expansão de macro.The BEGIN_TEMPLATE_MESSAGE_MAP macro foi projetada para permitir que mapeia de classes que contêm um argumento único modelo para declarar suas próprias mensagens.

Exemplo

Considere um exemplo em que a MFC CListBox classe é estendido para fornecer sincronização com uma fonte de dados externa.O fictíciaCSyncListBox clsistema autônomos é declarado sistema autônomo segue:

// 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
};

The CSyncListBox classe é modelado em um único tipo que descreve a fonte de dados com que serão sincronizados.Ele também declara três métodos que participarão do MAP da mensagem da classe: OnPaint, OnDestroy, and OnSynchronize.The OnSynchronize método é implementado sistema autônomo segue:

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 o CSyncListBox classe a ser especializado em qualquer tipo de classe que implementa o GetCount método, por exemplo, CArray, CList, and CMap.The StringizeElement função é uma função de modelo com protótipo 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 MAP da mensagem para essa classe seria definido sistema autônomo:

BEGIN_MESSAGE_MAP(CSyncListBox, CListBox)

ON_WM_PAINT()

ON_WM_DESTROY()

ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)

END_MESSAGE_MAP()

em que LBN_SYNCHRONIZE é uma mensagem de usuário personalizado definida pelo aplicativo, sistema autônomo:

#define LBN_SYNCHRONIZE (WM_USER + 1)

O MAP de macro acima não serão compilados, devido ao fato de que a especificação de modelo para o CSyncListBox classe será faltando durante a expansão de macro.The BEGIN_TEMPLATE_MESSAGE_MAP macro resolve esse problema, incorporando o parâmetro do modelo especificado para o MAP de macro expandidas.O MAP da mensagem para essa classe torna-se:

BEGIN_TEMPLATE_MESSAGE_MAP(CSyncListBox, CollectionT, CListBox)
   ON_WM_PAINT()
   ON_WM_DESTROY()
   ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)
END_MESSAGE_MAP()

A seguir demonstra o uso de amostra do CSyncListBox classe usando um CStringList objeto:

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 concluir o teste, o StringizeElement função deve ser especializada para trabalhar com o 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
}

Consulte também

Conceitos

Mapeamento e manipulação de mensagem

Referência

BEGIN_TEMPLATE_MESSAGE_MAP