Udostępnij za pośrednictwem


TN006: mapy komunikatów

Uwaga ta opisuje funkcja mapy komunikatów MFC.

Problem

Microsoft Windows implementuje funkcje wirtualnych w klasy okien, które używają jej wiadomości obiektu.Ze względu na dużą liczbę wiadomości zaangażowanych zapewniając oddzielnych funkcji wirtualnych dla każdej wiadomości systemu Windows spowodowałoby powstanie zbyt dużą wartość vtable.

Ponieważ liczba zdefiniowanych przez system wiadomości systemu Windows zmienia się w czasie, a ponieważ aplikacje można zdefiniować własne wiadomości systemu Windows, wiadomości mapuje zapewniają poziom pośrednia, uniemożliwiający łamanie istniejącego kodu zmiany w interfejsie.

Omówienie

MFC jest alternatywą dla użytego w tradycyjnych programów opartych na systemie Windows do obsługi wiadomości wysyłane do okna instrukcji switch.Mapowanie wiadomości do metody można zdefiniować tak, aby po otrzymaniu wiadomości przez okno właściwą metodą jest wywoływana automatycznie.Ten obiekt mapy wiadomość ma na celu przypominają funkcje wirtualnych, ale ma dodatkowe korzyści nie jest możliwe z wirtualnego funkcje C++.

Definiowanie mapy wiadomości

DECLARE_MESSAGE_MAP Makro deklaruje trzech członków dla klasy.

  • Prywatne tablica AFX_MSGMAP_ENTRY pozycje o nazwie _messageEntries.

  • Chronionym AFX_MSGMAP strukturę o nazwie messageMap co wskazuje na _messageEntries tablicy.

  • A chronione wirtualnego funkcji o nazwie GetMessageMap , które zwraca adres messageMap.

To makro należy umieścić w deklaracji klasy za pomocą map wiadomość.Umownie to na końcu deklaracji klasy.Na przykład:

class CMyWnd : public CMyParentWndClass
{
    // my stuff...

protected:
    //{{AFX_MSG(CMyWnd)
    afx_msg void OnPaint();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

Jest to format generowanych przez AppWizard i ClassWizard, podczas tworzenia nowych klas./ / {{A / /}} nawiasy są potrzebne do ClassWizard.

Tabela mapowania wiadomości jest zdefiniowany za pomocą zestawu makr, które rozszerzają do wpisów map wiadomość.Tabela zaczyna się od BEGIN_MESSAGE_MAP wywołania makra, który definiuje klasy, który jest obsługiwany przez tę mapę wiadomości i klasy nadrzędnej, do którego są przekazywane wiadomości nieobsługiwany.Tabela kończy się na END_MESSAGE_MAP wywołania makra.

Między wywołaniami tych dwóch makro jest wpis dla każdej wiadomości może być obsługiwanych przez tę mapę wiadomość.Każdy standardowy komunikat systemu Windows ma makro formularza ON_WM_MESSAGE_NAME który generuje wpis dla tej wiadomości.

Podpis standardową funkcję została zdefiniowana dla rozpakowywania parametrów każdej wiadomości systemu Windows i zapewnienie bezpieczeństwa typu.Podpisy te można znaleźć w pliku Afxwin.h w deklaracji z CWnd.Każdy z nich jest oznaczony przy użyciu słowa kluczowego afx_msg dla łatwej identyfikacji.

[!UWAGA]

ClassWizard wymaga użycia afx_msg słowa kluczowego w swoje deklaracje programu obsługi map wiadomość.

Te sygnatury funkcji zostały otrzymane przy użyciu prostych Konwencji.Nazwa funkcji zawsze rozpoczyna się od "On".To następuje nazwa komunikatu systemu Windows z "€ œwm_â usunięte i pierwszą literę każdego wyrazu wielką literą.Kolejność parametrów jest wParam następuje LOWORD(lParam) a następnie HIWORD(lParam).Nieużywane parametry nie są przekazywane.Wszystkie dojścia, które są pakowane według klas MFC są konwertowane na wskaźniki do odpowiednich obiektów MFC.Poniższy przykład pokazuje sposób obsługi WM_PAINT wiadomości i spowodować CMyWnd::OnPaint wywołanie funkcji:

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

Tabela mapowania wiadomości musi być zdefiniowana poza zakresem żadnej definicji funkcji lub klasy.Nie należy go umieszczać w bloku extern "C".

[!UWAGA]

ClassWizard będzie modyfikowania wpisów map wiadomości, które mają miejsce pomiędzy / / {{a / /}} wspornik komentarz.

Zdefiniowany przez użytkownika wiadomości systemu Windows

Zdefiniowane przez użytkownika wiadomości może zawierać mapę wiadomości za pomocą ON_MESSAGE makro.To makro akceptuje numer komunikatu i metoda formularza:

