Udostępnij za pośrednictwem


Jak: Tworzenie mapy wiadomości dla szablonu klasy

Mapowanie wiadomości w MFC zapewnia skuteczny sposób do kierowania wiadomości Windows odpowiednie wystąpienie obiektu C++.Przykładami MFC wiadomości mapę cele klasy aplikacji, klasy dokumentów i widoku, klas kontroli i itd.

Tradycyjne mapy wiadomości MFC zadeklarowane za pomocą BEGIN_MESSAGE_MAP makro zadeklarować start mapy wiadomości, wpis makro dla każdej metody klasy obsługi wiadomości i ostatecznie END_MESSAGE_MAP makro zadeklarować końca mapę wiadomości.

Ograniczenie jednego z BEGIN_MESSAGE_MAP makra występuje wówczas, gdy jest używany w połączeniu z klasa zawierająca argumenty szablonu.Gdy używana z klasą szablonu, to makro spowoduje błąd kompilacji, ze względu na brak parametrów szablonu podczas rozwijania makr.BEGIN_TEMPLATE_MESSAGE_MAP Makro zostało zaprojektowane, aby umożliwić mapuje klasy zawierające argument jednego szablonu, aby zadeklarować własne wiadomości.

Przykład

Rozważmy przykład gdzie MFC CListBox klasy jest rozszerzany, aby zapewnić synchronizację z zewnętrznego źródła danych.Fikcyjne CSyncListBox klasy jest zadeklarowany w następujący sposób:

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

CSyncListBox klasy jest opartą na szablonie na pojedynczy typ, który opisuje będą synchronizowane ze źródła danych.Deklaruje również trzy metody, które będą uczestniczyć w mapie wiadomości klasy: OnPaint, OnDestroy, i OnSynchronize.OnSynchronize metoda jest zaimplementowana w następujący sposób:

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

Umożliwia wdrożenie powyższych CSyncListBox klasy być wyspecjalizowany w dowolnego typu klasy, który implementuje GetCount metody, takie jak CArray, CList, i CMap.StringizeElement jest funkcja szablonu prototyp, co następuje:

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

Normalnie mapa wiadomości dla tej klasy byłoby zdefiniowane jako:

BEGIN_MESSAGE_MAP(CSyncListBox, CListBox)

ON_WM_PAINT()

ON_WM_DESTROY()

ON_MESSAGE(LBN_SYNCHRONIZE, OnSynchronize)

END_MESSAGE_MAP()

gdy LBN_SYNCHRONIZE jest zdefiniowany przez aplikację, takie jak wiadomości użytkownika niestandardowego:

#define LBN_SYNCHRONIZE (WM_USER + 1)

Powyższe mapę makro nie zostanie skompilowany, ze względu na fakt, że specyfikacja szablonu CSyncListBox klasy będzie brak podczas rozwijania makr.BEGIN_TEMPLATE_MESSAGE_MAP makro rozwiązuje to dołączając parametr określonego szablonu do mapy rozwiniętej makro.Mapa wiadomości dla tej klasy staje się:

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

Następujące demonstruje użycie próbki CSyncListBox klasy za pomocą CStringList obiekt:

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

Aby wykonać test, StringizeElement funkcja musi wyspecjalizowane do pracy z CStringList klasy:

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
}

Zobacz też

Informacje

BEGIN_TEMPLATE_MESSAGE_MAP

Koncepcje

Obsługa wiadomości i mapowanie