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


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

Примечание

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

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

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

Функция MFC 1.0 маршрутизации команд и диспетчеризации будет к архитектуре MFC 2.0

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

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

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

MFC 1.0 используется маршрутизация команд в лимитированном смысле для реализации интерфейса MDI (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, с помощью архитектуры команды в диалоговых окнах

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

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

Обратите внимание, что для всех этих функций, которые будут работать неправильно, эти идентификаторы команд должны быть >= 0x8000. Поскольку различные диалоговые окна можно получить направленными на тот же кадр, общие команды должны быть >= 0x8000, пока общей 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 могут изменять состояние или текст меню или для предварительного используются (например, список последних выбиравшихся файлов или OLE контекстное меню команд меню), фактически изменяется структура меню до меню будет выполнено.

Такие же параметры сортировки обработки 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 будет нормальным обработчиком команд обновления и смотрел бы примерно так:

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 и как маршрутизацией сообщений Windows и другие разделы, влияющие на них. Сведения только кратко описаны ниже. В разделе ссылки на библиотеки классов подробные сведения об открытых интерфейсов API. См. исходный код библиотеки MFC дополнительные сведения в подробностях реализации.

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

Проблемы CWnd

Функцию-член CWnd::OnChildNotify реализации предоставляет мощную и расширяемую архитектуру дочерних windows (также известных как элементы управления обработчик) или иным был уведомление сообщений, команд и уведомлений элемента управления, переходить к их родительскому элементу (или «владельцу»). Если дочернее окно (/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 из (см. ниже), полос прокрутки.

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

Проблемы CMDIFrameWnd/CMDIChildWnd

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

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

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

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

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

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

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

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

См. также

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

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

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