Визуальное программирование и MFC

       

Таблица сообщений


В библиотеке классов MFC для обработки сообщений используется специальный механизм, который имеет название Message Map - таблица сообщений.

Таблица сообщений состоит из набора специальных макрокоманд, ограниченных макрокомандами BEGIN_MESSAGE_MAP и END_MESSAGE_MAP. Между ними расположены макрокоманды, отвечающие за обработку отдельных сообщений:

BEGIN_MESSAGE_MAP(ИмяКласса,ИмяБазовогоКласса) // макросы END_MESSAGE_MAP()

Макрокоманда BEGIN_MESSAGE_MAP представляет собой заголовок таблицы сообщений. Она имеет два параметра. Первый параметр содержит имя класса таблицы сообщений. Второй - указывает его базовый класс.

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

  • стандартные сообщения Windows обрабатываются функцией обработки по умолчанию;
  • командные сообщения передаются по цепочке следующему объекту, который может обработать командное сообщение.
  • Можно определить таблицу сообщений класса вручную, однако более удобно воспользоваться для этой цели средствами ClassWizard. ClassWizard не только позволяет в удобной форме выбрать сообщения, которые должен обрабатывать класс. Он включит в состав класса соответствующие методы-обработчики. Программисту останется только вставить в них необходимый код. К сожалению, использовать все возможности ClassWizard можно только в том случае, если приложение создано с применением средств автоматизированного программирования MFC AppWizard.

    Рассмотрим макрокоманды, отвечающие за обработку различных типов сообщений.

    Макрокоманда ON_WM_<name>. Обрабатывает стандартные сообщения операционной системы Windows. Вместо <name> указывается имя сообщения без префикса WM_.
    Например:
    ON_WM_CREATE()
    Для обработки сообщений, определенных в таблице макрокомандой On_WM_<name>, вызываются одноименные методы. Имя метода обработчика соответствует названию сообщения, без учета префикса WM_. В классе CWnd определены обработчики для стандартных сообщений. Эти обработчики будут использоваться по умолчанию.
    Макрокоманды ON_WM_<name> не имеют параметров. Однако методы, которые вызываются для обработки соответствующих сообщений, имеют параметры, которые, количество и назначение которых зависит от обрабатываемого сообщения.


    Если определить обработчик стандартного сообщения Window в своем классе, то он будет вызываться вместо обработчика, определенного в классе CWnd (или другом базовом классе). В любом случае можно вызвать метод-обработчик базового класса из своего метода-обработчика.

    Макрокоманда ON_REGISTERED_MESSAGE. Эта макрокоманда обслуживает сообщения операционной системы Windows, зарегистрированные с помощью функции RegisterWindowMessage. Параметра nMessageVariable этой макрокоманды указывает идентификатор сообщения, для которого будет вызываться метод memberFxn:
    ON_REGISTERED_MESSAGE(nMessageVariable, memberFxn)

    Макрокоманда ON_MESSAGE. Данная макрокоманда обрабатывает сообщения, определенные пользователем. Идентификатор сообщения (его имя) указывается параметром message. Метод, который вызывается для обработки сообщения, указывается параметром memberFxn:
    ON_MESSAGE(message,memberFxn)

    Макрокоманда ON_COMMAND. Эти макрокоманды предназначены для обработки командных сообщений. Командные сообщения поступают от меню, кнопок панели управления и клавиш акселераторов. Характерной особенностью командных сообщений является то, что с ними связан идентификатор сообщения.
    Макрокоманда ON_COMMAND имеет два параметра. Первый параметр соответствует идентификатору командного сообщения, а второй - имени метода, предназначенного для обработки этого сообщения. Таблица сообщений должна содержать не больше одной макрокоманды для командного сообщения:


    ON_COMMAND(id,memberFxn)
    Обычно командные сообщения не имеют обработчиков, используемых по умолчанию. Существует только небольшая группа стандартных командных сообщений, имеющих методы-обработчики, вызываемые по умолчанию. Эти сообщения соответствуют стандартным строкам меню приложение. Так например, если строке Open меню File присвоить идентификатор ID_FILE_OPEN, то для его обработки будет вызван метод OnFileOpen, определенный в классе CWinApp.
    Макрокоманда ON_COMMAND_RANGE. Макрокоманда ON_COMMAND ставит в соответствие одному командному сообщению один метод-обработчик В некоторых случаях более удобно, когда один и тот же метод-обработчик применяется для обработки сразу нескольких командных сообщений с различными идентификаторами. Для этого предназначена макрокоманда ON_COMMAND_RANGE.
    Она назначает один метод-обработчик для обработки нескольких командных сообщений, интервалы которых лежат в интервале от id1 до id2:
    ON_COMMAND_RANGE(id1,id2,memberFxn)

    Макрокоманда ON_UPDATE_COMMAND_UI. Данная макрокоманда обрабатывает сообщения, предназначенные обновления пользовательского интерфейса, например меню, панелей управления, и позволяет менять их состояние.
    Параметр id указывает идентификатор сообщения, а параметр memberFxn - имя метода для его обработки:
    ON_UPDATE_COMMAND_UI(id,memberFxn)
    Методы, предназначенные для обработки данного класса сообщений, должны быть определены с ключевым словом afx_msg и иметь один параметр - указатель на объект класса CCmdUI. Для удобства имена методов, предназначенных для обновления пользовательского интерфейса, начинаются с OnUpdate:
    afx_msg void OnUpdate<имя_обработчика>(CCmdUI* pCmdUI);
    В качестве параметра pCmdUI методу передается указатель на объект класса CCmdUI. В нем содержится информация об объекте пользовательского интерфейса, который нужно обновить, - строке меню или кнопке панели управления. Класс CCmdUI также включает методы, позволяющие изменить внешний вид представленного им объекта пользовательского интерфейса.


    Сообщения, предназначенные для обновления пользовательского интерфейса, передаются, когда пользователь открывает меню приложения, а также во время цикла ожидания приложения, когда очередь сообщений приложения становится пуста.
    При этом посылается несколько сообщений, по одному для каждой строке меню. С помощью макрокоманд ON_UPDATE_COMMAND_UI можно определить методы-обработчики, ответственные за обновление внешнего вида каждой строки меню и соответствующие ей кнопки на панели управления. Эти методы могут изменять состояние строки меню - отображать ее серым цветом, запрещать ее выбор, отображать около нее символ "галочка" и т.д.
    Если не определить метод для обновления данной строки меню или кнопки панели управления, то выполняется обработка по умолчанию. Выполняется поиск обработчика соответствующего командного сообщения, и, если он не обнаружен, выбор строки запрещается.

    Макрокоманда ON_UPDATE_COMMAND_UI_RANGE. Эта макрокоманда обеспечивает обработку сообщений, предназначенных для обновления пользовательского интерфейса, идентификаторы которых лежат в интервале от id1 до id2. Параметр memberFxn указывает метод, используемый для обработки:
    ON_UPDATE_COMMAND_UI_RANGE(id1,id2,memberFxn)

    Макрокоманда ON_<name>. Данные макрокоманды предназначены для обработки сообщений от органов управления. Такие сообщения могут передаваться органами управления диалоговой панели. Сообщения от органов управления не имеют обработчиков, используемых по умолчанию. При необходимости их нужно определить самостоятельно.
    Все макрокоманды ON_<name> имеют два параметра. В первом параметре id указывается идентификатор органа управления. Сообщения от этого органа управления будут обрабатываться методом memberFxn. Например:
    ON_BN_CLICKED(id,memberFxn)

    Макрокоманда ON_CONTROL_RANGE. Эта макрокоманда обрабатывает сообщения от органов управления, идентификаторы которых находятся в интервале от id1 до id2. Параметр wNotifyCode содержит код извещения. Метод-обработчик указывается параметром memberFxn:
    ON_CONTROL_RANGE(wNotifyCode,id1,id2,memberFxn)

    Содержание раздела