Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

.pdf
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
13.15 Mб
Скачать

Таблицы строк

271

 

 

 

{

MSG msg;

KWnd mainWnd("StringTable", hInstance, nCmdShow, WndProc);

while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg);

}

return msg.wParam;

}

//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

switch (uMsg)

{

case WM_CREATE:

StatusFileMsg(hWnd, IDS_FILEREADONLY, "File_1"); StatusFileMsg(hWnd, IDS_FILETOOBIG, "File_2"); StatusFileMsg(hWnd, IDS_FILENOTFOUND, "File_3"); break;

case WM_DESTROY: PostQuitMessage(0); break;

default:

return DefWindowProc(hWnd, uMsg, wParam, lParam);

}

return 0;

}

//==================================================================== int StatusFileMsg(HWND hwnd, int status, char* fileName)

{

HINSTANCE hInst; char szFormat[80]; char szBuffer[200];

hInst = GetModuleHandle(NULL); LoadString(hInst, status, szFormat, 80); sprintf(szBuffer, szFormat, fileName);

return MessageBox(hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);

}

//////////////////////////////////////////////////////////////////////

Вэтом примере определена функция StatusFileMsg, отображающая информа цию о статусе некоторого файла. Имя файла передается в параметре fileName,

аего текущий статус — в параметре status. Содержание сообщения, соответствую щего текущему статусу, извлекается из ресурса таблицы строк. В оконной проце дуре функция StatusFileMsg вызывается три раза для демонстрации ее работы.

Теперь можно откомпилировать проект и посмотреть, как будет выполняться программа.

Вглаве 8 приводятся другие примеры программ, в которых используется ресурс таблицы строк. Такими примерами являются приложение ToolBar (листинг 8.1) и приложение StatusBar (листинг 8.5).

272

Глава 6. Меню и быстрые клавиши

6Меню и быстрые клавиши

Меню является важнейшим элементом большинства традиционных Windows приложений. Практически в каждом приложении под строкой заголовка главно го окна отображается полоса меню (menu bar), содержащего набор пунктов. На пример, приложение Microsoft Visual Studio 6.0 имеет меню, состоящее из пунктов File, Edit, View, Insert и многих других, как показано на рис. 6.1.

Рис. 6.1. Меню приложения Visual Studio 6.0

Меню большинства Windows приложений выглядят сходным образом. Это об легчает освоение новых программ для пользователей. Поэтому при разработке новых приложений рекомендуется придерживаться сложившегося стиля оформ ления меню.

Организация и виды меню

Меню, располагающееся ниже заголовка окна приложения, называется главным меню (main menu), или меню верхнего уровня. Главное меню относится ко всему приложению.

Иногда в приложениях используются контекстные меню, появляющиеся под курсором при щелчке правой кнопкой мыши. Такие меню ассоциируются с неко торым объектом, например окном или пиктограммой, на который указывает кур сор мыши в момент щелчка. Контекстные меню применяются для доступа к опе рациям, которые поддерживаются объектом.

Любое меню содержит пункты меню. Пункт меню обозначается на полосе меню своим именем — словом или короткой фразой.

Организация и виды меню

273

 

 

 

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

Типы пунктов меню

Различают два типа пунктов меню:

пункт команда;

пункт подменю.

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

Пункт подменю — это заголовок вызываемого меню следующего, более низ кого уровня.

Навигацию по меню пользователь осуществляет при помощи мыши или кла виатуры. Когда курсор мыши указывает на некоторый пункт главного меню, Windows выделяет его, изображая в виде объемной кнопки. Щелчок левой кноп кой мыши осуществляет выбор выделенного пункта меню.

Реакция Windows на выбор пункта меню зависит от типа пункта. Если выбра на команда, то Windows посылает приложению сообщение WM_COMMAND, содер жащее идентификатор этой команды. Если пользователь выбрал подменю, то Windows выводит на экран прямоугольную полосу этого подменю, называемого также всплывающим меню (popup menu). Для главного меню все подменю «всплы вают» ниже выбранного пункта. На рис. 6.2 показано подменю File в окне прило жения Visual Studio.

Рис. 6.2. Подменю File для приложения Visual Studio 6.0

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

274

Глава 6. Меню и быстрые клавиши

 

 

Восприятие подменю с большим количеством пунктов облегчается, если они разделены на некоторые логические группы. Разделители обозначаются горизон тальными линиями серого цвета.

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

Пункты Recent Files и Recent Workspaces помечены символом стрелки. Это озна чает, что они открывают подменю следующего уровня. Если пользователь выде ляет такой пункт, подведя курсор мыши, то Windows сразу выводит на экран со ответствующее подменю, размещая его справа от выделенного пункта. Для этого уровня подменю используется также термин каскадное меню.

Справа от имен некоторых пунктов можно увидеть строки Ctrl+N, Ctrl+O и дру гие подобные клавиатурные сочетания. Это обозначения так называемых быст рых клавиш, работа с которыми рассматривается в конце данной главы.

Системное меню

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

