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


TN021: Маршрутизация команд и сообщений

ПримечаниеПримечание

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

Эта заметка описывает маршрутизация архитектуру маршрутизации и диспетчера команд, а также сообщения окна дополнительных разделов.

Дополнительные сведения см. в разделе Visual C++ для общих сведений на архитектурах, описанные здесь, особенно различие между сообщениями окнах уведомления элемента управления и команды.Эта заметка предполагается, что вы знакомы с очень проблемы, описанные в печатной документации и только разделах адресов очень сложных.

Функции MFC 1.0 маршрутизации и диспетчера команд эволюционирует в архитектуре MFC 2.0

Окна имеют сообщение WM_COMMAND, перегружен, чтобы обеспечить уведомления команд меню и сочетаний клавиш и уведомления диалогового окно-элемента управления.

MFC 1.0, построенный на этом немногую, позволяя обработчик команд (например, «OnFileNew») в производном классе CWnd для получения вызывать в ответ на определенное WM_COMMAND.Это приклеиванно вместе с структурой данных называется сопоставлением сообщений и результатами в очень космическая-эффективном механизме команды.

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

MFC 1.0 использует маршрутизацию команды в смысле limited для реализации нескольких интерфейса MDI.(Команды делегата фрейма окна интерфейса MDI с его активным дочернему окну mdi-приложения).

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

Идентификаторы команд

См. раздел Visual C++ для объяснения маршрутизации команд и процесса привязки.Техническая примечание 20 содержит сведения об именовании идентификаторов.

Универсальный шаблон используется префикс «ID_» идентификаторы команд.Идентификаторы команд >= 0x8000.Линия или строка состояния сообщения будут отображаться строку описания команды если ресурс STRINGTABLE с теми же идентификаторами как идентификатор команды.

В ресурсах приложения может идентификатор команды появляется в нескольких местах:

  • В одном ресурсе STRINGTABLE, который имеет тот же идентификатор, как запрос сообщение-линии.

  • По возможности много ресурсов МЕНЮ, вложенные к пунктам меню, вызывающих ту же команду.

  • (РАСШИРЕННЫЙ) в кнопке диалогового окна для команды GOSUB.

В исходном коде приложения может идентификатор команды появляется в нескольких местах:

  • В вашем RESOURCE.H (или другом основном файле заголовков символов) для определения приложения идентификаторы команд.

  • Это ВОЗМОЖНО в массиве идентификатор, который используется для создания панель инструментов.

  • в макросе ON_COMMAND.

  • Это ВОЗМОЖНО в макросе ON_UPDATE_COMMAND_UI.

В настоящее время единственным реализация в MFC, требующий идентификаторы команд >= 0x8000 реализация диалоговым окнам и командам GOSUB.

Команды GOSUB, с помощью архитектуры команды в диалоговых окнах

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

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

Обратите внимание, что для всех этих функций работал, идентификаторы команд должны быть >= 0x8000.Поскольку многие диалоговых окон можно получить направленными на один и тот же кадру общие команды должны быть >= 0x8000, пока nonshared IDCs в определенном диалоговом окне, должно быть <= 0x7FFF.

Можно задать обычную кнопку в обычном модальном диалоговом окне с IDC набора кнопки соответствующее идентификатору командыКогда пользователь выбирает кнопку, владелец диалогового окна (обычно окна главного фрейма) возвращает команду, как и любая другая команда.Это действие вызывается командой GOSUB поскольку оно обычно используется, чтобы вывести другой - диалоговое окно (GOSUB первого диалогового окна).

Можно также вызвать функцию CWnd::UpdateDialogControls в диалоговом окне и передать ему адрес главного фрейма окна.Эта функция включить или отключить элементы управления диалогового окна, основанные на равны ли они обработчиков команд во фрейме.Эта функция вызывается автоматически для панелей элементов управления в цикле приложения простоя, но необходимо вызывать непосредственно для обычных диалоговым окнам, что необходимо иметь эту функцию.

При вызове ON_UPDATE_COMMAND_UI

Состояние флажка включается поддержка/всего времени пунктов меню все программы может быть сложными дорогей проблемой.Общий метод пункты меню включения/проверка, только когда пользователь выбирает контекстное меню.Реализация MFC 2.0 CFrameWnd обрабатывает сообщение WM_INITMENUPOPUP и использует архитектуру маршрутизации команд для указания состояния меню с помощью обработчиков ON_UPDATE_COMMAND_UI.

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

