- •Глава 10 Меню и быстрые клавиши
- •Структура меню
- •Шаблон меню
- •Ссылки на меню в вашей программе
- •Меню и сообщения
- •Образец программы
- •Этикет при организации меню
- •Сложный способ определения меню
- •Независимые всплывающие меню
- •Третий подход к определению меню
- •Использование системного меню
- •Изменение меню
- •Другие команды меню
- •Нестандартный подход к меню
- •Использование в меню битовых образов
- •Два способа создания битовых образов для меню
- •Контекст памяти
- •Создание битового образа, содержащего текст
- •Масштабирование битовых образов
- •Соберем все вместе
- •Добавление интерфейса клавиатуры
- •Быстрые клавиши
- •Зачем нужны быстрые клавиши?
- •Некоторые правила назначения быстрых клавиш
- •Загрузка таблицы быстрых клавиш
- •Преобразование нажатий клавиш клавиатуры
- •Получение сообщений быстрых клавиш
- •Программа poppad, имеющая меню и быстрые клавиши
- •Разрешение пунктов меню
- •Обработка опций меню
Ссылки на меню в вашей программе
Во многих приложениях Windows в описании ресурсов имеется только одно меню. Ссылка в программе на это меню имеет место в определении класса окна:
wndclass.lpszMenuName = "MyMenu" ;
Часто программисты используют строку имени программы в качестве имени меню, имени класса окна, имени значка программы. Однако, вместо имени для меню можно использовать число (или идентификатор). Тогда описание ресурса выглядело бы так:
45 MENU
{
[определение меню]
}
В этом случае, оператор присваивания для поля lpszMenuName структуры класса окна может быть либо такой:
wndclass.lpszMenuName = MAKEINTRESOURCE (45) ;
либо такой:
wndclass.lpszMenuName = "#45" ;
Хотя задание имени меню в классе окна является наиболее обычным способом ссылки на ресурс меню, существуют альтернативные варианты. В приложении для Windows ресурс меню можно загрузить в память с помощью функции LoadMenu, которая аналогична функциям LoadIcon и LoadCursor, описанным в главе 9. Если в описании ресурса меню используете имя, то возвращаемым значением функции LoadMenu является описатель меню:
hMenu = LoadMenu (hInstance, "MyMenu") ;
При использовании числа функция LoadMenu принимает либо такой вид:
hMenu = LoadMenu (hInstance, MAKEINTRESOURCE (45)) ;
либо такой:
hMenu = LoadMenu (hInstance, "#45") ;
Затем этот описатель меню можно указать в качестве девятого параметра функции CreateWindow:
hwnd = CreateWindow ("MyClass", "Window Caption",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
hMenu,
hInstance,
NULL) ;
В этом случае меню, указанное при вызове функции CreateWindow, перекрывает любое меню, заданное в классе окна. Меню, задаваемое в классе окна, можно считать заданным по умолчанию меню для окон, созданных на основе данного класса окна, если девятый параметр функции CreateWindow установлен в NULL. Поэтому можно использовать разные меню для различных окон, созданных на основе одного и того же класса окна.
Можно также указать NULL для меню при регистрации класса окна и NULL для меню при вызове функции CreateWindow, а затем присоединить меню к окну следующим образом:
SetMenu (hwnd, hMenu) ;
Такая форма позволяет динамически изменять меню окна. В программе NOPOPUPS, которая приведена далее в этой главе, показан пример, иллюстрирующий этот прием.
Любое меню, связанное с окном, удаляется при удалении окна. Любое несвязанное с окном меню перед завершением работы программы должно быть явно удалено при помощи вызова функции DestroyMenu.
Меню и сообщения
Когда пользователь выбирает пункт меню, Windows посылает оконной процедуре несколько различных сообщений. Большинство из этих сообщений могут игнорироваться программой, и просто передаваться DefWindowProc. Одним из таких сообщений является сообщение WM_INITMENU, которое имеет следующие параметры:
wParam |
lParam |
Описатель главного меню |
0 |
Значением параметра wParam является описатель главного меню, даже если пользователь выбирает пункт системного меню. В программах для Windows сообщение WM_INITMENU обычно игнорируется. Хотя это сообщение существует для того, чтобы дать вам возможность изменить меню перед тем, как будет выбран пункт меню, возможно, что любые изменения главного меню в этот момент могут привести пользователя в замешательство.
Кроме того, программа получает сообщения WM_MENUSELECT. Если пользователь перемещает курсор мыши по пунктам меню, программа может получить множество сообщений WM_MENUSELECT. Как будет рассказано в главе 12, это полезно при использовании строки состояния, содержащей полное описание опции меню. Данное сообщение имеет следующие параметры:
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
lParam |
Выбранный пункт: идентификатор меню или описатель всплывающего меню |
Флаги выбора |
Описатель меню, содержащего выбранный пункт |
Сообщение WM_MENUSELECT — это сообщение для отслеживания перемещения по меню. Младшее слово параметра wParam говорит о том, какой пункт меню выбран (подсвечен) в данный момент. В старшем слове параметра wParam могут быть комбинации из следующих флагов выбора: MF_GRAYED, MF_DISABLED, MF_CHECKED, MF_BITMAP, MF_POPUP, MF_HELP, MF_SYSMENU и MF_MOUSESELECT. Сообщение WM_MENUSELECT может понадобиться для того, чтобы изменить что-нибудь в рабочей области окна на основе информации о перемещении подсветки по пунктам меню. В большинстве программ это сообщение передается в DefWindowProc.
Когда Windows готова вывести на экран всплывающее меню, она посылает оконной процедуре сообщение WM_INITMENUPOPUP со следующими параметрами:
wParam |
Младшее слово (LOWORD) lParam |
Старшее слово (HIWORD) lParam |
Описатель всплывающего меню |
Индекс всплывающего меню |
Для системного меню 1, в противном случае 0 |
Это сообщение важно, если необходимо разрешать или запрещать пункты меню перед их выводом на экран. Например, предположим, что программа с помощью команды Paste всплывающего меню может копировать текст из буфера обмена. При получении для этого всплывающего меню сообщения WM_INITMENUPOPUP необходимо определить, имеется ли текст в буфере обмена. Если нет, то необходимо сделать этот пункт меню Paste недоступным. Мы рассмотрим такой пример в программе POPPAD, представленной далее в этой главе.
Самым важным сообщением меню является WM_COMMAND. Это сообщение показывает, что пользователь выбрал разрешенный пункт меню окна. Из главы 8 вы помните, что сообщения WM_COMMAND также посылаются дочерними окнами управления. Если оказывается, что для меню и дочерних окон управления используются одни и те же идентификаторы, то различить их можно с помощью значения параметра lParam, который для пункта меню будет равен 0:
|
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
lParam |
Меню: |
Идентификатор меню |
0 |
0 |
Элемент управления: |
Идентификатор элемента управления |
Код уведомления |
Описатель дочернего окна |
Сообщение WM_SYSCOMMAND похоже на сообщение WM_COMMAND за исключением того, что сообщение WM_SYSCOMMAND сигнализирует, что пользователь выбрал разрешенный пункт системного меню:
|
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
lParam |
Системное меню: |
Идентификатор меню |
0 |
0 (Если сообщение WM_SYSCOMMAND является результатом щелчка мыши, тогда старшее и младшее слово lParam являются, соответственно, экранными координатами X и Y курсора мыши.) |
Идентификатор меню показывает, какой пункт системного меню выбран. Для предопределенных пунктов системного меню, четыре младших разряда должны быть замаскированы. Результирующая величина будет одной из следующих: SC_SIZE, SC_MOVE, SC_MINIMIZE, SC_MAXIMIZE, SC_NEXTWINDOW, SC_PREVWINDOW, SC_CLOSE, SC_VSCROLL, SC_HSCROLL, SC_ARRANGE, SC_RESTORE и SC_TASKLIST. Кроме того, младшее слово параметра wParam может быть SC_MOUSEMENU или SC_KEYMENU.
Если вы добавите к системному меню новые пункты, то младшее слово параметра wParam станет идентификатором, который вы определите. Для избежания конфликта с предопределенными идентификаторами меню, используйте значения меньше чем 0xF000. Важно, чтобы обычные сообщения WM_SYSCOMMAND передавались в DefWindowProc. Если этого не сделать, то обычные команды системного меню будут отключены.
Последним сообщением, которое мы обсудим, является сообщение WM_MENUCHAR, которое, в действительности, не является собственно сообщением меню. Windows посылает это сообщение оконной процедуре в одном из двух случаев: если пользователь нажимает комбинацию клавиши <Alt> и символьной клавиши, несоответствующей пунктам меню, или при выводе на экран всплывающего меню, если пользователь нажимает символьную клавишу, не соответствующую пункту всплывающего меню. Параметры сообщения WM_MENUCHAR являются следующими:
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
lParam |
Код ASCII |
Код выбора |
Описатель меню |
Код выбора равен:
0 — всплывающее меню не отображается.
MF_POPUP — отображается всплывающее меню.
MF_SYSMENU — отображается системное меню.
Как правило, в программах для Windows это сообщение передается DefWindowProc, которая обычно возвращает 0 в Windows, после чего Windows издает звуковой сигнал (гудок). Мы рассмотрим использование сообщения WM_MENUCHAR в программе GRAFMENU, которая представлена далее в этой главе.