Клавиатурный интерфейс меню

Пользователь может работать с меню без использования мыши, так как Windows предоставляет дублирующий клавиатурный интерфейс.

Чтобы начать работу с главным меню, нужно нажать клавишу Alt или F10, пос ле чего меню активизируется и в нем автоматически выделяется первый пункт.

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

1.С помощью клавиш со стрелками влево/вправо выделить требуемый пункт и нажать клавишу Enter.

2.Нажать «горячую» клавишу, соответствующую мнемоническому символу в имени пункта.

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

При использовании «горячих» клавиш следует помнить, что текущий язык вво да с клавиатуры, установленный пользователем, должен соответствовать языку, на котором отображается имя пункта меню. Иначе выбор пункта не сработает.

Организация и виды меню

275

 

 

 

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

Пункты меню могут быть разрешенными (enabled), запрещенными (disabled) и не доступными (grayed).

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

Запрещенный и недоступный пункты с точки зрения поведения одинаковы. Их можно выделить, но нельзя выбрать. То есть и при щелчке мышью, и при на жатии клавиши Enter ничего не происходит. Различаются запрещенный и недо ступный пункты только своим внешним видом. Запрещенный пункт выглядит так же, как разрешенный, а недоступный пункт отображается серым цветом. Если вы хотите, чтобы пользователь знал, что пункт меню «отменен», делайте его недо ступным.

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

Каков же смысл использования запрещенных пунктов, которые внешне не от личаются от разрешенных пунктов? MSDN указывает, что их можно использо вать в обучающих приложениях, когда некоторое окно выводится на экран толь ко для иллюстрации и не должно реагировать на действия пользователя.

Для изменения статуса пунктов меню применяется функция EnableMenuItem.

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

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

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

На рис. 6.3 показано окно приложения MenuDemo1, в котором вызвано каскад ное меню, содержащее две группы пунктов. Первая группа пунктов управляет выбором RGB составляющих цвета. В ней может быть выбрана любая комбина ция этих флажков. Вторая группа предназначена для выбора интенсивности цве та из трех вариантов: темный, средний, светлый. Эти пункты интерпретируются как переключатели.

276

Глава 6. Меню и быстрые клавиши

 

 

Рис. 6.3. Отметка пунктов-флажков и пунктов-переключателей в подменю Color

Для управления отметкой пунктов флажков применяется функция CheckMenuItem. Для управления отметкой пунктов переключателей — функция CheckMenuRadioItem.

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

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

Атрибут «применяемый по умолчанию» может быть назначен любому пункту подменю при помощи функции SetMenuDefaultItem.

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

Вы можете создать меню одним из трех способов:

на основе шаблона меню, определенного в файле описания ресурсов;

при помощи функций CreateMenu и AppendMenu;

на основе шаблона меню, определяемого в памяти во время выполнения про граммы при помощи функции LoadMenuIndirect.

Чаще всего используется первый способ. Именно он и будет рассматриваться

вэтой главе.

Шаблон меню

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

èìÿ_ìåíþ MENU DISCARDABLE BEGIN

Описание 0-го пункта Описание 1-го пункта

...

Описание (n-1)-го пункта

END

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

277

 

 

 

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

Синтаксис описания i го пункта меню (i = 0,1,..., n – 1) зависит от типа пункта. Описание пункта подменю имеет следующий вид:

POPUP имя_пункта [, параметры]

BEGIN

Описание 0-го пункта Описание 1-го пункта

...

Описание (n-1)-го пункта

END

Легко заметить, что за исключением заголовка (первая строка) синтаксис и семантика описаний меню и подменю совпадают.

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

MENUITEM имя_пункта идентификатор [, параметры]

Если в имени пункта встречается символ &, то следующий за ним символ яв ляется мнемоническим символом.

Если вместо имени пункта использовано слово SEPARATOR, это приведет к тому, что вместо пункта меню будет отображена горизонтальная разделительная линия между группами пунктов.

Более подробно рассматривать определение шаблона меню нет нужды, пото му что оно создается автоматически при использовании редактора меню.

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

В главном меню Visual Studio выполните команду Insert Resource. В появившем ся диалоговом окне Insert Resource укажите тип ресурса Menu и нажмите кнопку New. В результате будет открыто окно редактора меню с заготовкой полосы нового меню (рис. 6.4).

Рис. 6.4. Окно редактора меню с заготовкой полосы меню

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

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

278

Глава 6. Меню и быстрые клавиши

 

 

Атрибуты пункта меню

Если сделать двойной щелчок мышью на прямоугольнике пункта меню, то будет отображено диалоговое окно Menu Item Properties (рис. 6.5), предназначенное для ввода или изменения атрибутов этого пункта.

Рис. 6.5. Диалоговое окно Menu Item Properties

Предназначение наиболее часто используемых атрибутов показано в табл. 6.1.

Таблица 6.1. Атрибуты пункта меню

Атрибут

Описание

 

 

ID

Идентификатор пункта

Caption

