Рисунок 3. Маршрутизация сообщений в MFC

Преобразование сообщений

Функция

CWinApp::PreTranslateMessage
CWinThread::PreTranslateMessage (в 32-битной MFC)

Назначение

Преобразование горячих клавиш.

Реализация в MFC

CWinThread вызывает CWnd::PreTranslateMessage окна, которому адресовано сообщение, всех его родителей, а также главного окна приложения. Это позволяет каждому окну выполнить собственное преобразование сообщения. Если окно обработало сообщение, оно возвращает TRUE, и маршрутизация прекращается.

Когда переопределять

Практически никогда. Используйте, если вам нужны горячие клавиши, работающие для абсолютно всех окон приложения. При этом почти во всех случаях необходимо вызывать функцию базового класса.

Функция

CWnd::PreTranslateMessage

Назначение

Преобразование горячих клавиш.

Реализация в MFC

CWnd просто возвращает FALSE.

CDialog вызывает ::IsDialogMessage, чтобы преобразовать клавиши, имеющие в диалогах специальное значение (такие как переход по TAB и быстрый доступ к элементам управления).

CFrameWnd преобразует горячие клавиши из таблицы IDR_ВАШАТАБЛИЦА, если они есть. Сначала обращается к pActiveDoc->GetDefaultAccelerator.

CMDIFrame сначала даёт возможность преобразовать сообщение активному дочернему окну, а затем вызывает ::TranslateMDISysAccel, чтобы преобразовать стандартные горячие клавиши интерфейса MDI в Windows.

CMDIChildFrame преобразует горячие клавиши, определённые в файле ресурсов. Сначала ищет горячие клавиши в документе.

CControlBar вызывает ::IsDialogMessage, если панель управления является диалоговой панелью.

COleIPFrameWnd сначала пытается преобразоваь локальные горячие клавиши, а затем позволяет выполнить преобразование контейнеру.

Когда переопределять

Перегружайте, когда вам нужны горячие клавиши, не предусмотренные в MFC. Например, если вы пишете "Калькулятор" на основе диалога (обычно у диалогов нет горячих клавиш). Или если таблица горячих клавиш изменяется в зависимости от текущего состояния программы. Переопределяйте CDocument::GetDefaultAccelerator, если вам нужны горячие клавиши, специфичные для каждого документа.


Обработка и отправка сообщений

Функция

CWnd::WindowProc

Назначение

Обрабатывает сообщение. Эта функция - эквивалент оконной процедуры в C++. Первая функция в цепочке обработки сообщений.

Реализация в MFC

CWnd особым образом обрабатывает WM_COMAND и WM_NOTIFY, а остольные сообщения направляются в соответствующие обработчики при помощи карты сообщений.

CControlBar перенаправляет сообщения пользовательского рисования, а также WM_COMMAND, WM_VKEYTOITEM и WM_CHARTOITEM родительскому окну.

Когда переопределять

Переопределяйте эту функцию, если вы хотите вмешаться в обработку сообщений до того, как это сделает MFC, или чтобы не использовать карты сообщений (допустим, в целях повышения производительности). Практически всегда следует вызывать реализацию базового класса.

Функция

CWnd::OnChildNotify

Назначение

Предоставляет дочерним окнам возможность обработать свои собственные уведомления, которые в противном случае достались бы только родительскому окну. Позволяет детям реализовывать своё собственное поведение, не прибегая к помощи родителей. Возвращает TRUE, если сообщение обработано.

Реализация в MFC

CWnd возвращает FALSE.

CButton, CListBox, CComboBox, CStatusBarCtrl, CTabCtrl, CListCtrl, и CHeaderCtrl направляют сообщения пользовательского рисования в виртуальные функции, такие как OnDraw и OnCompareItem. Благодаря этому элементы управления могут отрисовывать себя сами.

Когда переопределять

Переопределяйте, когда вы хотите обработать уведомление (WM_COMMAND или WM_NOTIFY) в дочернем окне, а не в родительском. Например, комбинированный список мог бы сам наполнять себя в ответ на собственное уведомление CBN_DROPDOWN. Или поле ввода могло бы проверять правильность набираемого текста. Возвращайте TRUE, если не хотите, чтобы родительское окно обработало сообщение.


Маршрутизация команд

Функция

CWnd::OnCommand

Назначение

Обрабатывает сообщение WM_COMMAND (команды и уведомления). Все WM_COMMAND'ы попадают сюда.

Реализация в MFC

CWnd передаёт уведомления от элементов управления в их функцию OnChildNotify. Если оно там не обработано, или если это команда, она передаётся в OnCmdMsg.

CFrameWnd осуществляет специальную обработку, относящуюся к контекстной справке.

CMDIFrameWnd даёт активному дочернему окну возможность обработать команду.

Когда переопределять

Редко. Переопределяйте эту функцию, когда вам нужно обработать команду до того, как MFC пропустит её через карты сообщений. Например, когда идентификатор команды хранится в переменной (в 32-битной MFC в этом случае лучше использовать ON_COMMAND_RANGE). Или когда вы связали с классом элемент управления, который не следует правилам использования WM_COMMAND (HWND в старшем слове LPARAM, код уведомления - в младшем), и хотите избежать предупреждений MFC.

