TN006: сопоставления сообщения
Эта заметка описывает средства сопоставления сообщения MFC.
Проблема
Microsoft Windows реализует виртуальных функций в классах окна, которые используют его средства обмена сообщениями.В большой объем сообщений, которые включали, предоставляя свою виртуальную функцию для каждого сообщения окна создание запретительно большое vtable.
Поскольку число сообщений, определенных системой windows, меняется со временем, и так как приложения могут определять свои собственные сообщения windows, сопоставления сообщений обеспечивают уровень косвенного обращения, которая предотвращает изменения интерфейса из критические существующего кода.
Общие сведения
MFC предоставляет альтернативу оператор switch, которая использовалась в традиционных на базе Windows программах для обработки сообщения, отправленные окно.Сопоставление сообщений к методам можно указать, чтобы при получении сообщения будет окном, соответствующий метод будет вызываться автоматически.Эта функция позволяет сообщение-сопоставления разработан таким образом, чтобы соответствовать виртуальные функции, но имеет дополнительные преимущества не возможные с виртуальными функциями C++.
Указание сопоставления сообщения
Макрос DECLARE_MESSAGE_MAP объявляет 3 члена класса.
Закрытый массив записей AFX_MSGMAP_ENTRY вызвал _messageEntries.
Защищенная структура AFX_MSGMAP вызвавшей messageMap, указывающую на _messageEntries массив.
Защищенная виртуальной функцией GetMessageMap, которая возвращает адрес messageMap.
Этот макрос должен быть помещается в объявление любого класса с помощью сопоставления сообщения.По соглашению его в конце объявления класса.Примеры.
class CMyWnd : public CMyParentWndClass
{
// my stuff...
protected:
//{{AFX_MSG(CMyWnd)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
Это формат, созданный AppWizard и ClassWizard, когда они создают новые классы.Скобки //и //{{}}, необходимые для ClassWizard.
Таблица сопоставления сообщения определяется с помощью набор макросов, развернут на записи сопоставления сообщения.Переданные начинается с вызова макроса BEGIN_MESSAGE_MAP, таблицы определяет класс, который обрабатывается данным сопоставлением сообщения и родительским классом, к которому необработанных сообщений.Таблица заканчивается вызовом макроса END_MESSAGE_MAP.
2, Между этими вызовами записи макроса для каждого сообщения, которые будут обрабатываться этим сопоставлением сообщения.Каждое сообщение имеет стандартного окна формы ON_WM_ макрос MESSAGE_NAME, создающей запись сообщения.
Стандартная подпись функции указана для распаковки параметров каждого сообщения windows и обеспечение безопасности типа.Такие подписи могут быть найдены в файле Afxwin.h в объявлении CWnd.Каждое из них помечается ключевым словом afx_msg для упрощения идентификации.
Примечание |
---|
ClassWizard необходимо использовать ключевое слово afx_msg в объявлении обработчика сопоставления сообщения. |
Эти подписи функции были получены с помощью простого соглашения.Имя функции всегда начинается с "On».Это за которым следует имя сообщения windows с удаленного WM_» и «первого символа каждого слова прописными буквами машинного.Упорядочение параметров wParam выполните LOWORD(lParam) затем HIWORD(lParam).Неиспользуемые параметры не передаются.Все маркеры, которые создает программу-оболочкуы классами MFC преобразованы к указателям на соответствующие объекты MFC.В следующем примере показано, как обработать сообщение WM_PAINT и вызвать функцию CMyWnd::OnPaint непосредственного вызова.
BEGIN_MESSAGE_MAP(CMyWnd, CMyParentWndClass)
//{{AFX_MSG_MAP(CMyWnd)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
Таблица сопоставления сообщения необходимо указать пределами области любого функции или определения класса.Она не должна быть помещена в блок extern «c».
Примечание |
---|
ClassWizard изменит записи сопоставления сообщения, возникающие между брекетом комментария //и //{{}}. |
Определяемые пользователем сообщения windows
Определяемые пользователем сообщения могут быть включены в сопоставлении сообщений с помощью макроса ON_MESSAGE.Этот макрос принимает номер сообщения и метода формы:
// 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()
В этом примере устанавливаем обработчик для пользовательского сообщения, которое содержит идентификатор сообщения windows, производное от стандартного базы WM_USER для определяемых пользователем сообщений.В следующем примере показано, как вызвать этот обработчик.
CWnd* pWnd = ...;
pWnd->SendMessage(WM_MYMESSAGE);
Диапазон определяемых пользователем сообщений, которые используют этот подход должен быть в диапазоне WM_USER к 0x7fff.
Примечание |
---|
ClassWizard не поддерживает вставку процедуры обработчика ON_MESSAGE из пользовательского интерфейса ClassWizard.Необходимо вручную вводить их из редактора Visual C++.ClassWizard анализирует эти записи и let возможность просматривать их как и все другие записи сообщение-сопоставления. |
Зарегистрированные сообщения windows
Функция RegisterWindowMessage используется для определения нового окна, сообщения гарантированно будет уникальным в пределах системы.Макрос ON_REGISTERED_MESSAGE используется для обработки этих сообщений.Этот макрос принимает имя переменной, содержащей UINT NEAR зарегистрированное идентификатор сообщения windowsПример
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()
Зарегистрированная переменная идентификатор сообщения windows (WM_FIND в этом примере) должна быть переменная NEAR из-за способа ON_REGISTERED_MESSAGE реализовано.
Диапазон определяемых пользователем сообщений, которые используют этот подход является в диапазоне 0xC000 к 0xFFFF.
Примечание |
---|
ClassWizard не поддерживает вставку процедуры обработчика ON_REGISTERED_MESSAGE из пользовательского интерфейса ClassWizard.Необходимо вручную вводить их из текстового редактора.ClassWizard анализирует эти записи и let возможность просматривать их как и все другие записи сообщение-сопоставления. |
Сообщения команды
Сообщения команд из меню и ускорителей обрабатывается в сопоставлениях сообщения с макросом ON_COMMAND.Этот макрос принимает идентификатор команды и метод.Только конкретное сообщение WM_COMMAND с wParam, равным указанным идентификатором команды обрабатывается методом, указанным в записи сообщение-сопоставления.Функции-члены обработчика команды не принимают параметры и возвращаемое void.Макрос имеет следующую форму:
ON_COMMAND(id, memberFxn)
Сообщения обновления команды направляются через один и тот же механизм, но используется макрос ON_UPDATE_COMMAND_UI.Функции-члены обработчика обновления команды принимает один параметр - указатель на объект CCmdUI и возвращаемое void.Макрос имеет форму
ON_UPDATE_COMMAND_UI(id, memberFxn)
Опытные пользователи могут использовать макрос ON_COMMAND_EX, расширенная форма обработчиков сообщений команды.Макрос содержит надмножество функциональности ON_COMMAND.Расширенные функции-члены команда-обработчика принимает один параметр, UINT, содержащий идентификатор команды, и возвращает BOOL.Возвращаемое значение должно быть TRUE, чтобы показать, что команда обрабатывается.В противном случае маршрутизация продолжится другим целевым объектам команды.
Примеры таких форм:
Внутреннее Resource.h (обычно, который создает Visual C++)
#define ID_MYCMD 100 #define ID_COMPLEX 101
Внутри объявления классов
afx_msg void OnMyCommand(); afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI); afx_msg BOOL OnComplexCommand(UINT nID);
Внутри определения сопоставления сообщения
ON_COMMAND(ID_MYCMD, OnMyCommand) ON_UPDATE_COMMAND_UI(ID_MYCMD, OnUpdateMyCommand) ON_COMMAND_EX(ID_MYCMD, OnComplexCommand)
в файле реализации
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; }
Опытные пользователи могут настроить диапазон команд с помощью обработчика одной команды: ON_COMMAND_RANGE или ON_COMMAND_RANGE_EX.См. документацию продукта дополнительные сведения об этих макросов.
Примечание |
---|
ClassWizard поддерживает создание ON_COMMAND и обработчики ON_UPDATE_COMMAND_UI, но он не поддерживает создание ON_COMMAND_EX или обработчики ON_COMMAND_RANGE.Однако мастер класса выполняется синтаксический анализ и препятствовал можно просмотреть все 4 варианта обработчика команды. |
Управление сообщения уведомления
Сообщения, отправляемые из дочерних элементов управления в окно имеют дополнительный квант сведения в их записи сопоставления сообщения: идентификатор элемента управленияВызывается обработчик сообщений, определенный в записи сопоставления сообщения, только если выполняются следующие условия:
Код уведомления элемента управления (высокое слово lParam), например BN_CLICKED, соответствует коду уведомления, указанному в записи сообщение-сопоставления.
Идентификатор элемента управления (wParam) совпадает идентификатор элемента управления, указанному в записи сообщение-сопоставления.
Сообщения уведомления пользовательских элементов управления могут использовать макрос ON_CONTROL, чтобы идентифицировать запись сопоставления сообщения с пользовательским кодом уведомления.Этот макрос имеет форму
ON_CONTROL(wNotificationCode, id, memberFxn)
Для предварительного потребления ON_CONTROL_RANGE могут быть использованы для обработки определенного уведомления от элемента управления диапазона элементов управления с тем же обработчиком.
Примечание |
---|
ClassWizard не поддерживает создание обработчика ON_CONTROL или ON_CONTROL_RANGE в пользовательском интерфейсе.Необходимо вручную вводить их в текстовом редакторе.ClassWizard анализирует эти записи и let возможность просматривать их как и все остальные записи сопоставления сообщения. |
Элементы управления используют более мощный WM_NOTIFY windows, общие для сложных уведомлений элемента управления.Эта версия MFC имеет непосредственную поддержку этого нового сообщения с помощью макросов ON_NOTIFY и ON_NOTIFY_RANGE.См. документацию продукта дополнительные сведения об этих макросов.