TN006: Mapy wiadomość
Uwaga ta opisuje funkcja MFC komunikatów mapę.
Problem
Microsoft Windows implementuje funkcje wirtualnych w klasy okna, które skorzystać z jego funkcji obsługi wiadomości.Spowodowane dużą liczbę wiadomości zaangażowanych przewidujące oddzielnych funkcję wirtualną każdego komunikatu systemu Windows stworzyłoby vtable zbyt duże.
Ponieważ zmienia liczbę wiadomości zdefiniowane w systemie Windows, ponieważ aplikacje można zdefiniować własne wiadomości systemu Windows, wiadomości mapuje zapewniają poziom pośrednia, uniemożliwiający złamanie istniejącego kodu zmiany interfejsu.
Omówienie
MFC jest alternatywą dla instrukcji switch, użytej w tradycyjnych programów systemu Windows do obsługi wiadomości wysłane do okna.Mapowanie wiadomości metod można zdefiniować tak, aby po odebraniu wiadomości przez okno odpowiedniej metody jest wywoływana automatycznie.Ten instrument mapę wiadomości jest przeznaczony do 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 który wskazuje _messageEntries tablicy.
A chronione wirtualnego funkcji o nazwie GetMessageMap , zwraca adres messageMap.
To makro należy wprowadzić w deklaracji dowolnej klasy za pomocą map wiadomości.Przez Konwencję jest 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./ / {{I / /}} nawiasy są potrzebne do ClassWizard.
Mapa wiadomości tabela jest zdefiniowana przy użyciu zestawu makr, które Rozwiń do wpisów map wiadomości.Tabela rozpoczyna się od BEGIN_MESSAGE_MAP wywołanie makra, który definiuje klasy, który jest obsługiwany przez tej mapy 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, do obsługi przez mapę tej wiadomości.Co standardowy komunikat systemu Windows ma makra formularza ON_WM_MESSAGE_NAME , generuje wpis dla tej wiadomości.
Rozpakowywanie parametrów każdego komunikatu systemu Windows i zapewnienie bezpieczeństwa typu zostały zdefiniowane podpisu funkcji standardowego.Podpisy te można znaleźć w pliku Afxwin.h w deklaracji z CWnd.Każdy z nich jest oznaczony za pomocą 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ści.
Podpisy te funkcje zostały otrzymane za pomocą prostego 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 wpisać wielkimi literami.Kolejność parametrów jest wParam po LOWORD(lParam) 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 ilustruje sposób obsługi WM_PAINT wiadomości i spowodować, że 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 definicji żadnych funkcji lub klasy.Nie powinny być przedmiotem blokiem extern "C".
[!UWAGA]
ClassWizard będzie modyfikowania wpisów map wiadomości, występujące między / / {{i / /}} nawias 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 liczba wiadomości 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 ustanowienie obsługi niestandardowy komunikat o identyfikatorze Windows wiadomości pochodzące z normą WM_USER dla wiadomości zdefiniowane przez użytkownika.Poniższy przykład przedstawia sposób wywoływać ten program:
CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);
Zakres wiadomości zdefiniowane przez użytkownika, takie podejście musi być z zakresu WM_USER do 0x7fff.
[!UWAGA]
ClassWizard nie obsługuje wprowadzanie ON_MESSAGE procedur obsługi interfejsu użytkownika ClassWizard.Należy ręcznie wprowadzić je z Edytora Visual C++.ClassWizard będzie analizować te zapisy i pozwalają na przeglądanie ich podobnie jak inne wpisy mapy wiadomości.
Zarejestrowane wiadomości systemu Windows
RegisterWindowMessage funkcja jest używana do definiowania nowej wiadomości okno, która jest gwarantowane jest unikatowy w całym systemie.Makro ON_REGISTERED_MESSAGE jest używana do obsługi tych wiadomości.To makro przyjmuje nazwę UINT NEAR zmienna, która zawiera identyfikator windows zarejestrowanych wiadomości.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 zmiennej identyfikator wiadomości systemu Windows (WM_FIND w tym przykładzie) musi być NEAR zmienna ze względu na sposób ON_REGISTERED_MESSAGE jest zaimplementowana.
Zakres wiadomości zdefiniowane przez użytkownika, takie podejście będzie w zakresie 0xC000 a 0xFFFF.
[!UWAGA]
ClassWizard nie obsługuje wprowadzanie ON_REGISTERED_MESSAGE procedur obsługi interfejsu użytkownika ClassWizard.Należy ręcznie wprowadzić je z edytora tekstu.ClassWizard będzie analizować te zapisy i pozwalają na przeglądanie ich podobnie jak 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 określonych WM_COMMAND wiadomość zawierającą wParam równa określone polecenie ID jest obsługiwane przez metody określonej we wpisie mapy wiadomości.Funkcje składowe obsługi polecenia żadnych parametrów i zwraca void.Makro ma następującą postać:
ON_COMMAND(id, memberFxn)
Polecenie aktualizacji wiadomości są routowane przez ten sam mechanizm, ale użyj ON_UPDATE_COMMAND_UI makro w zamian.Polecenie aktualizacji funkcji Członkowskich podjąć jeden parametr wskaźnika do CCmdUI object i zwraca void.Makro ma postać
ON_UPDATE_COMMAND_UI(id, memberFxn)
Zaawansowani użytkownicy mogą używać ON_COMMAND_EX makra, który jest rozszerzony formie obsługi wiadomości polecenie.Makro stanowi nadzbiór ON_COMMAND funkcji.Członkowskie polecenia obsługi rozszerzonych funkcji mieć jeden parametr, UINT zawiera identyfikator polecenia i zwraca BOOL.Wartość zwracana powinna być TRUE do wskazania obsługi polecenia.W przeciwnym razie routing będzie nadal innych obiektów docelowych polecenia.
Przykłady te formy:
Wewnątrz Resource.h (zazwyczaj generowane przez 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łużyć szereg poleceń przy użyciu obsługi jednego polecenia: ON_COMMAND_RANGE lub ON_COMMAND_RANGE_EX.Aby uzyskać więcej informacji na temat makr w dokumentacji produktu.
[!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 analizować i pozwalają na przeglądanie wszystkich czterech polecenia obsługi wariantów.
Komunikaty powiadamiające kontroli
Wiadomości wysyłane z formantów podrzędnych do okna mają dodatkowy bit informacji w ich wiadomości mapę wejścia: identyfikator formantu.Obsługi wiadomości, określonych 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), takie jak BN_CLICKED, odpowiada określonej we wpisie mapy wiadomości do tego kod powiadomienia.
Identyfikator formantu (wParam) z identyfikatorem kontroli określonej we wpisie mapy wiadomości.
Komunikaty powiadamiające formant niestandardowy może używać ON_CONTROL makro do definiowania wpisie mapy wiadomości 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 zakresu kontroli z tej samej obsługi.
[!UWAGA]
ClassWizard nie obsługuje tworzenia ON_CONTROL lub ON_CONTROL_RANGE obsługi interfejsu użytkownika.Należy ręcznie wprowadzić je w edytorze tekstu.ClassWizard będzie analizować te zapisy i pozwalają na przeglądanie ich podobnie jak inne wpisy mapy wiadomości.
Formanty standardowe Windows używać bardziej wydajne WM_NOTIFY dla powiadomienia złożone kontroli.Ta wersja MFC ma bezpośrednie wsparcie dla tej nowej wiadomości za pomocą ON_NOTIFY i ON_NOTIFY_RANGE makr.Aby uzyskać więcej informacji na temat makr w dokumentacji produktu.