Ссылки на меню в вашей программе
Во многих приложениях Windows в описании ресурсов имеется только одно меню. Ссылка в программе на это меню имеет место в определении класса окна:
wndclass.lpszMenuName = "MyMenu" ;
Часто программисты используют строку имени программы в качестве имени меню, имени класса окна, имени значка программы. Однако, вместо имени для меню можно использовать число (или идентификатор). Тогда описание ресурса выглядело бы так:
45 Menu { [определение меню] }
В этом случае, оператор присваивания для поля IpszMenuName структуры класса окна может быть либо такой:
wndclass.lpszMenuName = MAKEINTRESOURCE (45) ;
либо такой:
wndclass.lpszMenuName = "#45" ;
Хотя задание имени меню в классе окна является наиболее обычным способом ссылки на ресурс меню, существуют альтернативные варианты. В приложении для Windows ресурс меню можно загрузить в память с помощью функции LoadMenu, которая аналогична функциям Loadlcon и LoadCursor, описанным в главе 9. Если в описании ресурса меню используете имя, то возвращаемым значением функции LoadMenu является описатель меню:
hMenu = LoadMenu (hinstance, "MyMenu") ;
При использовании числа функция LoadMenu принимает либо такой вид:
hMenu = LoadMenu (hinstance, MAKEINTRESOURCE (45));
Либо такой:
hMenu = LoadMenu (hinstance, "#45") ;
Затем этот описатель меню можно указать в качестве девятого параметра функции Create Window.
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) ;
Любое меню, связанное с окном, удаляется при удалении окна. Любое несвязанное с окном меню перед завершением работы программы должно быть явно удалено при помощи вызова функции DestroyMenu.
Меню и сообщения
Когда пользователь выбирает пункт меню, Windows посылает оконной процедуре несколько различных сообщений. Большинство из этих сообщений могут игнорироваться программой, и просто передаваться DefWindowProc. Одним из таких сообщений является сообщение WM_INITMENU, которое имеет следующие параметры:
wParam – описатель главного меню, lParam – 0.
Значением параметра wParam является описатель главного меню, даже если пользователь выбирает пункт системного меню. В программах для Windows сообщение WM_INITMENU обычно игнорируется. Это сообщение существует для того, чтобы дать вам возможность изменить меню или выполнить другое действие перед тем, как будет выбран пункт меню.
Кроме того, программа получает сообщения WM_MENUSELECT. Если пользователь перемещает курсор мыши по пунктам меню, программа может получить множество сообщений WM_MENUSELECT. Это полезно при использовании строки состояния, содержащей полное описание опции меню. Данное сообщение имеет следующие параметры:
Младшее слово (LOWORD) wParam |
|
Старшее слово (HIWORD) wParam |
|
Iparam |
Выбранный пункт: идентификатор меню или описатель всплывающего меню |
|
Флаги выбора |
Описатель меню, содержащего выбранный пункт |
Сообщение WM_MENUSELECT — это сообщение для отслеживания перемещения по меню. Младшее слово параметра wParam говорит о том, какой пункт меню выбран (подсвечен) в данный момент. В старшем слове параметра wParam могут быть комбинации из следующих флагов выбора: MF_G RAYED, MF_DISABLED, MF_CHECKED, MF_BITMAP, MF_POPUP, MF_HELP, MF_SYSMENU и MF_MOUSESELECT. Сообщение WM_MENUSELECT может понадобиться для того, чтобы изменить что-нибудь в рабочей области окна на основе информации о перемещении подсветки по пунктам меню. В большинстве программ это сообщение передается в DefWindowProc.
Когда Windows готова вывести на экран всплывающее меню, она посылает оконной процедуре сообщение WM_INITMENUPOPUP со следующими параметрами:
wParam |
|
Младшее слово (LOWORD) IParam |
Старшее слово (HIWORD) IParam |
Описатель всплывающего меню |
|
Индекс всплывающего меню |
Для системного меню 1, в противном случае 0 |
Это сообщение важно, если необходимо разрешать или запрещать пункты меню перед их выводом на экран. Например, предположим, что программа с помощью команды Paste всплывающего меню может копировать текст из буфера обмена. При получении для этого всплывающего меню сообщения WM_INITMENUPOPUP необходимо определить, имеется ли текст в буфере обмена. Если нет, то необходимо сделать этот пункт меню Paste недоступным.
Самым важным сообщением меню является WM_COMMAND. Это сообщение показывает, что пользователь выбрал разрешенный пункт меню окна. Сообщения WM_COMMAND также посылаются дочерними окнами управления. Если оказывается, что для меню и дочерних окон управления используются одни и те же идентификаторы, то различить их можно с помощью значения параметра IParam, который для пункта меню будет равен 0:
|
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
IParam |
Меню:
Элемент управления: |
Идентификатор меню Идентификатор элемента управления |
0
Код уведомления |
0
Описатель дочернего окна |
Сообщение WM_SYSCOMMAND похоже на сообщение WM_COMMAND за исключением того, что сообщение WM_SYSCOMMAND сигнализирует, что пользователь выбрал разрешенный пункт системного меню:
|
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
IParam |
Системное меню: |
Идентификатор меню |
0 |
0 (Если сообщение WM_SYSCOMMAND является результатом щелчка мыши, тогда старшее и младшее слово IParam являются, соответственно, экранными координатами Х и Y курсора мыши.) |
Идентификатор меню показывает, какой пункт системного меню выбран. Для предопределенных пунктов системного меню, четыре младших разряда должны быть замаскированы. Результирующая величина будет одной из следующих:
SC_SIZE, SC_MOVE, SC_MINIMIZE, SC_MAXIMIZE, SC_NEXTWINDOW, SCJPREVWINDOW, SC_CLOSE, SC_VSCROLL, SC_HSCROLL, SC_ARRANGE, SC_RESTORE и SC_TASKLIST. Кроме того, младшее слово параметра wParam может быть SC_MOUSEMENU или SC_KEYMENU.
Если вы добавите к системному меню новые пункты, то младшее слово параметра wParam станет идентификатором, который вы определите. Для избежания конфликта с предопределенными идентификаторами меню, используйте значения меньше чем ОхFООО. Важно, чтобы обычные сообщенияWM_SYSCOMMAND передавались в DefWindowProc. Если этого не сделать, то обычные команды системного меню будут отключены.
Последним сообщением, которое мы обсудим, является сообщение WM_MENUCHAR, которое, в действительности, не является собственно сообщением меню. Windows посылает это сообщение оконной процедуре в одном из двух случаев: если пользователь нажимает комбинацию клавиши <Alt> и символьной клавиши, несоответствующей пунктам меню, или при выводе на экран всплывающего меню, если пользователь нажимает символьную клавишу, не соответствующую пункту всплывающего меню. Параметры сообщения WM_MENUCHAR являются следующими:
Младшее слово (LOWORD) wParam |
Старшее слово (HIWORD) wParam |
Iparam |
Код ASCII |
Код выбора |
Описатель меню |
Код выбора равен:
• 0 — всплывающее меню не отображается.
• MF_POPUP — отображается всплывающее меню.
• MF_SYSMENU — отображается системное меню.
Как правило, в программах для Windows это сообщение передается DejWindowProc, которая обычно возвращает 0 в Windows, после чего Windows издает звуковой сигнал (гудок).