Имя пункта (если в имени встречается символ «&», то следующий за ним символ

 

является мнемоническим)

Separator

Пункт представляет собой горизонтальную разделительную линию

Checked

При выводе на экран пункт помечается слева галочкой

Pop-up

Пункт определяет подменю, если флажок отмечен. В противном случае пункт

 

является обычной командой

Grayed

Пункт недоступен в исходном состоянии (несовместим с атрибутом Inactive)

Inactive

Пункт запрещен в исходном состоянии (несовместим с атрибутом Grayed)

Break

Этот атрибут может принимать одно из трех значений: None — обычный пункт

 

меню; Column — для меню верхнего уровня пункт выводится с новой строки,

 

а для подменю — в новом столбце; Bar — дополнительный столбец подменю

 

отделяется вертикальной линией

 

 

Как показано на рис. 6.5, изначально окно атрибутов пункта настроено на оп ределение пункта подменю (флажок Pop-up установлен).

Если вам нужно определить данный пункт как пункт команду, то флажок Pop-up необходимо сбросить. В этом случае текстовое поле ID становится доступным для ввода идентификатора (рис. 6.6).

Рис. 6.6. Диалоговое окно Menu Item Properties со сброшенным флажком Pop-up

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

279

 

 

 

Обычно идентификаторы меню начинаются с префикса IDM_ (ID for a menu). Например, определяя пункт команду для открытия файла, вы вводите в поле Caption текстовую строку &Open…, а в поле ID — текстовую строку IDM_OPEN.

ПРИМЕЧАНИЕ

Иногда мы будем отступать от этого правила и назначать для отдельных пунктов-команд идентификаторы, начинающиеся с префикса ID_. Это удобно, если демонстрируется решение одной и той же задачи с применением разных средств. Например, в рассматриваемой ниже программе MenuDemo1 выбор вида рисуемой фигуры осуществляется при помощи команд меню ID_RECTANGLE, ID_RHOMB, ID_ELLIPSE. В главе 7 решение аналогичной задачи в приложении DlgDemo2 реализуется через вызов диалогового окна с элементами управления типа «переключатель», которые имеют такие же идентификаторы. Применяя для сходных опций одни и те же идентификаторы в разных проектах, мы облегчаем сравнительный анализ этих решений.

Уровни меню

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

Прежде чем излагать процедуру создания меню при помощи редактора меню, опишем рекурсивную процедуру определения произвольного пункта для меню i го уровня.

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

1.Начало.

2.Двойным щелчком мыши на прямоугольнике пункта меню вызовите диалого вое окно Menu Item Properties.

3.Если пункт определяет подменю, то есть меню (i + 1) го уровня, выполните следующую последовательность действий:

установите флажок Pop-up;

введите имя пункта. Если оно содержит мнемонический символ, то перед таким символом нужно вставить знак &;

при необходимости задайте другие опции пункта;

закройте окно Menu Item Properties;

для каждого пункта меню (i + 1) го уровня выполните настоящую процеду ру, подставив на месте параметра i значение i + 1.

4.Если пункт определяет команду, то выполните следующую последовательность действий:

сбросьте флажок Pop-up;

введите имя пункта, предваряя мнемонический символ знаком &;

введите идентификатор пункта;

280

Глава 6. Меню и быстрые клавиши

 

 

при необходимости задайте другие опции пункта;

закройте окно Menu Item Properties.

5.Если пункт определяет горизонтальную разделительную линию, то выполни те следующую последовательность действий:

сбросьте флажок Pop-up;

установите флажок Separator;

закройте окно Menu Item Properties.

6.Конец.

Обратите внимание на то, что на шаге 3 алгоритма процедура вызывает саму

себя. Именно поэтому она является рекурсивной.

При кажущейся простоте алгоритма на самом деле он может описывать до вольно сложный процесс. Вообразите себе виртуальный стек, на вершине которо го запоминается очередной рекурсивный вызов процедуры из шага 3 алгоритма. Когда разработчик, создающий меню, достигает шага 6 алгоритма, это в общем случае вовсе не конец процесса. Если виртуальный стек не пуст, то нужно вер нуться к прерванной процедуре, из которой произошел вызов выполняемой про цедуры. И, конечно, удалить запомненный вызов с вершины стека. И только ког да воображаемый стек окажется пуст, создание рассматриваемого пункта меню i го уровня будет завершено.

Теперь можно описать процедуру создания меню верхнего уровня при помо щи редактора меню.

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

1.Для каждого пункта меню выполните описанную выше процедуру определе ния пункта для меню i го уровня, полагая значение i равным нулю.

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

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

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

Наиболее традиционным способом является присваивание полю lpszMenuName структуры WNDCLASSEX значения указателя на имя меню, что надо сделать еще пе ред регистрацией класса окна. Если имя меню определено как целочисленный идентификатор (например, IDR_MENU1), то применяйте макрос MAKEINTRESOURCE для получения значения, присваиваемого полю lpszMenuName.

1 См. главу 5, раздел «Создание пиктограммы с помощью графического редактора».