Окт 16 2009

Внесение изменений в меню

Обычно в сложных приложениях возникает необходимость изменять меню в ходе выполнения программы. Win32 API предоставляет соответствующие функции для модификации меню и его отдельных пунктов.
Состав меню можно изменять с помощью следующих функций: AppendMenu — добавляет новый элемент в конец меню; DeleteMenu — удаляет существующий пункт меню и уничтожает его; InsertMenu — вставляет в меню новый пункт; RemoveMenu — удаляет существующий пункт меню.
Необходимо хорошо понимать, как различаются функции DeleteMenu и RemoveMenu, когда они применяются к пунктам-подменю. Функция DeleteMenu уничтожает это подменю, а функция RemoveMenu — нет.
Для пунктов меню наиболее часто применяются такие изменения, как смена символьной строки имени пункта, установка или снятие отметки, изменение статуса пункта. Функция SetMenuItemlnfo позволяет выполнять сразу несколько таких операций в одном вызове функции. Можно также использовать более конкретные функции для выполнения отдельных операций, которые приведены в следующем списке:
CheckMenuItem — управляет отметкой пунктов-флажков; CheckMenuRadioItem — управляет отметкой пунктов-переключателей; EnableMenuItem — изменяет статус пункта меню; ModifyMenu — изменяет имя пункта меню.
Некоторые из функций стоит рассмотреть более подробно.


Окт 16 2009

Добавление меню к окну приложения

После определения меню в файле описания ресурсов оно еще не появится в составе окна приложения. Чтобы это случилось, меню нужно присоединить к окну. Для этого можно использовать несколько способов.
Наиболее традиционным способом является присваивание полю LpszMenuName структуры WNDCLASSEX значения указателя на имя меню, что надо сделать еще перед регистрацией класса окна. Если имя меню определено как целочисленный идентификатор (например, IDR_MENU1), то применяйте макрос MAKEINTRESOURCE для получения значения, присваиваемого полю LpszMenuName.
Так как во всех примерах программного кода в данной книге главное окно приложения создается с использованием объекта класса KWnd, то рассматриваемый способ присоединения меню реализуется передачей значения MAKEINTRES0URCE(IDR_MENU1) параметру menuName конструктора класса KWnd .
Напомним, что оконный класс1, регистрируемый с использованием структуры wc типа WNDCLASSEX, определяет меню, используемое по умолчанию всеми окнами этого класса. А что значит «используемое по умолчанию»? Только то, что при создании окна с помощью функции CreateWindow параметру hMenu этой функции передается значение NULL. Это видно в коде конструктора класса KWnd.
Вы можете связать с окном при его создании другое меню, отличающееся от того, которое применяется по умолчанию. В этом способе требуемое меню сначала загружается при помощи функции LoadMenu, имеющей следующий прототип:
HMENU LoadMenu(HINSTANCE hlnstance, LPCTSTR IpMenuName);
Затем дескриптор меню hMenu, возвращаемый функцией LoadMenu, передается параметру hMenu функции CreateWindow.
Есть и еще один способ назначения меню, когда для этой цели используется функция SetMenu:
BOOL SetMenu(HWND hWnd. HMENU hMenu);
В качестве параметров данная функция принимает дескриптор окна и дескриптор меню, возвращенный функцией LoadMenu. Новое меню заменяет старое меню, если оно уже было.


Окт 16 2009

Процедура определения меню нулевого уровня

1. Для каждого пункта меню выполните описанную выше процедуру определения пункта для меню г'-го уровня, полагая значение i равным нулю.
2. Если возникнет необходимость перегруппировать пункты меню в пределах конкретного уровня, то перетащите пункты в нужную позицию при помощи мыши. Сохраните ресурс меню аналогично сохранению ресурса пиктограммы.


Окт 16 2009

Процедура определения пункта для меню i-го уровня

1. Начало.
2. Двойным щелчком мыши на прямоугольнике пункта меню вызовите диалоговое окно Menu Item Properties.
3. Если пункт определяет подменю, то есть меню (i+ 1)-го уровня, выполните следующую последовательность действий:
■ установите флажок Pop-up;
■ введите имя пункта. Если оно содержит мнемонический символ, то перед таким символом нужно вставить знак &;
■ при необходимости задайте другие опции пункта;
■ закройте окно Menu Item Properties;
■ для каждого пункта меню (i + 1)-го уровня выполните настоящую процедуру, подставив на месте параметра г значение i + 1.
4. Если пункт определяет команду, то выполните следующую последовательность действий:
■ сбросьте флажок Pop-up;
■ введите имя пункта, предваряя мнемонический символ знаком &;
■ введите идентификатор пункта;
при необходимости задайте другие опции пункта;
закройте окно Menu Item Properties.
5. Если пункт определяет горизонтальную разделительную линию, то выполните следующую последовательность действий:
сбросьте флажок Pop-up;
установите флажок Separator;
• закройте окно Menu Item Properties.
6. Конец.
Обратите внимание на то, что на шаге 3 алгоритма процедура вызывает саму себя. Именно поэтому она является рекурсивной.
При кажущейся простоте алгоритма на самом деле он может описывать довольно сложный процесс. Вообразите себе виртуальный стек, на вершине которого запоминается очередной рекурсивный вызов процедуры из шага 3 алгоритма. Когда разработчик, создающий меню, достигает шага 6 алгоритма, это в общем случае вовсе не конец процесса. Если виртуальный стек не пуст, то нужно вернуться к прерванной процедуре, из которой произошел вызов выполняемой процедуры. И, конечно, удалить запомненный вызов с вершины стека. И только когда воображаемый стек окажется пуст, создание рассматриваемого пункта меню i-го уровня будет завершено.
Теперь можно описать процедуру создания меню верхнего уровня при помощи редактора меню.


