Freigeben über


How to: Create a Message Map for a Template-Klasse

Zuordnung Nachrichten in MFC bietet eine effiziente Möglichkeit, Windows-Meldungen auf eine entsprechende C++-Objektinstanz zu verweisen.Beispiele für MFC-Meldungszuordnungs zielen enthalten Anwendungsklassen, Dokument und Ansichtsklassen, Steuerelementklassen usw.

Herkömmliche MFC-Meldungszuordnungen werden mithilfe des BEGIN_MESSAGE_MAP Makros deklariert, um den Anfang der Meldungszuordnung, die einen Eintrag für jede Meldung Handler Klassenmethode, und das END_MESSAGE_MAP Makro deklarieren, das Ende der Meldungszuordnung schließlich zu deklarieren.

Eine Einschränkung mit dem BEGIN_MESSAGE_MAP Makro tritt auf, wenn sie in Verbindung mit einer Klasse verwendet wird, die Vorlagenargumente enthält.Wenn es mit einer Vorlagenklasse verwendet wird, verursacht einen Kompilierungsfehler dieses Makro aufgrund einer fehlenden Vorlagenparameter während der Makroerweiterung.Das BEGIN_TEMPLATE_MESSAGE_MAP Makro wurde entworfen, um die Klassen, die ein einzelnes Vorlagenargument enthalten, um ihre eigenen Meldungszuordnungen zu deklarieren.

Beispiel

Betrachten Sie ein Beispiel, in dem die Klasse MFC CListBox erweitert wird, um die Synchronisierung mit einer externen Datenquelle bereitgestellt.Die fiktive CSyncListBox-Klasse deklariert wurde:

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

Die CSyncListBox-Klasse ist für einen einzelnen Typ auf Vorlagen basierende, der die Datenquelle beschreibt, die sie synchronisiert.Die ebenfalls deklariert drei Methoden, die in der Meldungszuordnung der Klasse verwendet werden: OnPaint, OnDestroy und OnSynchronize.Die OnSynchronize-Methode implementiert wird:

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

Die obige Implementierung ermöglicht die auf einem Klassentyp, der die GetCount-Methode, wie CArray, CList implementiert, und CMap spezialisiert werden CSyncListBox-Klasse.Die StringizeElement-Funktion ist eine Vorlagenfunktion, die durch Folgendes einen Prototyp entwickelt wurde:

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

Normalerweise würde die Meldungszuordnung für diese Klasse definiert z. B.:

BEGIN_MESSAGE_MAP(CSyncListBox, CListBox)

ON_WM_PAINT()

ON_WM_DESTROY()

ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)

END_MESSAGE_MAP()

wo eine benutzerdefinierte LBN_SYNCHRONIZE Benutzer ist für eine von der Anwendung definierte z. B.:

#define LBN_SYNCHRONIZE (WM_USER + 1)

Die oben dargestellte Makro nicht kompiliert, die aufgrund von Fakten, dass die Vorlagen für die Festlegung CSyncListBox-Klasse während der Makroerweiterung fehlen wird.Das BEGIN_TEMPLATE_MESSAGE_MAP löst dieses Makro, indem der angegebenen Vorlagenparameter in der erweiterten Makro Zuordnung integriert.Die Meldungszuordnung für diese Klasse wird:

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

Das folgende Beispiel veranschaulicht die Verwendung der CSyncListBox-Klasse unter Verwendung eines CStringList-Objekts:

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

Um den Test ausführen zu können, muss die StringizeElement-Funktion spezialisiert werden mit der CStringList-Klasse zu umgehen:

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
}

Siehe auch

Referenz

BEGIN_TEMPLATE_MESSAGE_MAP

Konzepte

Meldungsbehandlung und Zuordnung