Partager via


How to: Create a Message Map for a Template, classe

Le mappage de message dans MFC offre un moyen efficace pour exécuter les messages windows à une instance de l'objet appropriée C++.Les exemples des cibles de table des messages MFC incluent les classes d'application, le document et les classes d'affichage, classes de contrôle, et ainsi de suite.

Les tables des messages traditionnelles MFC sont déclarées utilisation de la macro BEGIN_MESSAGE_MAP pour déclarer le début de la table des messages, une macro entrée pour chaque méthode de la classe de gestionnaire de messages, et enfin la macro d' END_MESSAGE_MAP de déclarer le mappage de fin de le message.

Une limitation avec la macro de BEGIN_MESSAGE_MAP se produit lorsqu'elle est utilisée conjointement avec une classe contenant les arguments template.Lorsque utilisé avec une classe de modèle, cette macro provoque une erreur de compilation en raison de les paramètres manquants de modèle pendant l'expansion macro.La macro de BEGIN_TEMPLATE_MESSAGE_MAP a été conçu pour permettre aux classes contenant un argument template unique pour déclarer leurs propres tables des messages.

Exemple

Prenons un exemple dans lequel la classe MFC CListBox est étendue pour fournir à la synchronisation une source de données externe.La classe fictive de CSyncListBox est déclarée comme suit :

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

La classe de CSyncListBox est modélisée sur un type unique qui décrit la source de données à laquelle il doit se synchroniser avec.Il indique également trois méthodes qui participeront à la table des messages de la classe : OnPaint, OnDestroy, et OnSynchronize.La méthode d' OnSynchronize est implémentée comme suit :

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

L'implémentation ci-dessus permet la classe de CSyncListBox à spécialiser sur un type de classe qui implémente la méthode de GetCount , telle que CArray, CList, et CMap.La fonction de StringizeElement est une fonction de modèle prototype par ce qui suit :

// Template function for converting an element within a collection
// to a CString object
template<typename CollectionT>
CString StringizeElement(CollectionT* pCollection, INT iIndex);

Normalement, la table des messages pour cette classe est définie comme suit :

BEGIN_MESSAGE_MAP(CSyncListBox, CListBox)

ON_WM_PAINT()

ON_WM_DESTROY()

ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)

END_MESSAGE_MAP()

LBN_SYNCHRONIZE est un message utilisateur personnalisé défini par l'application, telle que :

#define LBN_SYNCHRONIZE (WM_USER + 1)

Le mappage ci-dessus ne pourra pas, puisque la spécification du modèle pour la classe de CSyncListBox est manquante pendant l'expansion macro.La macro de BEGIN_TEMPLATE_MESSAGE_MAP résout en incorporant le paramètre de modèle spécifié dans le mappage développée.La table des messages pour cette classe devient :

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

Ce qui suit montre l'exemple de la classe de CSyncListBox à l'aide d'un objet de 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);
   }
}

Pour terminer le test, la fonction de StringizeElement doit être spécialisée pour utiliser la classe de CStringList :

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
}

Voir aussi

Référence

BEGIN_TEMPLATE_MESSAGE_MAP

Concepts

Gestion des messages et mappage