Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система Microsoft Windows 3.1 для программиста

© Александр Фролов, Григорий Фролов
Том 13, М.: Диалог-МИФИ, 1993, 284 стр.

[Назад] [Содеожание] [Дальше]

1.2. Создание меню при помощи шаблона

Для создания меню вы можете использовать три метода.

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

Во-вторых, можно создать меню "с нуля" при помощи специальных функций программного интерфейса Windows. Этот способ хорош для приложений, меняющих внешний вид меню, когда вы не можете создать заранее подходящий шаблон. Разумеется, второй метод пригоден и для создания статических меню.

В-третьих, можно подготовить шаблон меню непосредственно в оперативной памяти и создать меню на базе этого шаблона.

Создание шаблона меню

Шаблон меню можно создать в текстовом виде либо при помощи приложения Resource Workshop, либо обычным текстовым редактором, например, входящим в состав Borland Turbo C++ for Windows. В любом случае перед сборкой приложения текстовое описание шаблона меню должно находиться в файле ресурсов с расширением имени .rc, указанном в проекте приложения (или в файле, включаемом в файл проекта оператором #include).

Описание шаблона меню имеет следующий вид:

nameID MENU   [load] [mem]
BEGIN     
  . . .
  . . .
  . . .
END 

Поле nameID используется для идентификации шаблона меню. Оно может указываться либо в виде текстовой строки, либо в виде числа от 1 до 65535.

Параметр load - необязательный. Он используется для определения момента загрузки меню в память. Если этот параметр указан как PRELOAD, меню загружается в память сразу после запуска приложения. По умолчанию используется значение LOADONCALL, в этом случае загрузка шаблона в память происходит только при отображении меню.

Параметр mem также необязательный. Он влияет на тип памяти, выделяемой для хранения шаблона, и может указываться как FIXED (ресурс всегда остается в фиксированной области памяти), MOVEABLE (при необходимости ресурс может перемещаться в памяти, это значение используется по умолчанию) или DISCARDABLE (если ресурс больше не нужен, занимаемая им память может быть использована для других задач). Значение DISCARDABLE может использоваться вместе со значением MOVEABLE.

Между строками BEGIN и END в описании шаблона располагаются операторы описания строк MENUITEM и операторы описания временных меню POPUP.

Оператор MENUITEM имеет следующий формат:

MENUITEM text, id [, param] 

Параметр text определяет имя строки меню. Вы должны указать текстовую строку в двойных кавычках, например, "File". Текстовая строка может содержать символы &, \t, \a.

Если в текстовой строке перед буквой стоит знак &, при выводе меню данная буква будет подчеркнута. Например, строка "&File" будет отображаться как "File". Клавиша, соответствующая подчеркнутой букве, может быть использована в комбинации с клавишей <Alt> для ускоренного выбора строки. Для того чтобы записать в строку сам символ &, его следует повторить дважды. Аналогично, для записи в строку меню символа двойной кавычки " его также следует повторить дважды.

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

Символ \a выравнивает текст по правой границе временного меню или полосы меню.

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

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

Атрибут Описание
CHECKED При выводе меню на экран строка меню отмечается галочкой "

"

GRAYED Строка меню отображается серым цветом и находится в неактивном состоянии. Такую строку нельзя выбрать. Этот атрибут несовместим с атрибутом INACTIVE
HELP Слева от текста располагается разделитель в виде вертикальной линии
INACTIVE Строка меню отображается в нормальном виде (не серым цветом), но находится в неактивном состоянии. Этот атрибут несовместим с атрибутом GRAYED
MENUBREAK Если описывается меню верхнего уровня, элемент меню выводится с новой строки. Если описывается временное меню, элемент меню выводится в новом столбце
MENUBARBREAK Аналогично атрибуту MENUBREAK, но дополнительно новый столбец отделяется вертикальной линией (используется при создании временных меню)

Для описания временных меню используется оператор POPUP :

POPUP text [, param]
BEGIN     
  . . .
  . . .
  . . .
END 

Между строками BEGIN и END в описании временного меню располагаются операторы описания строк MENUITEM и операторы описания вложенных временных меню POPUP.

Параметры text и param указываются так же, как и для оператора MENUITEM .

Для того чтобы создать в меню горизонтальную разделительную линию, используется специальный вид оператора MENUITEM :

MENUITEM SEPARATOR 

Поясним сказанное выше на простом примере.

Скоро мы приведем исходные тексты приложения, имеющего меню (рис. 1.9). Это приложение называется, конечно, MENU.

Рис. 1.9. Главное окно приложения MENU, имеющего меню

Меню этого приложения состоит из строк "File", "Edit" и "Help". При выборе любой строки на экране появляется одно из трех временных меню.

Меню "File" (рис. 1.10) содержит строки, предназначенные для выполнения стандартных для приложений Windows команд, таких, как создание нового документа (или другого объекта) "New", загрузка документа "Open...", и т. д. Обратите внимание, что после строк "Save as..." и "Printer setup..." располагаются горизонтальные разделительные линии.

Рис. 1.10. Меню "File"

На рис. 1.11 показано временное меню "Edit". Оно организовано в виде таблицы из двух столбцов. В левом столбце находятся названия команд ("Undo", "Cut", "Copy", "Paste"), в правом - обозначения комбинаций клавиш, которые предназначены для ускоренного выбора строки меню.

Рис. 1.11. Меню "Edit"

Временное меню "Help" (рис. 1.12) содержит две неактивные строки ("Index" и "Keyboard"), три неактивные строки, отображаемые серым цветом ("Commands", "Procedures", "Using Help"), горизонтальную разделительную линию и обычную строку "About...").