Функция

CWnd::OnNotify

Назначение

Обрабатывает сообщения WM_NOTIFY (уведомления). Все WM_NOTIFY'и попадают сюда.

CWnd даёт элементу управления возможность обработать собственные уведомления, вызывая его функцию OnChildNotify. Если уведомление не обработано, оно передаётся в OnCmdMsg.

CSplitterWnd передаёт необработанные уведомления родительскому окну.

Когда переопределять

Редко. В тех же случаях, что и OnCommand.

Функция

CCmdTarget

Назначение

Базовый класс для объектов, которые имеют карты сообщений и могут обрабатывать команды и уведомления.

Реализация в MFC

От него порождаются классы CWnd, CDocument, CDocTemplate и CWinThread (или CWinApp).

Когда переопределять

Если вам нужен класс, способный обрабатывать команды или обновлять объекты пользовательского интерфейса, произведите его от CCmdTarget.

Функция

CCmdTarget::OnCmdMsg

Назначение

Обрабатывает команды, уведомления и CN_UPDATE_COMMAND_UI.

Реализация в MFC

CCmdTarget направляет команду в соответствующий обработчик при помощи карты сообщений.

CFrameWnd вызывает по порядку OnCmdMsg следующих объектов: активного представления (CView), самого себя (CWnd) и приложения (CWinApp), реализуя тем самым обработку команд архитектуры документ/представление.

CView передаёт управление в m_pDocument->OnCmdMsg, а уже затем выполняет обработку сам.

Когда переопределять

Переопределяйте эту функцию, когда хотите включить дополнительные объекты, такие как дочернее окно, не произведённое от CView или немодальный диалог, в процесс обработки команд. Почти всегда следует вызывать реализацию базового класса, или стандартная обработка команд перестанет работать. Можно использовать OnCmdMsg, чтобы напрямую отправлять сообщения в любой класс, порождённый от CCmdTarget. Возвращайте TRUE, если хотите остановить дальнейшую маршрутизацию.


Объекты пользовательского интерфейса

Функция

CCmdUI

Назначение

Представляет объект пользовательского интерфейса, состояние которого может обновлять любой получатель команд в цепочке маршрутизации.

CCmdUI используется для пунктов меню и элементов управления. Порождённые от него классы CStatusCmdUI и CToolCmdUI используются для панелей строки состояний и кнопок на панели инструментов.

CCmdUI предоставляет виртуальные функции, такие как SetText, Enable, SetCheck и т. д., для манипулирования объектом.

Когда переопределять

Порождайте от CCmdUI новый класс, чтобы реализовать не предусмотренный в MFC тип объекта пользовательского интерфейса, требующий обновления.

Функция

CCmdUI::DoUpdate

Назначение

Осуществляет обновление объекта пользовательского интерфейса.

Реализация в MFC

Посылает CN_UPDATE_COMMAND_UI заданному получателю, передавая указатель на объект класса CCmdUI в качестве параметра. Получателем обячно является главное окно, которое перенаправляет сообщеине во все объекты архитектуры документ/представление (документ, представление, само главное окно и приложение), каждый из которых может внести вклад в обновление состояния объекта.

Когда переопределять

Не знаю ни одной ситуации, в которой вам может потребоваться переопределить эту функцию.

Функция

WM_IDLEUPDATECMDUI
CWnd::OnIdleUpdateCmdUI

Назначение

Это сообщение, определённое в MFC (объявлено в AFXPRIV.H), посылается главному окну и всем его потомкам из OnIdle.

Реализация в MFC

CControlBar вызывает OnUpdateCmdUI.

CFrameWnd обновляет свою компоновку (положение и размер панелей управления и клиентского окна), главное меню и заголовок.

CMDIFrameWnd обновляет меню.

COleIPFrameWnd обновляет главное окно и окно контейнера.

Когда переопределять

Вы можете перехватывать это сообщение, чтобы обновлять объекты пользовательского интерфейса в процессе фоновой обработки. Окно должно быть потомком (не обязательно прямым) главного окна, поэтому такой способ не будет работать для немодальных диалогов, у которых родителем является рабочий стол. Необходимо включить AFXPRIV.H, чтобы обрабатывать это сообщение.

Функция

CControlBar::OnUpdateCmdUI

Назначение

Обновляет объекты пользовательского интерфейса, принадлежащие панели управления.

Реализация в MFC

CToolBar обновляет свои кнопки.

CStatusBar обновляет свои панели.

CDialogBar вызывает UpdateDialogControls, чтобы обновить свои элементы управления.

Когда переопределять

Переопределяйте эту функцию, чтобы обновлять объекты на специализированной контрольной панели. Или используйте её, чтобы обновлять объекты напрямую (без обработки сообщений).

Функция

CWnd::UpdateDialogControls

Назначение

Обновляет элементы управления диалога.

Реализация в MFC

CWnd посылает CN_UPDATE_COMMAND_UI для каждого элемента управления диалога.

Когда переопределять

Вызывайте эту функцию, когда вам требуется обновить элементы управления диалога. Её можно вызывать из обработчика OnIdleUpdateCmdUI для немодальных диалогов, или когда что-то изменяется в модальном диалоге. Переопределять её требуется редко.


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.