Поделиться через


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. См. в документации по продукту дополнительные сведения об этих макросах.

См. также

Другие ресурсы

Технические примечания по номеру

Технические примечания по категории