Рис. 1.12. Меню "Help"

Для того чтобы создать описанное выше меню, в приложении Menu Demo в файле ресурсов определен шаблон меню:

#include "menu.hpp"
APP_MENU MENU 
BEGIN
 POPUP "&File"
 BEGIN
   MENUITEM "&New",              CM_FILENEW
   MENUITEM "&Open...",          CM_FILEOPEN
   MENUITEM "&Save",             CM_FILESAVE
   MENUITEM "Save &as...",       CM_FILESAVEAS
   MENUITEM SEPARATOR
   MENUITEM "&Print...",         CM_FILEPRINT
   MENUITEM "Page se&tup...",    CM_FILEPAGE_SETUP
   MENUITEM "P&rinter setup...", CM_FILEPRINTER_SETUP
   MENUITEM SEPARATOR
   MENUITEM "E&xit",             CM_FILEEXIT
 END

 POPUP "&Edit"
 BEGIN
   MENUITEM "&Undo\tCtrl+Z",     CM_EDITUNDO
   MENUITEM "&Cut\tCtrl+X",      CM_EDITCUT
   MENUITEM "&Copy\tCtrl+C",     CM_EDITCOPY
   MENUITEM "&Paste\tCtrl+V",    CM_EDITPASTE
 END

 POPUP "&Help"
 BEGIN
   MENUITEM "&Index\tF1",  CM_HELPINDEX,      INACTIVE
   MENUITEM "&Keyboard",   CM_HELPKEYBOARD,   INACTIVE
   MENUITEM "&Commands",   CM_HELPCOMMANDS,   GRAYED
   MENUITEM "&Procedures", CM_HELPPROCEDURES, GRAYED
   MENUITEM "&Using help", CM_HELPUSING_HELP, GRAYED
   MENUITEM SEPARATOR
   MENUITEM "&About...",   CM_HELPABOUT
 END
END

Шаблон меню начинается с оператора MENU, в котором определено меню с именем APP_MENU. Это меню состоит из трех временных меню, описанных оператором POPUP.

Для определения строк временных меню используется оператор MENUITEM. В качестве второго оператора используются константы, символическое имя которых имеет префикс CM_. Мы определили эти константы в файле menu.hpp, включаемом в файл описания ресурсов оператором #include (можно использовать любые целые неодинаковые значения):

#define CM_HELPABOUT           24346
#define CM_HELPUSING_HELP      24345
#define CM_HELPPROCEDURES      24344
#define CM_HELPCOMMANDS        24343
#define CM_HELPKEYBOARD        24342
#define CM_HELPINDEX           24341

