Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Замечание
Библиотека классов Microsoft Foundation (MFC) продолжает поддерживаться. Однако мы больше не добавляем функции или обновляем документацию.
Замечание
Следующая техническая заметка не была обновлена, так как она была впервые включена в онлайн-документацию. В результате некоторые процедуры и темы могут быть устаревшими или неверными. Для получения последних сведений рекомендуется искать интересующую тему в индексе веб-документации.
Эта техническая заметка описывает отражение сообщений, новую функцию в MFC 4.0. Он также содержит инструкции по созданию простого повторно используемого компонента, использующего отражение сообщений.
Эта техническая заметка не обсуждает отражение сообщений, так как оно применяется к элементам ActiveX (ранее называемым элементами управления OLE). См. статью ActiveX Controls: подкласс элемента управления Windows.
Что такое отражение сообщений
Элементы управления Windows часто отправляют сообщения уведомлений в родительские окна. Например, многие элементы управления отправляют уведомление о цвете элемента управления (WM_CTLCOLOR или один из его вариантов), чтобы разрешить родительскому элементу предоставить кисть для рисования фона элемента управления.
В Windows и MFC до версии 4.0 родительский окно, часто диалоговое окно, отвечает за обработку этих сообщений. Это означает, что код для обработки сообщения должен находиться в классе родительского окна и должен дублироваться в каждом классе, который должен обрабатывать это сообщение. В вышеупомянутом случае каждое диалоговое окно, которое требовало элементов управления с настраиваемыми фонами, должно было обрабатывать сообщение о цвете элемента управления. Было бы гораздо проще повторно использовать код, если класс элемента управления может быть написан, который будет обрабатывать свой собственный цвет фона.
В MFC 4.0 старый механизм по-прежнему работает— родительские окна могут обрабатывать сообщения уведомлений. Кроме того, MFC 4.0 упрощает повторное использование, предоставляя функцию "отражение сообщений", которая позволяет обрабатывать эти сообщения уведомлений в окне дочернего элемента управления или родительском окне или в обоих. В примере цвета фона элемента управления теперь можно написать класс элемента управления, который задает свой собственный цвет фона, обрабатывая отраженное WM_CTLCOLOR сообщение — все без использования родительского элемента. (Обратите внимание, что так как отражение сообщений реализуется MFC, а не Windows, родительский класс окна должен быть производным от CWnd отражения сообщений для работы.)
Более старые версии MFC осуществляли нечто похожее на реверс сообщений, предоставляя виртуальные функции для нескольких сообщений, например, сообщения для полей списка, нарисованных пользователем (WM_DRAWITEM и так далее). Новый механизм отражения сообщений обобщен и согласован.
Отражение сообщений обратно совместимо с кодом, написанным для версий MFC до 4.0.
Если вы предоставили обработчик для определенного сообщения или для диапазона сообщений в классе родительского окна, он переопределит отражающие обработчики сообщений для того же сообщения, если вы не вызываете функцию обработчика базового класса в собственном обработчике. Например, если вы обрабатываете WM_CTLCOLOR в классе диалогового окна, ваша обработка переопределит любые обработчики отражённых сообщений.
Если в родительском классе окна вы предоставляете обработчик для определенного сообщения WM_NOTIFY или диапазона сообщений WM_NOTIFY, обработчик будет вызываться только в том случае, если дочерний элемент управления, отправляющий эти сообщения, не имеет отражающего обработчика сообщений ON_NOTIFY_REFLECT(). Если вы используете ON_NOTIFY_REFLECT_EX() в карте сообщений, обработчик сообщений может или не позволить родительскому окну обрабатывать сообщение. Если обработчик возвращает FALSE, сообщение также будет обрабатываться родительским объектом, тогда как вызов, возвращающий TRUE, не позволяет родительскому объекту его обработать. Обратите внимание, что отраженное сообщение обрабатывается перед сообщением уведомления.
Когда отправляется сообщение WM_NOTIFY, элемент управления получает первый шанс обработать его. Если отправляется любое другое отражаемое сообщение, родительское окно имеет первый шанс обработать его, а элемент управления получит отражаемое сообщение. Для этого потребуется функция обработчика и соответствующая запись в карте сообщений класса элемента управления.
Макрос карты сообщений для отраженных сообщений немного отличается от макросов для обычных уведомлений: у него к обычному имени добавляется _REFLECT. Например, для обработки сообщения WM_NOTIFY в родительском объекте используется макрос ON_NOTIFY на карте сообщений родительского объекта. Чтобы обработать отраженное сообщение в дочернем элементе управления, используйте макрос ON_NOTIFY_REFLECT в карте сообщений дочернего элемента управления. В некоторых случаях параметры также отличаются. Обратите внимание, что ClassWizard обычно может добавлять записи карты сообщений для вас и предоставлять шаблонные реализации функций с корректными параметрами.
См. раздел TN061: ON_NOTIFY и WM_NOTIFY сообщения для получения информации о новом сообщении WM_NOTIFY.
Message-Map записи и прототипы функций обработчика для отраженных сообщений
Чтобы обработать отражаемое сообщение об уведомлении элемента управления, используйте макросы карты сообщений и прототипы функций, перечисленные в таблице ниже.
ClassWizard обычно может добавлять эти записи карты сообщений для вас и предоставлять заготовки функций. Сведения об определении обработчика сообщений для отражаемого сообщения см. в разделе "Определение обработчиков для отраженных сообщений".
Чтобы преобразовать имя сообщения в отраженное имя макроса, добавьте ON_ и добавьте _REFLECT. Например, WM_CTLCOLOR становится ON_WM_CTLCOLOR_REFLECT. (Чтобы узнать, какие сообщения могут быть отражены, выполните противоположное преобразование записей макроса в таблице ниже.)
Ниже приведены три исключения из приведенного выше правила.
Макрос для уведомлений WM_COMMAND является ON_CONTROL_REFLECT.
Макрос для отражения сообщений WM_NOTIFY называется ON_NOTIFY_REFLECT.
Макрос для обработки отражений ON_UPDATE_COMMAND_UI - это ON_UPDATE_COMMAND_UI_REFLECT.
В каждом из указанных выше особых случаев необходимо указать имя функции-члена обработчика. В других случаях необходимо использовать стандартное имя для функции обработчика.
Значения параметров и возвращаемые значения функций документируются под именем функции или под именем функции с префиксом On. Например, CtlColor документируется в OnCtlColor. Для нескольких отражаемых обработчиков сообщений требуется меньше параметров, чем аналогичные обработчики в родительском окне. Просто соотнесите имена в таблице ниже с именами формальных параметров в документации.
| Элемент карты | Прототип функции |
|---|---|
afx_msg voidmemberFxn( ); |
|
ON_NOTIFY_REFLECT(wNotifyCode,memberFxn) |
afx_msg voidmemberFxn( NMHDR*pNotifyStruct, LRESULT*result); |
ON_UPDATE_COMMAND_UI_REFLECT(memberFxn) |
afx_msg voidmemberFxn( CCmdUI*pCmdUI); |
| ON_WM_CTLCOLOR_REFLECT( ) |
afx_msg HBRUSH CtlColor (CDC)*pDC, UINTnCtlColor); |
| ON_WM_DRAWITEM_REFLECT( ) |
afx_msg void DrawItem (LPDRAWITEMSTRUCTlpDrawItemStruct); |
| ON_WM_MEASUREITEM_REFLECT( ) |
afx_msg void MeasureItem (LPMEASUREITEMSTRUCTlpMeasureItemStruct); |
| ON_WM_DELETEITEM_REFLECT( ) |
afx_msg void DeleteItem (LPDELETEITEMSTRUCTlpDeleteItemStruct); |
| ON_WM_COMPAREITEM_REFLECT( ) |
afx_msg int CompareItem (LPCOMPAREITEMSTRUCTlpCompareItemStruct); |
| ON_WM_CHARTOITEM_REFLECT( ) |
afx_msg int CharToItem (UINTnKey, UINTnIndex); |
| ON_WM_VKEYTOITEM_REFLECT( ) |
afx_msg int VKeyToItem (UINTnKey, UINTnIndex); |
| ON_WM_HSCROLL_REFLECT( ) |
afx_msg void HScroll (UINTnSBCode, UINTnPos); |
| ON_WM_VSCROLL_REFLECT( ) |
afx_msg void VScroll (UINTnSBCode, UINTnPos); |
| ON_WM_PARENTNOTIFY_REFLECT( ) |
afx_msg void ParentNotify (UINTmessage, LPARAMlParam); |
Макросы ON_NOTIFY_REFLECT и ON_CONTROL_REFLECT имеют различные варианты, позволяющие обрабатывать более чем одним объектом (например, элементом управления и его родительским элементом) определенное сообщение.
| Элемент карты | Прототип функции |
|---|---|
ON_NOTIFY_REFLECT_EX(wNotifyCode,memberFxn) |
afx_msg BOOLmemberFxn( NMHDR*pNotifyStruct, LRESULT*результат); |
ON_CONTROL_REFLECT_EX(wNotifyCode,memberFxn) |
afx_msg BOOLmemberFxn( ); |
Обработка отраженных сообщений: пример многократно используемых элементов управления
В этом простом примере создается многократно используемый элемент управления CYellowEdit. Элемент управления работает так же, как обычный элемент управления редактирования, за исключением того, что он отображает черный текст на желтом фоне. Было бы легко включить функции-члены, которые позволят элементу управления CYellowEdit отображать различные цвета.
Чтобы попробовать пример, создающий повторно используемый элемент управления
Создайте диалоговое окно в существующем приложении. Дополнительные сведения см. в разделе редактора диалогов .
У вас должно быть приложение, в котором необходимо разработать повторно используемый элемент управления. Если у вас нет существующего приложения, создайте диалоговое приложение с помощью AppWizard.
С загруженным в Visual Studio проектом используйте ClassWizard для создания нового класса под именем
CYellowEditна основеCEdit.Добавьте три переменные-члены в ваш класс
CYellowEdit. Первые два будут переменными COLORREF для хранения цвета текста и цвета фона. Третий объектCBrushбудет содержать кисть, предназначенную для рисования фона. ОбъектCBrushпозволяет создать кисть один раз и затем просто ссылаться на нее, а также автоматически уничтожать кисть при уничтожении элемента управленияCYellowEdit.Инициализируйте переменные-члены, написав конструктор следующим образом:
CYellowEdit::CYellowEdit() { m_clrText = RGB(0, 0, 0); m_clrBkgnd = RGB(255, 255, 0); m_brBkgnd.CreateSolidBrush(m_clrBkgnd); }С помощью ClassWizard добавьте обработчик для отраженного сообщения WM_CTLCOLOR в
CYellowEditкласс. Обратите внимание, что знак равенства перед именем сообщения в списке сообщений, который можно обрабатывать, указывает на то, что сообщение отражено. Это описано в разделе "Определение обработчика сообщений" для отражаемого сообщения.ClassWizard добавляет для вас следующий макрос карты сообщений и шаблон функции:
ON_WM_CTLCOLOR_REFLECT() // Note: other code will be in between.... HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) { // TODO: Change any attributes of the DC here // TODO: Return a non-NULL brush if the // parent's handler should not be called return NULL; }Замените текст функции следующим кодом. Код задает цвет текста, цвет фона текста и цвет фона для остальной части элемента управления.
pDC->SetTextColor(m_clrText); // text pDC->SetBkColor(m_clrBkgnd); // text bkgnd return m_brBkgnd; // ctl bkgndСоздайте элемент управления редактирования в диалоговом окне, а затем подключите его к переменной-члену, дважды щелкнув элемент управления редактированием при удержании ключа элемента управления вниз. В диалоговом окне "Добавление переменной" укажите имя переменной, выберите "Control" для категории, а затем "CYellowEdit" для типа переменной. Не забудьте задать порядок вкладок в диалоговом окне. Кроме того, не забудьте включить файл заголовка элемента
CYellowEditуправления в файл заголовка диалогового окна.Создайте и запустите приложение. Элемент управления редактирования будет иметь желтый фон.
См. также
Технические примечания по номеру
Технические заметки по категориям