TN006. Схемы сообщений
Эта заметка описывает поддержку сопоставления сообщений MFC.
Проблема
Microsoft Windows реализует виртуальных функций в классах окна, использующие его средства обмена сообщениями. Из-за большому количеству входящих сообщений, обеспечивая отдельно виртуальную функцию для каждого сообщения Windows создание запретительно большое vtable.
Поскольку количество сообщений, определенных системой Windows изменяется с течением времени, и так как приложения могут определять собственные сообщения Windows, схемы сообщений обеспечивают уровень косвенного обращения, предотвращает изменения интерфейса прерывание из существующего кода.
Обзор
MFC предоставляет альтернативный способ оператор switch, который использовался в традиционных на базе Windows программах для обработки сообщений, отправленных в окно. Сопоставление из сообщений методам можно определить, если сообщение будет получено окном, соответствующий метод вызывается автоматически. Это средство сопоставления сообщений обеспечивает, чтобы соответствовать виртуальные функции, но имеет дополнительные выгоды не возможные с функциями виртуального C 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 и при создании новых классов. Квадратные скобки //и //{{webservername}}, необходимые для ClassWizard.
Таблица схемы сообщений определяется с помощью набора макросов, развернут записи сопоставления сообщений. Передаются начинается с вызовом макроса BEGIN_MESSAGE_MAP, который таблицы определяется класс, который обрабатывается этой схемой сообщений и родительским классом, к которой необработанные сообщения. Таблица заканчивается вызовом макроса END_MESSAGE_MAP.
Между этими вызовами 2 макроса запись для каждого сообщения, которое будет обрабатываться эта схема сообщений. Стандартное каждое сообщение содержит макрос ON_WM_ формы Windows 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 изменяет записи сопоставления сообщений, возникающие между квадратной скобкой комментариев //и //{{webservername}}.
Определяемые пользователем сообщения 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 C++.ClassWizard анализирует эти записи и позволяет просматривать их так же, как и любые другие записи сопоставления сообщений.
Зарегистрированные сообщения Windows
Функция RegisterWindowMessage используется для определения нового сообщения окна, который обязательно уникальным во всех частях системы. Макрос ON_REGISTERED_MESSAGE используется для обработки этих сообщений. Этот макрос принимает имя переменной UINT NEAR, содержащая зарегистрированные идентификатор сообщения окна Пример
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 анализирует эти записи и позволяет просматривать их так же, как и любые другие записи сопоставления сообщений.
Сообщения команды
Сообщения команд из меню и сочетаний клавиш, обрабатываются в схемах сообщений с макросом 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 анализирует эти записи и позволяет просматривать их так же, как и любые другие записи сопоставления сообщений.
Стандартные элементы управления Windows используется более мощный интерфейс WM_NOTIFY для получения уведомлений сложного элемента управления. Эта версия MFC имеет непосредственную поддержку нового сообщения с помощью макросов ON_NOTIFY и ON_NOTIFY_RANGE. См. в документации по продукту дополнительные сведения об этих макросах.