Академический Документы
Профессиональный Документы
Культура Документы
ЛЕКЦИЯ 10
СОЗДАНИЕ МЕНЮ ______________________________________________________________________ 1
Основные типы меню____________________________________________________________________ 1
Создание меню с помощью редактора меню ________________________________________________ 1
Атрибуты элементов меню _______________________________________________________________ 2
Подключение меню к окну приложения _____________________________________________________ 3
Файл ресурсов _________________________________________________________________________ 3
Создание обработчика событий для элемента меню __________________________________________ 4
Создание акселераторов (клавиш быстрого вызова) __________________________________________ 5
Загрузка акселераторов _________________________________________________________________ 6
МЕНЮ
Ничто не ценится так дорого пользователем и не стоит так
дешево программисту, как меню.
Мигель Сервантес
Одной из основных проблем разработки пользовательского интерфейса любой программы является
создание средства быстрого и удобного доступа ко всем командам, поддерживаемым данным приложени-
ем. Пользователи уже успели привыкнуть к тому, что для запуска большинства команд нужно выполнить
несколько щелчков мышью. Кроме того, они хотят, чтобы все команды были сосредоточены в одном мес-
те.
Чтобы удовлетворить все эти требования, в Visual Studio предусмотрено специальное средство – ре-
дактор меню, с помощью которого можно быстро и удобно создать структуру меню разрабатываемой про-
граммы. Данное средство можно использовать и для создания строки меню для любой формы вашего
приложения, а также контекстных (или всплывающих) меню. Как правило, все команды сгруппированы по
логическим функциям (работа с файлами, редактирование, изменение режимов просмотра объектов и
др.).
В файл ресурсов автоматически добавится пустое меню. Чтоб сконструировать нужный вид меню,
надо перейти на закладку ResourceView окна Workspace. Раскройте дерево ресурсов, а затем раскройте
папку Menu.
В контекстном меню идентификатора меню выберите пункт Properties и в диалоговом окне Menu
Properties:
выберите русский язык в качестве языка интерфейса;
измените идентификатор ресурса (в качестве префикса обычно используют IDR_ – IDentifier of Re-
source).
Изменить последовательность команд в меню можно путём перетаскивания строк в окне редактора
меню.
Файл ресурсов
Все ваши действия при создании меню записываются в файле ресурсов (файл с расширением *.гс).
Файл ресурсов недоступен в среде Visual Studio для просмотра и редактирования, но его можно открыть с
помощью блокнота. Вот как выглядит текст в файле ресурсов, описывающий меню:
// Menu
IDR_MAIN_MENU MENU DISCARDABLE
BEGIN
POPUP "Файл"
BEGIN
MENUITEM "Открыть", IDM_OPEN
MENUITEM "Выход", IDM_EXIT
END
END
Первая строка содержит параметр, который определяет способ хранения меню в оперативной памя-
ти. Этот параметр может принимать следующие значения:
DISCARDABLE меню может быть удалено из памяти, если больше не используется;
FIXED меню постоянно находится в памяти;
LOADONCALL меню загружается при обращении к нему;
MOVEABLE меню может перемещаться в другую область памяти;
PRELOAD меню загружается при запуске программы.
Вот текст, описывающий строку в поле Prompt, элемента меню (он также находится в файле ресур-
сов):
Для ввода нового акселератора дважды щёлкните на пустой строке в таблице акселераторов, для
редактирования – на существующей. Диалоговое окно Accel Properties позволяет сформировать
таблицу акселераторов.
Таблица акселераторов определяется в файле описания ресурсов приложения в следующем виде:
<ID_ACCEL> ACCELERATORS
BEGIN
Key , ID , [Type] , [Modifiers]
END
ID_ACCEL идентификатор таблицы акселераторов;
Key определяет клавишу, которая будет использована для создания акселератора;
ID задает идентификатор команды WM_COMMAND, которая передается в функцию окна
при использовании акселератора;
Туре принимает значение ASCII или VIRTKEY и определяет клавишу с использованием ко-
да ASCII или с использованием кода виртуальной клавиши;
Modifiers если в поле Туре стоит VIRTKEY, то здесь можно указывать параметры Ctrl, Alt или
Shift.
Загрузка акселераторов
К счастью, чтобы использовать в программе акселераторы, не требуется почти никаких затрат, по-
скольку поддержка акселераторов встроена в операционную систему. Но, как обычно, не может быть все
столь хорошо. Дело в том, что сначала таблицу акселераторов необходимо загрузить из ресурсов вашей
программы, после чего вызывать функцию TranslateAccelerator в цикле обработки сообщений главного
окна программы. Вот здесь-то и кроется засада, поскольку в модальном диалоге цикл обработки сообще-
ний скрыт где-то в недрах операционной системы и в явном виде недоступен.
Конечно, можно было бы создать немодальный диалог, но это потребует дополнительных усилий про-
граммиста – например, в случае вложенных немодальных диалогов придется изрядно попотеть, стараясь
не допустить переключения между диалогом-родителем и диалогом-потомком. К счастью, программисты
из одной чрезвычайно крупной компании при разработке MFC поступили весьма интересно, поскольку в
MFC нет модальных диалогов в чистом виде – при использовании функции DoModal в наследнике CDia-
log создается типичный немодальный диалог с циклом выборки сообщений, а "модальность" такого диало-
га эмулируется программно. Благодаря такому решению у нас есть доступ к циклу сообщений, а для реа-
лизации акселераторов большего нам и не надо.
Перед использованием акселераторов они должны быть загружены в память, для чего используется
функция LoadAccelerators, которая возвращает указатель на загруженную таблицу акселераторов. Указа-
тель необходимо сохранить, поскольку он используется в качестве параметра функции TranslateAccelera-
tor, поэтому в Visual Stidio перейдем на закладку "ClassView", в контекстом меню класса основного диало-
га выбираем пункт меню Add member variable... (добавить переменную-член класса).
Здесь выбран тип доступа Protected в соответствии с правилами хорошего тона C++: не надо давать
доступ к членам класса больше, чем это действительно необходимо, поскольку помогает избавиться от
необоснованной модификации членов класса за его пределами.
Теперь в конструкторе диалога добавляем код загрузки таблицы акселераторов:
CMenuDemoDlg :: CMenuDemoDlg ( CWnd* pParent /*=NULL*/ )
: CDialog ( CMenuDemoDlg :: IDD , pParent )
{
m_hIcon = AfxGetApp ( ) -> LoadIcon ( IDR_MAINFRAME) ;
// загрузки таблицы акселераторов
hAccel = LoadAccelerators ( AfxGetResourceHandle ( ) ,
MAKEINTRESOURCE( IDR_ACCELTABLE ) ) ;
}
Здесь был использован весьма полезный макрос MAKEINTRESOURCE ( ). Дело в том, что боль-
шинство функций Win32, работающих с ресурсами, для ссылок на ресурсы используют их текстовые име-