Окт 16 2009

Уровни меню

Меню верхнего уровня обычно относится к нулевому уровню. Если пункт этого меню определяет некоторое подменю, то такое подменю будет называться меню первого уровня. Если пункт меню первого уровня, в свою очередь, определяет некоторое подменю, то такое подменю будет называться меню второго уровня.
Прежде чем излагать процедуру создания меню при помощи редактора меню, опишем рекурсивную процедуру определения произвольного пункта для меню 7-го уровня.


Окт 16 2009

Вызов редактора меню

В главном меню Visual Studio выполните команду Insert ► Resource. В появившемся диалоговом окне Insert Resource укажите тип ресурса Menu и нажмите кнопку New.
По умолчанию редактор присваивает первому из создаваемых шаблонов меню имя IDR_MENU1. В файле resource.h этот идентификатор определяется как целочисленная константа. Если вы хотите изменить назначенное имя, то сделайте двойной щелчок мышью на полосе меню и в открывшемся диалоговом окне Menu Properties введите необходимый идентификатор в текстовом поле ID. Например, для шаблона главного меню можно оставить имя по умолчанию IDR_MENU1, а для шаблонов контекстных меню назначить имена, отражающие их назначение.
В начале полосы создаваемого меню будет отображен пунктирный прямоугольник нулевого пункта меню. Нумерация пунктов начинается с нуля.


Окт 16 2009

Определение меню в виде ресурса

Вы можете создать меню одним из трех способов:
на основе шаблона меню, определенного в файле описания ресурсов;
при помощи функций CreateMenu и AppendMenu;
на основе шаблона меню, определяемого в памяти во время выполнения программы при помощи функции LoadMenuIndirect.


Окт 16 2009

Пункт меню, применяемый по умолчанию

Подменю может содержать один пункт, выполняемый по умолчанию. Имя этого пункта выделяется жирным шрифтом. Когда пользователь открывает подменю двойным щелчком мыши, Windows автоматически выполнит команду по умолчанию, закрыв при этом подменю. Если пункт по умолчанию отсутствует, то двойной щелчок приводит просто к открытию подменю.
Атрибут «применяемый по умолчанию» может быть назначен любому пункту подменю при помощи функции SetMenuDefaultltem.


Окт 16 2009

Отметка пунктов меню

Иногда пункт меню используется в роли флажка (check box). Флажок может быть установлен или сброшен. Переход из одного состояния в другое происходит при каждом выборе пункта меню. Установленный флажок помечается символом «галочка», а сброшенный флажок теряет отметку. Флажки обычно объединяются в группы и обеспечивают выбор либо одной, либо нескольких опций одновременно.
Пункты меню могут использоваться также в роли переключателей (radio button). Переключатели, как и флажки, обычно используются в группе. В отличие от флажков, переключатели связываются только с взаимоисключающими опциями, поэтому в группе можно выбрать только один переключатель. Выбранный переключатель отмечается жирной точкой или маленьким закрашенным кружком.


Окт 16 2009

Статус пунктов меню

Пункты меню могут быть разрешенными {enabled), запрещенными (disabled) и недоступными (grayed).
По умолчанию пункт меню является разрешенным. Когда пользователь выбирает такой пункт, система посылает сообщение WM_COMMAND или отображает соответствующее подменю, в зависимости от типа пункта.
Запрещенный и недоступный пункты с точки зрения поведения одинаковы. Их можно выделить, но нельзя выбрать. То есть и при щелчке мышью, и при нажатии клавиши Enter ничего не происходит. Различаются запрещенный и недоступный пункты только своим внешним видом. Запрещенный пункт выглядит так же, как разрешенный, а недоступный пункт отображается серым цветом. Если вы хотите, чтобы пользователь знал, что пункт меню «отменен», делайте его недоступным.
В хорошо продуманном интерфейсе пользователя приложение должно управлять статусом пунктов меню в зависимости от текущего состояния программы. Например, команда вставки данных из буфера обмена Windows не имеет смысла, если буфер обмена пуст. В такой ситуации лучше отменить и выделить серым цветом соответствующий пункт меню. Вообще, рекомендуется делать недоступными те пункты меню, использование которых в данный момент бессмысленно или даже небезопасно с точки зрения устойчивости работы приложения.
Каков же смысл использования запрещенных пунктов, которые внешне не отличаются от разрешенных пунктов? MSDN указывает, что их можно использовать в обучающих приложениях, когда некоторое окно выводится на экран только для иллюстрации и не должно реагировать на действия пользователя.
Для изменения статуса пунктов меню применяется функция EnableMenuItem.


« Предыдущая страницаСледующая страница »