#define CM_EDITPASTE           24324
#define CM_EDITCOPY            24323
#define CM_EDITCUT             24322
#define CM_EDITUNDO            24321

#define CM_FILEEXIT            24338
#define CM_FILEPRINTER_SETUP   24337
#define CM_FILEPAGE_SETUP      24336
#define CM_FILEPRINT           24335
#define CM_FILESAVEAS             24334
#define CM_FILESAVE            24333
#define CM_FILEOPEN            24332
#define CM_FILENEW             24331

Обратите внимание на определение временного меню "Edit". Для того чтобы организовать меню в виде таблицы из двух столбцов, мы использовали символ табуляции \t.

В описании временного меню "Help" используются атрибуты строк INACTIVE и GRAYED. Напомним, что строки с такими атрибутами являются неактивными, их невозможно выбрать. Разница между этими атрибутами заключается в том, что строка с атрибутом INACTIVE выводится нормальным цветом (как активная строка меню), а строка с атрибутом GRAYED выводится серым цветом.

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

Опишем кратко процесс создания шаблона меню при помощи приложения Resource Workshop.

Для того чтобы создать шаблон меню редактором ресурсов Resource Workshop, запустите его и из меню "File" выберите строку "New project...". В появившейся на экране диалоговой панели выберите тип ресурса - файл .RC, вслед за чем нажмите на кнопку "OK". Если файл описания ресурсов проектируемого приложения уже существует, вы можете открыть его, выбрав из меню "File" строку "Open project...".

Далее из меню "Resource" выберите строку "New...". На экране появится диалоговая панель "New resource". В списке "Resource type" выберите строку "MENU" и нажмите кнопку "OK". В главном окне приложения Resource Workshop вы увидите несколько окон, предназначенных для проектирования шаблона меню (рис. 1.13).

Рис. 1.13. Проектирование шаблона меню

Окно "TEST MENU" предназначено для визуальной проверки проектируемого меню. С помощью этого окна в любой момент времени вы можете проверить работу созданного вами меню.

Окно MENU_1 содержит текстовое описание создаваемого меню. Первоначально меню состоит из одного временного меню "Pop-up", в котором определена одна строка "Item". Вы можете выбирать мышью строки описания элементов меню, при этом в левой части окна "MENU" вам будет предоставлена возможность изменить название, идентификатор и атрибуты соответствующего элемента.

Для добавления строки во временное меню в окне "MENU_1" выделите строку, после которой надо добавить новую. Затем из меню "Menu" выберите строку "New menu item". Можно добавить горизонтальную разделительную линию. Для этого из меню "Menu" выберите строку "New separator".

Если вам надо добавить новое временное меню, выделите строку "__EndPopup__" и выберите из меню "Menu" строку "New pop-up".

Для удаления строки или временного меню вам достаточно выделить соответствующую строку в окне "MENU_1" и нажать клавишу <Delete>.

Для того чтобы изменить атрибуты строки меню выделите нужную строку в окне "MENU_1" и в левой части окна "MENU:MENU_1" укажите новые атрибуты.

В поле "Item text" вы можете изменить текст, соответствующей строке меню.

В поле "Item id" можно задать идентификатор строки меню. Это может быть любое целое число. Когда вы создаете меню при помощи Resource Workshop, идентификаторы строк меню присваиваются автоматически. Напомним, что идентификатор строки меню передается функции окна приложения в параметре wParam сообщения WM_COMMAND. Пользуясь этим идентификатором, приложение определяет строку, выбранную вами в меню, после чего выполняет необходимые действия в соответствии с логикой работы приложения.

С помощью группы переключателей "Item type" вы можете изменить тип выделенной вами в окне "MENU_1" строки, превратив обычную строку ("Menu item") в разделительную линию ("Separator").

При помощи переключателя "Break before" можно определить для строк принудительный переход на новую строку или в новый столбец.

Если включен переключатель "No break", элементы меню располагаются как обычно, то есть строка нового временного меню добавляется в полосе меню с левой стороны, а новая строка временного меню располагается в нижней части меню.

