лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows
.pdfПриложение MenuDemo1 |
291 |
|
|
|
|
x0 = rect.right / 2;
y0 = rect.bottom / 2;
// Координаты прямоугольника и эллипса
if (shapeSize |
== MIN) { |
|
|
x1 = x0 - W/2; |
y1 = y0 - H/2; |
||
x2 = x0 + W/2; |
y2 = y0 + H/2; |
||
} |
|
|
|
else { |
|
|
|
x1 = y1 = 0; |
|
|
|
x2 = rect.right; |
y2 = rect.bottom; |
||
} |
|
|
|
// Координаты |
ромба |
|
|
pt[0].x = (x1 + x2) / 2; |
pt[0].y = y1; |
||
pt[1].x = x2; |
|
|
pt[1].y = (y1 + y2) / 2; |
pt[2].x = (x1 + x2) / 2; |
pt[2].y = y2; |
||
pt[3].x = x1; |
|
|
pt[3].y = (y1 + y2) / 2; |
switch (shapeData.id_shape) { case ID_RECTANGLE:
Rectangle(hDC, x1, y1, x2, y2); break;
case ID_RHOMB: Polygon(hDC, pt, 4); break;
case ID_ELLIPSE:
Ellipse(hDC, x1, y1, x2, y2); break;
}
DeleteObject(SelectObject(hDC, hOldBrush));
}
EndPaint(hWnd, &ps); break;
case WM_DESTROY: PostQuitMessage(0); break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
Обратите внимание на некоторые детали реализации в программном коде. Так, меню, определенное в файле ресурсов MenuDemo1.rc с идентификатором IDR_MENU1, подключается к окну приложения при объявлении объекта mainWnd класса KWnd:
KWnd mainWnd("MenuDemo1", hInstance, nCmdShow, WndProc,MAKEINTRESOURCE(IDR_MENU1),, 100, 100, 400, 300);
Текущие параметры рисуемой фигуры хранятся в переменной shapeData струк турного типа ShapeData.
В блоке обработки сообщения WM_CREATE сначала определяется значение дес криптора hMenu главного меню, а затем вызывается функция SetMenuDefaultItem
292 |
Глава 6. Меню и быстрые клавиши |
|
|
для установки атрибута «применяемый по умолчанию» пункту Open подменю File. Дескриптор подменю File, передаваемый первому параметру данной функ ции, получен вызовом функции GetSubMenu(hMenu, 0).
Далее трижды вызывается функция CheckMenuRadioItem для установки исход ных отметок в группах пунктов, интерпретируемых как переключатели:
Группа |
Первый пункт в группе |
Последний пункт в группе |
|
|
|
Подменю View |
IDM_SHOW_SHAPE |
IDM_HIDE_SHAPE |
Подменю Shape |
ID_RECTANGLE |
IM_ELLIPSE |
Подменю Color |
ID_DARK |
ID_LIGHT |
|
|
|
Отметки ставятся на пунктах, заданных четвертым параметром функции CheckMenuRadioItem. Следует отметить, что эти пункты соответствуют началь ным значениям переменных bShow, shapeData.id_shape и shapeData.id_bright. В дальнейшем при обработке соответствующих сообщений отметки переходят на другие пункты внутри каждой группы.
Пункты другой группы подменю, Color, интерпретируемые как флажки, полу чают свои отметки при помощи функции CheckMenuItem, когда обрабатывается сообщение WM_COMMAND с параметром wParam, младшее слово которого равно
IDM_RED, IDM_GREEN или IDM_BLUE.
Пункт главного меню Increase! c идентификатором IDM_RESIZE используется как флажок, переводящий переменную shapeSize из значения MIN в значение MAX и обратно.
Но пункты главного меню не могут получать отметку взведенного флажка. Поэтому, обрабатывая сообщение WM_COMMAND с параметром wParam, равным IDM_RESIZE, программа изменяет имя пункта от Increase к Decrease и обратно. Эта смена имени обеспечивается вызовом функции ModifyMenu. Символьная строка, назначаемая пункту, извлекается из массива itemResizeName. После возврата из ModifyMenu вызывается функция DrawMenuBar, чтобы немедленно отобразить из менения в полосе главного меню.
Когда изображение скрыто после выполнения команды Hide shape из подменю View, действия по изменению размеров фигуры теряют смысл. Интерфейс про граммы только выиграет, если в этой ситуации пункт меню IDM_RESIZE сделать недоступным. При обработке сообщения WM_COMMAND с параметром wParam, рав ным IDM_HIDE_SHAPE, вызывается функция EnableMenuItem, которой передается флаг MFS_GRAYED. В результате этого указанный пункт меню становится недоступ ным. При обработке сообщения WM_COMMAND с параметром wParam, равным
IDM_SHOW_SHAPE, вызывается функция EnableMenuItem с флагом MFS_ENABLED, и пункт меню IDM_RESIZE снова становится доступным для пользователя.
При обработке сообщения WM_COMMANDс параметром wParam, равным IDM_ABOUT, вызывается функция MessageBox, которая выводит окно сообщений с информаци ей о программе и ее разработчиках.
В финальной части обработки сообщения WM_COMMAND вызывается функция InvalidateRect, чтобы перерисовать клиентскую область окна с учетом изменивше гося состояния приложения.
Рекомендуем вам откомпилировать эту программу и посмотреть, как она ра ботает.
Работа с контекстным меню |
293 |
|
|
|
|
Работа с контекстным меню
Контекстное меню, называемое иногда меню быстрого вызова (shortcut menu), по является в любой части окна приложения при щелчке правой кнопкой мыши. Оно выглядит как всплывающее меню, но без привязки к меню верхнего уровня. Обыч но содержание контекстного меню изменяется в зависимости от «контекста» — места, где произведен щелчок правой кнопкой мыши. В сложных приложениях контекстные меню часто содержат пункты, дублирующие команды основного меню, но сгруппированные иначе, чтобы максимально облегчить пользователю работу с приложением. После выбора пункта контекстного меню оно исчезает с экрана.
Конечно же, для программиста создание и обработка контекстного меню име ют свою специфику.
Определение шаблона контекстного меню
Создавая шаблон контекстного меню с помощью редактора меню, определите ну левой пункт меню нулевого уровня как подменю, имеющее какое нибудь услов ное имя. Этот пункт нигде не будет отображаться. Он необходим только для по лучения дескриптора подменю с помощью функции GetSubMenu.
Затем определите подменю (меню 1 го уровня) по процедуре, описанной выше. Сохраните созданный шаблон в файле описания ресурсов, назначив ему под
ходящий идентификатор, например IDR_MENU_MYCONTEXT.
Загрузка меню
Загрузка контекстного меню осуществляется в блоке обработки сообщения
WM_CREATE при помощи функций LoadMenu и GetSubMenu:
HMENU hMenuMyContext;
hMenuMyContext = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_MYCONTEXT)); hMenuMyContext = GetSubMenu(hMenuMyContext, 0);
Функция LoadMenu возвращает дескриптор меню, определенного в файле ре сурсов с идентификатором IDR_MENU_MYCONTEXT. Этот дескриптор относится к фиктивному меню нулевого уровня, которое не должно отображаться на экране. Содержанием контекстного меню является нулевой пункт указанного меню, по этому окончательное значение дескриптора hMenuMyContext определяется вызо вом функции GetSubMenu.
Полученный дескриптор hMenuMyContextпотом передается функции TrackPopupMenuEx, которая выводит всплывающее контекстное меню на экран.
Вызов меню
Когда пользователь делает щелчок правой кнопкой мыши, Windows отправляет окну приложения сообщение WM_RBUTTONDOWN, содержащее клиентские коорди наты1 курсора мыши в момент щелчка. Кроме того, Windows отправляет сообще ние WM_CONTEXTMENU, содержащее экранные координаты (screen coordinates) курсора
1 Координаты указываются относительно левого верхнего угла клиентской области окна.
294 |
Глава 6. Меню и быстрые клавиши |
|
|
мыши. Вы можете организовать вызов контекстного меню, обрабатывая любое из этих сообщений, при помощи функции TrackPopupMenuEx:
BOOL TrackPopupMenuEx |
( |
HMENU hmenu, |
// дескриптор контекстного меню |
UINT fuFlags, |
// флаги |
int x, |
// горизонтальная позиция |
int y, |
// вертикальная позиция |
HWND hwnd, |
// дескриптор окна |
LPTPMPARAMS lptpm // область экрана, которую меню не должно перекрывать
);
Второй параметр функции может содержать флаги, управляющие размещени ем полосы меню относительно позиции курсора мыши (x, y), и флаги, задающие некоторые другие характеристики. Обычно можно воспользоваться флагами по умолчанию, передавая этому параметру нулевое значение. По умолчанию левый верхний угол всплывающего меню привязывается к точке (x, y).
Параметрам x и y необходимо передать экранные координаты курсора мыши в момент щелчка правой кнопкой. Координаты курсора мыши можно извлечь из параметра lParam сообщения WM_RBUTTONDOWN или сообщения WM_CONTEXTMENU. Нужно только учесть, что сообщение WM_RBUTTONDOWN содержит клиентские ко ординаты, поэтому при работе с этим сообщением необходимо преобразовать кли ентские координаты в экранные координаты при помощи функции ClientToScreen.
Параметр hwnd содержит дескриптор окна, владеющего контекстным меню. Все сообщения от меню будут направляться этому окну. При помощи параметра lptpm можно определить область экрана, которую меню не должно перекрывать. Чаще всего этому параметру передается значение NULL.
Функция не возвращает управление до тех пор, пока работа пользователя с меню не будет завершена выбором пункта или отказом от выбора.
Обработка сообщений, направляемых окну владельцу от контекстного меню, не отличается от обработки сообщений, источником которых является основное меню.
Приемы работы с контекстным меню продемонстрируем на примере разработ ки конкретного приложения.
Приложение MenuDemo2
Приложение MenuDemo2 решает те же задачи, что и приложение MenuDemo1, отли чаясь от него только организацией меню. Главное меню приложения MenuDemo2 содержит те же пункты, что и приложение MenuDemo1, за вычетом пункта Draw shape. Подменю второго уровня Shape и Color для отсутствующего пункта Draw shapeдолж ны быть реализованы в виде контекстных меню.
Первое контекстное меню, всплывающее при щелчке мышью в левой полови не окна, позволяет выбрать вид фигуры. Второе контекстное меню, всплывающее при щелчке мышью в правой половине окна, позволяет выбрать цвет заливки фигуры.
Создайте новый проект с именем MenuDemo2. Скопируйте из папки проекта MenuDemo1 в папку проекта MenuDemo2 файлы с расширениями .cpp, .h и .rc, скор ректировав их имена заменой MenuDemo1 на MenuDemo2. Добавьте эти файлы в состав проекта.
Работа с контекстным меню |
295 |
|
|
|
|
Откройте в окне редактирования файл recource.h и найдите строку коммен тария
// Used by MenuDemo1.rc
Замените ее следующей строкой:
//Used by MenuDemo2.rc
Вокне Workspace перейдите на вкладку ResourceView, откройте в иерархическом списке папку Menu и двойным щелчком мыши на элементе IDR_MENU1 вызовите редактор меню.
Из меню нужно удалить пункт Draw shape, выделив его мышью и нажав клави шу Delete. Среда разработки Visual Studio не позволит сделать это сразу, выведя предупреждение в виде диалогового окна (рис. 6.7).
Рис. 6.7. Предупреждение об уничтожении всех пунктов подменю Draw shape
Нажмите клавишу OK для подтверждения удаления пункта меню.
Теперь нужно определить два новых шаблона меню, которые будут использо ваться для контекстных меню. Эти шаблоны должны получить идентификаторы
IDR_MENU_SHAPE и IDR_MENU_COLOR соответственно.
Меню IDR_MENU_SHAPE должно иметь фиктивный пункт нулевого уровня с ус ловным именем shape, а подменю shape должно содержать пункты, указанные
втабл. 6.9. Меню IDR_MENU_COLOR должно иметь фиктивный пункт нулевого уров ня с условным именем color. Подменю color должно содержать пункты, указанные
втабл. 6.10.
Код модуля MenuDemo2.cpp приведен в листинге 6.2.
Листинг 6.2. Проект MenuDemo2
//////////////////////////////////////////////////////////////////////
// MenuDemo2.cpp #include <windows.h> #include <stdio.h> #include "KWnd.h" #include "resource.h"
#define W |
200 |
// ширина фигуры |
#define H |
140 |
// высота фигуры |
enum ShapeSize { MAX, MIN }; |
||
typedef struct { |
|
|
int id_shape; |
// идентификатор фигуры |
|
BOOL fRed; |
// компонент красного цвета |
|
BOOL fGreen; |
// компонент зеленого цвета |
|
BOOL fBlue; |
// компонент синего цвета |
|
int id_bright; |
// идентификатор яркости цвета |
|
} ShapeData; |
|
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
продолжение
296 |
Глава 6. Меню и быстрые клавиши |
|
|
Листинг 6.2 (продолжение)
//==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("MenuDemo2", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg);
}
return msg.wParam;
}
//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC; |
|
|
|
|
|
|
PAINTSTRUCT ps; |
|
|
|
|||
RECT rect; |
|
|
|
|
||
static HMENU hMenu; |
|
// дескриптор главного меню |
||||
static HMENU hMenuShape; |
// дескриптор 1-го контекстного меню |
|||||
static HMENU hMenuColor; |
// дескриптор 2-го контекстного меню |
|||||
POINT point, ptInClient; |
|
|||||
int |
x0, |
y0, |
x1, |
y1, |
x2, |
y2; |
POINT pt[4];
static ShapeSize shapeSize = MIN; static BOOL bShow = TRUE;
static HBRUSH hBrush, hOldBrush;
char* itemResizeName[2] = { "Decrease!", "Increase!"};
int intensity[3] = { 85, 170, 255 }; // интенсивность RGB-компонентов цвета int brightness;
static ShapeData shapeData;
switch (uMsg)
{
case WM_CREATE:
hMenu = GetMenu(hWnd);
hMenuShape = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU_SHAPE));
hMenuShape = GetSubMenu(hMenuShape, 0);
hMenuColor = LoadMenu(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDR_MENU_COLOR));
hMenuColor = GetSubMenu(hMenuColor, 0);
//IDM_OPEN - пункт меню, применяемый по умолчанию SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE);
//Исходные отметки пунктов меню CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,
IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND); CheckMenuRadioItem(hMenuShape, ID_RECTANGLE,
ID_ELLIPSE, ID_RECTANGLE, MF_BYCOMMAND); CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, ID_DARK, MF_BYCOMMAND);
shapeData.id_shape = ID_RECTANGLE;
Работа с контекстным меню |
297 |
|
|
|
|
|
shapeData.id_bright = ID_DARK; |
|
|
break; |
|
|
case WM_CONTEXTMENU: |
|
|
point.x = LOWORD(lParam); |
|
|
point.y = HIWORD(lParam); |
|
|
ptInClient = point; |
|
|
ScreenToClient(hWnd, &ptInClient); |
|
|
GetClientRect(hWnd, &rect); |
|
|
if (ptInClient.x < rect.right / 2) |
|
|
TrackPopupMenuEx(hMenuShape, 0, point.x, point.y, hWnd, NULL); |
|
|
else |
|
|
TrackPopupMenuEx(hMenuColor, 0, point.x, point.y, hWnd, NULL); |
|
|
break; |
|
|
case WM_COMMAND: |
|
|
switch (LOWORD(wParam)) |
|
{ |
|
|
|
/* код обработки для значений параметра: IDM_OPEN, IDM_CLOSE, |
|
|
IDM_SAVE, IDM_EXIT, IDM_SHOW_SHAPE, IDM_HIDE_SHAPE - из листинга 6.1 |
|
*/ |
|
|
|
case ID_RECTANGLE: |
|
|
shapeData.id_shape = ID_RECTANGLE; |
|
|
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE, |
|
|
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND); |
|
|
break; |
|
|
case ID_RHOMB: |
|
|
shapeData.id_shape = ID_RHOMB; |
|
|
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE, |
|
|
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND); |
|
|
break; |
|
|
case ID_ELLIPSE: |
|
|
shapeData.id_shape = ID_ELLIPSE; |
|
|
CheckMenuRadioItem(hMenuShape, ID_RECTANGLE, |
|
|
ID_ELLIPSE, LOWORD(wParam), MF_BYCOMMAND); |
|
|
break; |
|
|
case ID_RED: |
|
|
shapeData.fRed = ~shapeData.fRed; |
|
|
CheckMenuItem(hMenuColor, ID_RED, |
|
|
MF_BYCOMMAND | shapeData.fRed? MF_CHECKED : MF_UNCHECKED); |
|
|
break; |
|
|
case ID_GREEN: |
|
|
shapeData.fGreen = ~shapeData.fGreen; |
|
|
CheckMenuItem(hMenuColor, ID_GREEN, |
|
|
MF_BYCOMMAND | shapeData.fGreen? MF_CHECKED : MF_UNCHECKED); |
|
|
break; |
|
|
case ID_BLUE: |
|
|
shapeData.fBlue = ~shapeData.fBlue; |
|
|
CheckMenuItem(hMenuColor, ID_BLUE, |
|
|
MF_BYCOMMAND | shapeData.fBlue? MF_CHECKED : MF_UNCHECKED); |
|
|
break; |
|
|
case ID_DARK: |
|
|
shapeData.id_bright = ID_DARK; |
продолжение |
|
|
|
298 Глава 6. Меню и быстрые клавиши
Листинг 6.2 (продолжение)
CheckMenuRadioItem(hMenuColor, ID_DARK, ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND);
break;
case ID_MEDIUM:
shapeData.id_bright = ID_MEDIUM; CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND); break;
case ID_LIGHT:
shapeData.id_bright = ID_LIGHT; CheckMenuRadioItem(hMenuColor, ID_DARK,
ID_LIGHT, LOWORD(wParam), MF_BYCOMMAND); break;
/* код обработки для case IDM_RESIZE - из листинга 6.1 */
case IDM_ABOUT: MessageBox(hWnd,
"MenuDemo2\nVersion 1.0\nCopyright: Finesoft Corporation, 2005.", "About MenuDemo2", MB_OK);
break;
default:
break;
}
InvalidateRect(hWnd, NULL, TRUE); break;
case WM_PAINT:
/* код обработки сообщения WM_PAINT - из листинга 6.1 */ break;
case WM_DESTROY: PostQuitMessage(0); break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
Рис. 6.8. Окно приложения MenuDemo2 с контекстным меню в правой части окна
Быстрые клавиши |
299 |
|
|
|
|
При обработке сообщения WM_CONTEXTMENU необходимо выяснить, в какой ча сти окна произведен щелчок правой кнопкой мыши. Для этого экранные коорди наты курсора мыши, сохраненные в переменной point, преобразуются к клиентс ким координатам, представленным переменной ptInClient. Размеры клиентской области окна определяются в переменной rect после вызова функции GetClientRect.
Если щелчок произошел в левой части окна, то функции TrackPopupMenuEx пе редается дескриптор меню hMenuShape. Если щелчок был выполнен в правой час ти окна, то функции TrackPopupMenuEx передается дескриптор меню hMenuColor.
На рис. 6.8 показан вид окна приложения с контекстным меню hMenuColor.
Быстрые клавиши
Быстрая клавиша (keyboard accelerator) — это клавиша или комбинация клавиш, которые при нажатии генерируют сообщение WM_COMMAND или WM_SYSCOMMAND.
Обычно быстрые клавиши дублируют пункты меню, предоставляя пользова телю альтернативный способ вызова команд. На рис. 6.2 мы уже видели обозначе ния быстрых клавиш на полосе подменю File в окне приложения Visual Studio. Например, команду Newпользователь может вызвать, либо выбрав пункт File New, либо нажав сочетание клавиш Ctrl+N. Очевидно, что второй способ быстрее.
Хотя традиционно быстрые клавиши являются эквивалентом пунктов команд меню, они могут генерировать и такие команды, которых нет в меню.
Для многооконных приложений с множеством оконных процедур быстрые кла виши очень важны. Как известно, Windows посылает сообщения клавиатуры окон ной процедуре того окна, которое в данный момент имеет фокус ввода. Однако при работе с быстрыми клавишами Windows посылает сообщение WM_COMMANDтой окон ной процедуре, чей дескриптор был передан функции TranslateAccelerator. Как пра вило, это будет оконная процедура главного окна приложения, то есть именно того окна, в котором расположено меню. Следовательно, нет необходимости дублиро вать логику обработки быстрых клавиш в каждой оконной процедуре.
Чтобы добавить в приложение обработку быстрых клавиш, нужно выполнить последовательность действий:
1.Модифицировать определение ресурса меню, добавив к имени каждого дуб лируемого пункта информацию о быстрой клавише.
2.Определить таблицу быстрых клавиш в файле описания ресурсов.
3.Обеспечить загрузку таблицы быстрых клавиш в память приложения.
4.Модифицировать цикл обработки сообщений в функции WinMain.
Модификация определения ресурса меню
Говоря о модификации, мы подразумеваем, что ресурс меню уже был определен ранее, без учета использования быстрых клавиш. В принципе, ничто не мешает вам заранее продумать вопрос дублирования меню быстрыми клавишами и сде лать те добавления, о которых говорится здесь, на этапе создания меню.
Для модификации определения пункта вызовите диалоговое окно Menu Item Properties (см. рис. 6.5) и в конце имени пункта, которое указано в поле Caption, добавьте текстовую строку \t<обозначение быстрой клавиши>.
300 |
Глава 6. Меню и быстрые клавиши |
|
|
Например, если добавляется быстрая клавиша Ctrl+O для дублирования пункта &Open... из подменю File, то следует добавить к прежнему имени текстовую строку \tCtrl+O. После модификации поле Caption будет содержать строку &Open...\tCtrl+O.
Таблица быстрых клавиш
Эта таблица обычно создается при помощи редактора таблиц быстрых клавиш. Для его запуска нужно выполнить команду меню Insert Resource в главном меню приложения Visual Studio. В появившемся диалоговом окне Insert Resource следу ет указать тип ресурса Accelerator, после чего нажать кнопку New. В результате бу дет открыто окно редактора таблицы быстрых клавиш (рис. 6.9).
Рис. 6.9. Окно редактора таблицы быстрых клавиш
По умолчанию редактор присваивает таблице быстрых клавиш имя IDR_AC CELERATOR1. В файле resource.h этот идентификатор определяется как целочисленная константа. В большинстве случаев можно согласиться с этим именем по умолча нию. После двойного щелчка на пустой строке таблицы откроется диалоговое окно
Accel Properties (рис. 6.10).
Рис. 6.10. Диалоговое окно Accel Properties
В поле ID введите идентификатор быстрой клавиши. Если быстрая клавиша дублирует пункт меню, то этот идентификатор должен совпадать с идентифика тором пункта меню. Например, если определяется быстрая клавиша для пункта &Open... подменю File для приложения MenuDemo1, следует ввести идентификатор
IDM_OPEN.
Вгруппе переключателей Type оставьте включенным переключатель VirtKey, так как в поле Key будет указываться виртуальная клавиша. Коды виртуальных кла виш можно посмотреть в табл. 4.3 (глава 4).
Введите в поле Key идентификатор нужной клавиши. Для цифр и латинских букв в качестве идентификатора вводится сам символ.
Вгруппе Modifiers установите те флажки, которые соответствуют дополнитель ным клавишам, входящим в определяемую комбинацию клавиш.
Например, если определяется быстрая клавиша Ctrl+O для пункта &Open..., то следует оставить включенным флажок Ctrl, а в поле Key ввести символ O (строчная буква «O» английского алфавита).
