logo
Конспект по ООПиП ч

Обновление команд.

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

Один состоит в том, чтобы организовать огромную таблицу, элементами которой будут все имеющиеся в приложении пункты меню, каждому из которых сопоставлен флаг. Состояние флага — TRUE или FALSE — указывает, доступен ли этот пункт меню. Как только возникает необходимость вывести меню на экран, можно просмотреть таблицу и все станет ясно. При любой операции, которая может повлечь за собой изменения в статусе какого-либо пункта меню, таблица обновляется. Все это в совокупности называется подходом непрерывного обновления (continuous-updating approach). Другой подход состоит в том, чтобы, не имея такой таблицы, перед каждым выводом меню на экран анализировать все условия, которые влияют на возможную блокировку. Он называется подходом обновления по требованию (update-on-demand approach). Именно такой подход и реализован в Windows. Когда наступает время выводить на экран меню, конкретные объекты "знают", нужно ли блокировать связанный с ними пункт меню. Например, объект класса документа знает, был ли он модифицирован после последнего сохранения, и решает, стоит ли блокировать пункт Save меню File. Объект класса представления знает, есть ли выделенный фрагмент текста, и может решить, как поступить с пунктами Cut и Copy меню Edit. Все это означает, что комплексная задача блокировки пунктов меню в соответствии с контекстом приложения распределяется между различными объектами приложения, а не возлагается на главную вызывающую подпрограмму WndProc(). Подход, реализованный в MFC, состоит в том, чтобы использовать небольшой объект класса CCmdUI (класс интерфейса с командами пользователя — command user interface) и предоставить ему возможность перехватывать любые сообщения ON_UPDATE_COMMAND_UI. Организовать такой перехват можно, добавив (или предоставив возможность ClassWizard добавить) макрос ON_UPDATE_COMMAND_UI в карту сообщений. Объект класса CCmdUI также используется для блокировки или разблокировки командных кнопок и других элементов управления.

Класс CCmdUI имеет следующие функции-члены.

Enable(). Принимает аргумент TRUE или FALSE. Блокирует элемент интерфейса пользователя, если передан аргумент FALSE, в противном случае делает элемент доступным.

SetCheck(). Включает или выключает элемент управления.

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

SetText(). Устанавливает текст надписи пункта меню или кнопки, если элемент управления — кнопка.

DoUpdate(). Формирует сообщение.

Как ClassWizard помогает перехватывать команды и их обновления.

В диалоговом окне ClassWizard, в списке Object IDs выделено имя класса. Ниже имеются идентификаторы всех ресурсов (меню, панелей инструментов, элементов управления и т.д.), которые могут формировать команду или сообщение при условии, что объект данного класса присутствует на экране. Если вы выделите один из них, то список связанных с ним сообщений Messages станет значительно короче. С каждым идентификатором ресурса связаны только две строки в списке сообщений — COMMAND и UPDATE_COMMAND_UI. Выбор первой позволяет добавить в класс функцию, которая будет обрабатывать либо ту команду меню, которую выбрал пользователь, либо щелчок на кнопке, т.е. обрабатывать команду. Выбор второй позволяет добавить в класс функцию, которая задает состояние пункта меню, кнопки или любого другого элемента управления перед тем, как операционная система соберется вывести его на экран, т.е. выполнить обновление команды. Если нужно ввести новую функцию для перехвата команды или обновления, щелкните на кнопке Add Function. Это включит в процесс разработки еще один этап — ClassWizard предоставит вам возможность изменять имя функции, которое он сформировал по стандартной схеме. Имя функции обработки команды начинается с On. Оставшаяся часть формируется следующим образом— удаляется ID и символы подчеркивания из идентификатора ресурса, а каждое слово пишется строчными буквами, кроме первого символа. Имена обработчиков обновления команд начинаются с OnUpdate, а далее используется то же преобразование идентификатора ресурса. Например, функция, которая перехватывает команду от ID_APP_EXIT, будет называться OnAppExit, а функция, которая обновляет ID_APP_EXIТ, будет называться OnUpdateAppExit. Далеко не каждая команда нуждается в обработчике обновления. Объект класса фрейма окна выполняет некоторую работу в части блокировки элементов управления самостоятельно, безо всяких указаний на то со стороны разработчика. Пусть у вас есть меню Network (Сеть), а в нем — пункт Sent (Послать). Команда этого пункта меню перехватывается объектом класса документа. Если же в приложении не открыт ни один документ, этот пункт меню будет заблокирован главным окном приложения, причем блокировка организуется без вашего участия. Для многих команд этого вполне достаточно, т.е. команда блокируется, если объект, который должен ее обрабатывать, не существует. Для других же, которые могут иметь смысл, только в случае, если что-то выбрано или выделено, схема блокировки значительно сложнее. Вот здесь и нужно участие разработчика в программировании процесса обновления команды.