Если включен переключатель "Menu bar break", строка названия временного меню располагается не слева, а внизу, образуя "второй этаж" полосы меню. Эта возможность используется редко.

Переключатель "Menu break" предназначен для размещения строки временного меню в другом столбце меню.

Переключатель "Help break" задает выравнивание названия временного меню по правой границе полосы меню. В приложениях, созданных для Windows версии 3.0, такое расположение использовалось для меню "Help". Однако в стандартных приложениях Windows версии 3.1 выравнивание меню "Help" по правой границе не выполняется.

С помощью переключателя "Initial state" вы можете задать начальное состояние элемента меню как активное ("Enabled"), неактивное ("Disabled") или неактивное с отображением серым цветом ("Grayed"). Можно также указать, что строка меню должна быть отмечена галочкой. Для этого следует установить переключатель "Checked".

Меню "Menu" приложения Resource Workshop содержит строки "New file pop-up", "New edit pop-up" и "New help pop-up". Эти строки предназначены для автоматического создания стандартных меню "File", "Edit" и "Help", которые должны быть в любом стандартном приложении Windows. Мы воспользовались этими строками для создания меню в нашем приложении Menu Demo, упомянутом выше.

Выбрав из меню "Menu" строку "Check duplicates", вы можете проверить идентификаторы строк созданного вами меню. Если в меню есть строки с одинаковыми идентификаторами, на экране появится диалоговая панель с предупреждающим сообщением.

После завершения процесса формирования меню вы можете изменить имя меню в описании шаблона. Для этого из меню "Resource" выберите строку "Rename". На экране появится диалоговая панель "Rename resource", с помощью которой вы сможете изменить имя меню (рис. 1.14).

Рис. 1.14. Изменение имени меню

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

Подключение меню к окну приложения

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

Подключение меню при регистрации класса окна

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

Например, пусть в файле описания ресурсов шаблон меню определен под именем APP_MENU:

APP_MENU MENU
BEGIN
....
....
....
END 

В этом случае для подключения меню при регистрации класса вы должны записать адрес текстовой строки "APP_MENU" в поле lpszMenuName структуры wc, имеющей тип WNDCLASS:

wc.lpszMenuName = "APP_MENU";

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

Например, пусть в файле описания ресурсов и в файле исходного текста приложения определена константа:

#define APP_MENU 123

В этом случае ссылка на меню при регистрации класса окна должна выполняться следующим образом:

wc.lpszMenuName = MAKEINTRESOURCE(APP_MENU);

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

Когда для класса окна определено меню, все перекрывающиеся и временные окна, создаваемые на базе этого класса, будут иметь меню, если при создании окна функцией CreateWindow идентификатор меню указан как 0.

Подключение меню при создании окна

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

Девятый параметр функции CreateWindow используется для подключения меню к создаваемому окну:

hwnd = CreateWindow(
    szClassName,         // имя класса окна
    szWindowTitle,       // заголовок окна
    WS_OVERLAPPEDWINDOW, // стиль окна
    CW_USEDEFAULT,       // размеры и расположение окна
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,      
    0,                   // идентификатор родительского окна
    hmenu,               // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
                         // параметры

Значение параметра идентификатора меню может быть получено, например, от функции LoadMenu , определенной в программном интерфейсе Windows:

HMENU WINAPI LoadMenu(HINSTANCE hInstance, 
   LPCSTR lpszMenuName);

Параметр hInstance должен содержать идентификатор текущей копии приложения, полученный через соответствующий параметр функции WinMain.

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

Функция LoadMenu возвращает идентификатор загруженного меню или NULL при ошибке.

Перед завершением своей работы приложение должно уничтожить загруженное меню функцией DestroyMenu :

BOOL WINAPI DestroyMenu(HMENU hmenu);

В качестве единственного параметра функции DestroyMenu необходимо указать идентификатор уничтожаемого меню.

Функция DestroyMenu возвращает в случае успеха значение TRUE, при ошибке - FALSE.

[Назад] [Содеожание] [Дальше]