Структура меню приложения, изменянная Visual C++ используется для представления потенциала команды, доступные во время WM_INITMENUPOPUP.Обработчики ON_UPDATE_COMMAND_UI может изменить состояние или текст меню или для предварительного используют (например, список файлов MRU или ЯВЛЯЕТСЯ всплывающее меню команд), фактически изменить структуру меню, прежде чем меню отображается.

Одну и ту же обработку ON_UPDATE_COMMAND_UI сортировка выполняется для панелей инструментов (и других панелей элементов управления), когда приложение вводит свой бездействующий цикл.См. в библиотеке классов ссылается, и Техническая примечание 31 дополнительные сведения о панелях элементов управления.

Вложенные всплывающие меню

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

Во-первых, оно вызывается для раскрывающегося меню.Это необходимо, так как всплывающие меню не имеют идентификаторов и используется идентификатор первого пункта меню раскрывающегося меню для обращения ко всему всплывающему меню.В этом случае переменную-член m_pSubMenu объекта CCmdUI будет не равны null и указывает на всплывающему меню.

Во-вторых, она вызывается непосредственно перед пунктов меню в всплывающем меню быть выписанным.В этом случае идентификатор относится только к первому пункту меню и переменную-член m_pSubMenu объекта CCmdUI будет иметь значение null.

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

File>
    New>
        Sheet (ID_NEW_SHEET)
        Chart (ID_NEW_CHART)

Команды ID_NEW_SHEET и ID_NEW_CHART можно независимо включить или отключить.Контекстное меню меню Создать должны быть включены при соблюдении одного из 2 включена.

Обработчик команд для ID_NEW_SHEET (первой команды во всплывающем) как будет выглядеть текст:

void CMyApp::OnUpdateNewSheet(CCmdUI* pCmdUI)
{
    if (pCmdUI->m_pSubMenu != NULL)
    {
        // enable entire pop-up for "New" sheet and chart
        BOOL bEnable = m_bCanCreateSheet || m_bCanCreateChart;

        // CCmdUI::Enable is a no-op for this case, so we
        //   must do what it would have done.
        pCmdUI->m_pMenu->EnableMenuItem(pCmdUI->m_nIndex,
            MF_BYPOSITION | 
                (bEnable ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
        return;
    }
    // otherwise just the New Sheet command
    pCmdUI->Enable(m_bCanCreateSheet);
}

Обработчик команд для ID_NEW_CHART является обычным обработчиком команд обновления и смотрел бы что-то how to:

void CMyApp::OnUpdateNewChart(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(m_bCanCreateChart);
}

ON_COMMAND и ON_BN_CLICKED

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

ПримечаниеПримечание

В действительности, все сообщения уведомления элемента управления проходят через цепочку обработчика команды.Например, технически возможно, написать обработчик уведомления элемента управления для EN_CHANGE в классе документа.Обычно это не желательно поскольку практические применения этой функции мало, функция не поддерживается ClassWizard и использование функций может привести к утлом коде.

Отключение автоматического отключения элемент управления " Кнопка "

Если установить элемент управления " Кнопка " диалоговой панели или в диалоговом окне с использованием при вызове CWnd::UpdateDialogControls в ваших, обратите внимание, что кнопки, которые не имеют обработчики ON_COMMAND или ON_UPDATE_COMMAND_UI автоматически будут блокированы, границами.В некоторых случаях, не будет иметь обработчик, но требуется кнопки остаются включенными.Самым простым способом достижения этого добавить фиктивный обработчик команд (простой, чтобы сделать с функциональным возможностям ClassWizard) и не выполнять никаких действий в ней.

Маршрутизация сообщения окна

Далее описывается еще несколько дополнительных подразделов в классах MFC и как маршрутизацию сообщений окон и другие шаги тесно сжимают их.Сведения только описано здесь представлено краткое.См. в разделе справочник по библиотеке классов дополнительные сведения о открытый API-интерфейс.Дополнительные сведения см. в разделе исходный код библиотеки MFC дополнительные сведения о подробности реализации.

Пример см. в Техническая примечание 17 дополнительные сведения об очистке окна, очень важный шаг для всего CWnd- производные классы.

Проблемы CWnd

Функция-член CWnd::OnChildNotify реализации предоставляет мощную и расширяемую архитектуру для дочерних окон (также известных как элементы управления) или обработчик сообщений, в противном случае информирован команд и уведомлений элемента управления, которые расходятся к их родительскому элементу (или «владелец»).Если дочернее окно (/control) сам объект C++ CWnd, то сначала OnChildNotify виртуальная функция вызывается с параметрами из исходного сообщения (т е структуры MSG ).Дочернее окно может оставить сообщение одной съесть его или изменить сообщение для родительского элемента (в разреженное множество столбцов).

Реализация по умолчанию CWnd обрабатывает следующие сообщения и использует обработчик OnChildNotify чтобы разрешить дочерние окна (элементов управления) к первому доступа на сообщении:

  • WM_MEASUREITEM и WM_DRAWITEM (для собственный-притяжки)

  • WM_COMPAREITEM и WM_DELETEITEM (для собственный-притяжки)

  • WM_HSCROLL и WM_VSCROLL

  • WM_CTLCOLOR

  • WM_PARENTNOTIFY

Обратите внимание, что обработчик OnChildNotify используется для изменения сообщения рисования владельцем в сообщения собственный-притяжки.

В дополнение к обработчику OnChildNotify сообщения прокрутки имеют более дополнительные расширения функциональности маршрутизации.Представленной ниже приведены дополнительные сведения о полосах прокрутки и источниках сообщений WM_HSCROLL и WM_VSCROLL.

Проблемы CFrameWnd

Класс CFrameWnd обеспечивает большую часть маршрутизации команд и реализации обновления интерфейса пользователя.Это в основном используется для окна главного фрейма приложения (CWinApp::m_pMainWnd), но применяется ко всем окнам кадра.

Окно главного фрейма окна со строкой меню и родительский линии строки состояния или сообщений.См. обсуждение о маршрутизации. приведенное выше и WM_INITMENUPOPUP. команды

Класс CFrameWnd обеспечивает управление активного представления.Следующие сообщения направляются через активное представление.

  • Все сообщения команды (активное представление возвращает первый доступ к ним).

  • Сообщения WM_HSCROLL и WM_VSCROLL from (см. ниже) полос прокрутки с общим родителем.

  • WM_ACTIVATEWM_MDIACTIVATE для MDI) получают повернутыми в вызовы виртуальных функций CView::OnActivateView.

Проблемы CMDIFrameWnd/CMDIChildWnd

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

Общая схема маршрутизации, что активное дочернее окно MDI получает первый доступ к командам.Функции PreTranslateMessage значения по умолчанию обрабатывают таблицы сочетаний клавиш и для дочерних окон MDI (first) и фрейма MDI (секунды), а также стандартных ускорителей система-команды MDI обычно обрабатывается TranslateMDISysAccel (последним).

Проблемы полосы прокрутки

При обработке прокрутка-сообщение (WM_HSCROLL/OnHScroll и/или WM_VSCROLL/OnVScroll), следует попробовать написать код обработчика поэтому он не зависит от, где сообщение поступило от полосы прокрутки.Это не только общие окна выдает, поскольку сообщения прокрутки могут поступать из истинных элементов управления полосы прокрутки или полос прокрутки WS_HSCROLL/WS_VSCROLL, которые не являются элементов управления " полоса прокрутки ".

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

На бортовой заметку, 2 производного класса CWnd где стили полосы прокрутки, определенные в создают время поглощены к окнам и не передаются.При передаче в процедуре создания WS_HSCROLL и могут быть установлены WS_VSCROLL независимо, но после создания не могут быть изменены.Конечно, не следует напрямую просмотра или задания WS_? ПРОКРУТИТЕ список битов стилей окна, они создали.

Для CMDIFrameWnd стили полосы прокрутки передаче в Создать или LoadFrame используется для создания MDICLIENT.Если необходимо обладать прокручиваемой области, MDICLIENT (например, руководитель программ окон) обязательно устанавливать оба стиля полосы прокрутки (WS_HSCROLL | WS_VSCROLL) для стиля, используемого для создания CMDIFrameWnd.

Для полосы прокрутки CSplitterWnd стили применяются к специальным совместному использованию полосы прокрутки областей разделителя.Для статических полях разделитель, обычно не будет устанавливать любой стиль полосы прокрутки.Для динамических окон разделитель, обычно будет иметь стиля полосы прокрутки для направления можно разделить, т е WS_HSCROLL если можно разбить строки, если WS_VSCROLL можно разделить столбцы.

См. также

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

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

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