TN061. Сообщения ON_NOTIFY и WM_NOTIFY
Примечание.
Следующее техническое примечание не было обновлено, поскольку сначала оно было включено в электронную документацию. В результате некоторые процедуры и разделы могут быть устаревшими или неверными. Для получения последних сведений рекомендуется выполнить поиск интересующей темы в алфавитном указателе документации в Интернете.
Эта техническая заметка содержит справочную информацию о новом сообщении WM_NOTIFY и описывает рекомендуемый (и наиболее распространенный) способ обработки WM_NOTIFY сообщений в приложении MFC.
Сообщения уведомлений в Windows 3.x
В Windows 3.x элементы управления уведомляют своих родителей о событиях, таких как щелчки мыши, изменения в содержимом и выборе, а также управление фоновым рисунком, отправив родительскому сообщению сообщение. Простые уведомления отправляются в виде специальных WM_COMMAND сообщений с кодом уведомления (например, BN_CLICKED) и идентификатором элемента управления, упакованным в wParam и дескриптор элемента управления в lParam. Обратите внимание, что так как wParam и lParam полны, нет способа передать дополнительные данные — эти сообщения могут быть только простым уведомлением. Например, в уведомлении BN_CLICKED нет способа отправлять сведения о расположении курсора мыши при нажатии кнопки.
Если элементы управления в Windows 3.x должны отправлять уведомление, включающее дополнительные данные, они используют различные специальные сообщения, включая WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEM и т. д. Эти сообщения можно отражать обратно в элемент управления, отправляемый им. Дополнительные сведения см. в разделе TN062: сообщение Рефлексия ion для элементов управления Windows.
Сообщения уведомлений в Win32
Для элементов управления, существующих в Windows 3.1, API Win32 использует большинство сообщений уведомлений, которые использовались в Windows 3.x. Однако Win32 также добавляет ряд сложных, сложных элементов управления для тех, которые поддерживаются в Windows 3.x. Часто эти элементы управления должны отправлять дополнительные данные с их сообщениями уведомления. Вместо добавления нового сообщения WM_* для каждого нового уведомления, требующего дополнительных данных, конструкторы API Win32 решили добавить только одно сообщение, WM_NOTIFY, которое может передавать любой объем дополнительных данных в стандартизованном виде.
WM_NOTIFY сообщения содержат идентификатор элемента управления, отправляющего сообщение в wParam, и указатель на структуру в lParam. Эта структура представляет собой структуру NMHDR или некоторую большую структуру, которая имеет структуру NMHDR в качестве первого элемента. Обратите внимание, что так как элемент NMHDR является первым, указатель на эту структуру можно использовать как указатель на NMHDR или в качестве указателя на большую структуру в зависимости от способа его приведения.
В большинстве случаев указатель будет указывать на большую структуру, и вам потребуется привести ее при использовании. В некоторых уведомлениях, таких как распространенные уведомления (имена которых начинаются с NM_) и TTN_SHOW и TTN_POP уведомления элемента управления подсказками, фактически используется структура NMHDR .
Структура NMHDR или начальный элемент содержит дескриптор и идентификатор элемента управления, отправляющего сообщение, и код уведомления (например, TTN_SHOW). Ниже показан формат структуры NMHDR :
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
Для сообщения TTN_SHOW для элемента кода будет задано значение TTN_SHOW.
Большинство уведомлений передают указатель на большую структуру, содержащую структуру NMHDR в качестве первого члена. Например, рассмотрим структуру, используемую LVN_KEYDOWN сообщением элемента управления представлением списка, которое отправляется при нажатии клавиши в элементе управления представлением списка. Указатель указывает на структуру LV_KEYDOWN , которая определена, как показано ниже:
typedef struct tagLV_KEYDOWN {
NMHDR hdr;
WORD wVKey;
UINT flags;
} LV_KEYDOWN;
Обратите внимание, что так как элемент NMHDR впервые находится в этой структуре, указатель, передаваемый в сообщении уведомления, можно привести к указателю на NMHDR или указатель на LV_KEYDOWN.
Уведомления, общие для всех новых элементов управления Windows
Некоторые уведомления являются общими для всех новых элементов управления Windows. Эти уведомления передают указатель на структуру NMHDR .
Код уведомления | Отправлено, так как |
---|---|
NM_CLICK | Нажатой пользователем левой кнопкой мыши в элементе управления |
NM_DBLCLK | Пользователь дважды щелкнул левую кнопку мыши в элементе управления |
NM_RCLICK | Пользователь щелкнул правую кнопку мыши в элементе управления |
NM_RDBLCLK | Дважды щелкнув правой кнопкой мыши пользователя в элементе управления |
NM_RETURN | Пользователь нажимал клавишу ВВОД, а элемент управления имеет фокус ввода |
NM_SETFOCUS | Элемент управления был задан фокус на входных данных |
NM_KILLFOCUS | Элемент управления потерял фокус ввода |
NM_OUTOFMEMORY | Управление не удалось завершить операцию, так как недостаточно памяти |
ON_NOTIFY. Обработка сообщений WM_NOTIFY в приложениях MFC
Функция CWnd::OnNotify
обрабатывает сообщения уведомлений. Его реализация по умолчанию проверка сопоставление сообщений для обработчиков уведомлений для вызова. Как правило, вы не переопределяете OnNotify
. Вместо этого вы предоставляете функцию обработчика и добавляете запись карты сообщений для этого обработчика в карту сообщений класса окна владельца.
ClassWizard с помощью листа свойств ClassWizard может создать запись ON_NOTIFY карты сообщений и предоставить вам функцию обработчика скелета. Дополнительные сведения об использовании ClassWizard для упрощения работы см. в разделе "Сопоставление сообщений с функциями".
Макрос карты сообщений ON_NOTIFY имеет следующий синтаксис:
ON_NOTIFY(wNotifyCode, id, memberFxn)
Используются следующие параметры.
wNotifyCode
Код для обработки сообщения уведомления, например LVN_KEYDOWN.
id
Дочерний идентификатор элемента управления, для которого отправляется уведомление.
memberFxn
Функция-член, вызываемая при отправке этого уведомления.
Функция-член должна быть объявлена со следующим прототипом:
afx_msg void memberFxn(NMHDR* pNotifyStruct, LRESULT* result);
Используются следующие параметры.
pNotifyStruct
Указатель на структуру уведомлений, как описано в приведенном выше разделе.
result
Указатель на код результата, который вы задали перед возвратом.
Пример
Чтобы указать, что функция-член будет обрабатывать сообщения LVN_KEYDOWN из идентификатора CListCtrl
IDC_LIST1
, можно использовать ClassWizard, чтобы добавить следующую функцию OnKeydownList1
в карту сообщений:
ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeydownList1)
В приведенном выше примере функция, предоставляемая ClassWizard:
void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
Обратите внимание, что ClassWizard предоставляет указатель правильного типа автоматически. Вы можете получить доступ к структуре уведомлений через pNMHDR или pLVKeyDow.
ON_NOTIFY_RANGE
Если необходимо обработать то же WM_NOTIFY сообщение для набора элементов управления, можно использовать ON_NOTIFY_RANGE, а не ON_NOTIFY. Например, у вас может быть набор кнопок, для которых требуется выполнить то же действие для определенного сообщения уведомления.
При использовании ON_NOTIFY_RANGE укажите непрерывный диапазон дочерних идентификаторов, для которых нужно обрабатывать сообщение уведомления, указав начальные и конечные дочерние идентификаторы диапазона.
ClassWizard не обрабатывает ON_NOTIFY_RANGE; чтобы использовать его, необходимо самостоятельно изменить карту сообщений.
Прототип записи и функции карты сообщений для ON_NOTIFY_RANGE выглядит следующим образом:
ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn)
Используются следующие параметры.
wNotifyCode
Код для обработки сообщения уведомления, например LVN_KEYDOWN.
id
Первый идентификатор в непрерывном диапазоне идентификаторов.
idLast
Последний идентификатор в непрерывном диапазоне идентификаторов.
memberFxn
Функция-член, вызываемая при отправке этого уведомления.
Функция-член должна быть объявлена со следующим прототипом:
afx_msg void memberFxn(UINT id, NMHDR* pNotifyStruct, LRESULT* result);
Используются следующие параметры.
id
Дочерний идентификатор элемента управления, отправляющего уведомление.
pNotifyStruct
Указатель на структуру уведомлений, как описано выше.
result
Указатель на код результата, который вы задали перед возвратом.
ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE
Если для обработки сообщения требуется несколько объектов в маршрутизации уведомлений, можно использовать ON_NOTIFY_EX (или ON_NOTIFY_EX_RANGE), а не ON_NOTIFY (или ON_NOTIFY_RANGE). Единственное различие между версией EX и обычной версией заключается в том, что функция-член, вызываемая для версии EX , возвращает ЛОГИЧЕСКОЕ значение, указывающее, следует ли продолжать обработку сообщений. Возврат FALSE из этой функции позволяет обрабатывать одно и то же сообщение в нескольких объектах.
КлассWizard не обрабатывает ON_NOTIFY_EX или ON_NOTIFY_EX_RANGE; Если вы хотите использовать любой из них, необходимо самостоятельно изменить карту сообщений.
Прототип записи и функции карты сообщений для ON_NOTIFY_EX и ON_NOTIFY_EX_RANGE приведены ниже. Значения параметров совпадают с значениями версий, отличных от EX .
ON_NOTIFY_EX(nCode, id, memberFxn)
ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn)
Прототип для обоих из указанных выше вариантов совпадает:
afx_msg BOOL memberFxn(UINT id, NMHDR* pNotifyStruct, LRESULT* result);
В обоих случаях идентификатор содержит дочерний идентификатор элемента управления, отправляющего уведомление.
Функция должна возвращать значение TRUE , если сообщение уведомления было полностью обработано или FALSE , если другие объекты в маршрутизации команд должны иметь возможность обрабатывать сообщение.
См. также
Технические примечания по номеру
Технические примечания по категории