    // inside the class declaration
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

    #define WM_MYMESSAGE (WM_USER + 100)

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE_MAP()

W tym przykładzie ustalamy obsługi dla wiadomość niestandardową, która ma identyfikator wiadomości Windows pochodzące z normą WM_USER podstawa używana do wiadomości przez użytkownika.Poniższy przykład pokazuje sposób wywoływania tego programu obsługi:

CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);

Zakres wiadomości przez użytkownika, które używają tego podejścia musi być w zakresie WM_USER do 0x7fff.

[!UWAGA]

ClassWizard nie obsługuje wprowadzanie ON_MESSAGE procedury obsługi interfejsu użytkownika ClassWizard.Należy wprowadzić ręcznie je z Edytora Visual C++.ClassWizard będzie analizować te wpisy, a pozwalają na przeglądanie ich tak jak wszelkie inne wpisy mapy wiadomości.

Wiadomości zarejestrowanych systemu Windows

RegisterWindowMessage funkcja jest używane do definiowania nowego komunikatu w oknie, że zapewniona jest unikatowy w całym systemie.Makro ON_REGISTERED_MESSAGE jest używany do obsługi tych wiadomości.To makro przyjmuje nazwę z UINT NEAR zmienna, która zawiera identyfikator windows zarejestrowany komunikat.Na przykład

class CMyWnd : public CMyParentWndClass
{
public:
    CMyWnd();

    //{{AFX_MSG(CMyWnd)
    afx_msg LRESULT OnFind(WPARAM wParam, LPARAM lParam);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

static UINT NEAR WM_FIND = RegisterWindowMessage("COMMDLG_FIND");

BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
    //{{AFX_MSG_MAP(CMyWnd)
    ON_REGISTERED_MESSAGE(WM_FIND, OnFind)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

Zarejestrowane zmienna identyfikator wiadomości systemu Windows (WM_FIND w tym przykładzie) musi być NEAR zmiennej ze względu na sposób ON_REGISTERED_MESSAGE jest zaimplementowana.

Zakres wiadomości przez użytkownika, które używają tego podejścia będzie się w zakresie 0xC000 0xFFFF.

[!UWAGA]

ClassWizard nie obsługuje wprowadzanie ON_REGISTERED_MESSAGE procedury obsługi interfejsu użytkownika ClassWizard.Ręcznie wprowadź je z edytora tekstu.ClassWizard będzie analizować te wpisy, a pozwalają na przeglądanie ich tak jak wszelkie inne wpisy mapy wiadomości.

Komunikaty polecenia

Komunikaty polecenia z menu i akceleratory są obsługiwane w mapach wiadomość z ON_COMMAND makro.To makro akceptuje identyfikator polecenia i metody.Tylko dotyczące WM_COMMAND wiadomość zawierającą wParam równa określonego polecenia ID odbywa się w sposób określony we wpisie mapy wiadomości.Funkcje obsługi polecenia nie mają żadnych parametrów i zwraca void.Makro ma następującą postać:

ON_COMMAND(id, memberFxn)

Komunikaty polecenia aktualizacji są kierowane przez ten sam mechanizm, ale użyj ON_UPDATE_COMMAND_UI makro w zamian.Funkcje składowe obsługi polecenia update korzystać z jednego parametru, wskaźnik do CCmdUI object i zwrócić void.Makro ma postać

ON_UPDATE_COMMAND_UI(id, memberFxn)

Zaawansowani użytkownicy mogą używać ON_COMMAND_EX makra, która jest formą Rozszerzone polecenie obsługi wiadomości.Makro stanowi nadzbiór ON_COMMAND funkcjonalność.Funkcje składowe program obsługi poleceń rozszerzonego korzystać z jednego parametru, UINT zawiera identyfikator polecenia i zwrócić BOOL.Wartość zwracana powinna być TRUE do wskazania, że polecenie zostało obsłużone.W przeciwnym razie routing będzie nadal innych obiektów docelowych polecenia.

Przykłady te formy:

  • Resource.h do wewnątrz (zwykle generowany przez program Visual C++)

    #define    ID_MYCMD      100
    #define    ID_COMPLEX    101
    
  • Wewnątrz deklaracji klasy

    afx_msg void OnMyCommand();
    afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
    afx_msg BOOL OnComplexCommand(UINT nID);
    
  • Wewnątrz definicji mapy wiadomości

    ON_COMMAND(ID_MYCMD, OnMyCommand)
    ON_UPDATE_COMMAND_UI(ID_MYCMD, OnUpdateMyCommand)
    ON_COMMAND_EX(ID_MYCMD, OnComplexCommand)
    
  • W pliku implementacji

    void CMyClass::OnMyCommand()
    {
        // handle the command
    }
    
    void CMyClass::OnUpdateMyCommand(CCmdUI* pCmdUI)
    {
        // set the UI state with pCmdUI
    }
    
    BOOL CMyClass::OnComplexCommand(UINT nID)
    {
        // handle the command
        return TRUE;
    }
    

Użytkownicy zaawansowani może obsługiwać wiele poleceń za pomocą jednego polecenia obsługi: ON_COMMAND_RANGE lub ON_COMMAND_RANGE_EX.Zobacz dokumentację produktu, aby uzyskać więcej informacji na temat makr.

[!UWAGA]

ClassWizard obsługuje tworzenie ON_COMMAND i ON_UPDATE_COMMAND_UI obsługi, ale nie obsługuje tworzenia ON_COMMAND_EX lub ON_COMMAND_RANGE obsługi.Jednak Kreator klas przeanalizować i pozwalają na przeglądanie wszystkich czterech polecenia obsługi wariantów.

Komunikaty sterujące powiadomień

Wpis mapowania wiadomości, które są wysyłane z formantów podrzędnych do okna mają dodatkowe bit informacji w swojej wiadomości: identyfikator formantu.Obsługi wiadomości określone we wpisie mapy wiadomości nazywa się tylko wtedy, gdy są spełnione następujące warunki:

  • Kod powiadomienia kontroli (wyższe słowo lParam), takich jak BN_CLICKED, zgodny z kodem notyfikacji określonej we wpisie mapy wiadomości.

  • Identyfikator formantu (wParam) jest zgodny z Identyfikatorem formantu określonej we wpisie mapy wiadomości.

Komunikaty powiadamiające formant niestandardowy może używać ON_CONTROL makro, aby zdefiniować wpisu mapowania wiadomość z kodu niestandardowego powiadomienia.To makro ma postać

ON_CONTROL(wNotificationCode, id, memberFxn)

Zaawansowane wykorzystanie ON_CONTROL_RANGE może służyć do obsługi powiadamiania określonego formantu z gamy formantów za pomocą tej procedury obsługi.

[!UWAGA]

ClassWizard nie obsługuje tworzenia ON_CONTROL lub ON_CONTROL_RANGE obsługi w interfejsie użytkownika.Ręcznie wprowadź je w edytorze tekstu.ClassWizard będzie analizować te wpisy, a pozwalają na przeglądanie ich tak jak wszelkie inne wpisy mapy wiadomości.

Formanty systemu Windows użyj bardziej wydajne WM_NOTIFY dla powiadomień sterowania złożonego.Ta wersja programu MFC z bezpośredniego wsparcia dla tej nowej wiadomości przy użyciu ON_NOTIFY i ON_NOTIFY_RANGE makra.Zobacz dokumentację produktu, aby uzyskać więcej informacji na temat makr.

Zobacz też

Inne zasoby

Uwagi techniczne według numerów

Uwagi techniczne według kategorii