СООБЩЕНИЯ МЕНЮ ПРИЛОЖЕНИЙ WINDOWS
При смене подсвеченного элементаменю (если, к примеру, пользователь «пробегает» по элементам меню спомощью клавиш со стрелками вверх и вниз) в оконную процедуру посылаетсясообщение WM_MENUSELECT. Этосообщение посылают все элементы меню.
Когда же пользователь производитвыбор (нажимает клавишу «Enter», к примеру),сообщение WM_COMMAND оконнойпроцедуре посылают только обычные элементы меню. Запрещенные и «серые»элементы меню в этом случае никаких сообщений не посылают.
В элементах wParamи IParam посылаемых сообщений хранится информация,достаточная для того, чтобы программа смогла определить, какие действия ейнеобходимо выполнить случае выбора пользователем того или иного элемента меню.
Помимо обычного меню у окна вбольшинстве случаев есть еще и системное меню. Сказанное относится и ксистемному меню. Отличие между обычным меню и системным состоит в том, чтооконной процедуре посылаются сообщения WM_SYSMENUSELECT и WM_SYSCOMMAND.Кроме этого, сообщения WM_SYSCOMMANDоконная процедура получает и в случае нажатия кнопок минимизации, максимизациии закрытия окна, которые находятся не в системном меню, а в правом углузаголовка окна.
Параметры сообщения WM_MENUSELECT. В младшем слове wParam оконная процедура получает сведения о том, какойэлемент стал подсвеченным. Если учесть, что макросы LOWORD() и HIWORD () выделяют соответственно младшее истаршее слово 32-битного аргумента, и назвать источник сообщения uItem, то можно записать:
uItem =(UINT) LOWORD (wParam);
В зависимости от обстоятельствсмысл uItem различается:
если подсвеченный элементявляется конечным и не влечет за собой вызов popup-меню,то ultem содержит идентификатор элемента меню;
если подсвеченный элемент привыборе влечет за собой вызов popup-меню, то ultem содержит номер (индекс) этого элемента в том меню, вкотором оно находится;
В старшем слове wParam содержатся характеристики подсвеченного элемента. Аналогичнопредыдущему,
fuFlags= (UINT) HIWORD (wParam).
Возможные значения fuFlags характеризуются идентификаторами, начинающимися с MF_ (табл.1).
Таблица 1
Характеристики подсвеченногоэлемента менюФлаг Описание MF_BITMAP Вместо строки в качестве элемента меню применяется bitmap MF_CHECKED Элемент отмечаемый (со «значком») MF_DISABLED Элемент запрещен MF_GRAYED Элемент запрещен и отображается серым цветом MF_HILITE Элемент подсвечен MF_MOUSESELECT Элемент выбран мышью MF_OWNERDRAW За прорисовку элемента отвечает не система, а программа MF_POPUP Элемент вызывает появление рорир-меню более низкого уровня MF_SYSMENU Элемент из системного меню
lParamсодержит в себе хэндл того меню, которому принадлежит подсвеченный элемент. Обозначивхэндл меню как hMenu, получим:
hMenu =(HMENU) lParam;
Параметры сообщения WM_COMMAND. Как и в случае с WM_SELECTMENU, младшее слово wParam содержит сведения об источнике сообщения. Так каксообщение WM_COMMAND посылаетсятолько конечными элементами меню, то в младшем слове wParamсодержится идентификатор выбранного элемента меню:
wID = LOWORD (wParam);
Старшее слово wParam указывает, от какого управляющего элемента пришло сообщение.Если сообщение пришло от меню, то это слово равно нулю, т.е.
wNotifyCode= HIWORD (wParam) = 0;
lParam вслучае сообщения от меню ВСЕГДА равно NULL!
Параметры сообщения WM_INITMENU. Сообщение WM_INITMENUпоступает перед отображением главного меню.
Параметр wParam равендескриптору меню. Если сообщение WM_INITMENU обрабатывают, то возвращают 0. Обработкаобычно сводится к изменению состояния элементов меню
Параметры сообщения WM_INITMENUPOPUP.
Это сообщение поступает передотображением временного меню.
Параметр wParam равендескриптору меню.
Младшее слово параметра lParam равно позиции этого меню в меню верхнего уровня:
uItem =(UINT) LOWORD (lParam);
Старшее слово lParamравно 1 для системного меню и 0 — для обычного.
Если это сообщение обрабатывают,то возвращают 0. Обработка обычно сводится к изменению состояния элементов меню.
Итак, меню имеет строгуюдревовидную структуру, которая начинается с меню первого уровня (оно обычноназывается главным меню программы или menubar'ом ирасполагается сразу под заголовком окна). К этому меню первого уровня могутбыть присоединены как конечные элементы меню, так и элементы, выбор которыхприводит к появлению так называемых всплывающих (popup)меню, к которым, в свою очередь, присоединяются элементы очередного уровня и т.д.Перед началом создания меню вся его структура должна быть тщательно продумана. Неплохо,если бы программист имел перед глазами графическое представление этого меню.
Для создания меню необходимовыполнить следующие действия:
Выбрать подменю самого низкогоуровня, которые содержат только конечные элементы меню, и создать их с помощьюфункций CreateMenu () или CreatePopupMenu() в зависимости от потребностей. Эти функции возвращают хэндл созданного меню.Меню создается пустым.
Посредством функции AppendMenu () добавляем в них требуемые элементы.
Создаем меню следующего, болеевысокого уровня, и добавляем в них требуемые элементы и меню, созданные нами напредыдущем шаге.
Повторяем пункты 1 — 3 до техпор, пока создание всех подменю не будет закончено.
Создаем главное меню программыпосредством использования функции CreateMenu ().
Присоединяем созданные подменюсамого высокого уровня к главному меню программы с помощью функции AppendMenu ().
Присоединяем меню к окнупосредством использования функции SetMenu ().
Прорисовываем меню с помощьюфункции DrawMenuBar ().
Если в ходе программы сложиласьтакая ситуация, что меню оказалось не присоединенным к окну, перед выходом изпрограммы обязательно уничтожаем его, вызывая функцию DestroyMenu () (присоединенноек окну меню уничтожается автоматически при уничтожении окна).
Формат названных API-функций выглядитследующим образом:
HMENU CreateMenu ()
Параметры: не имеются.
Возвращаемое значение: хэндлвновь созданного меню, иначе — NULL.
HMENU CreatePopupMenu ()
Параметры: не имеются.
Возвращаемое значение: хэндлвновь созданного всплывающего меню, иначе — NULL.
BOOL AppendMenu(HMENU hMenu, UINT uFlags, UINT idNewItem, LPCTSTR lpszNewItem)
Параметры:
hMenu — хэндл того меню, вкоторое добавляется новый пункт.
uFlags — комбинация битовыхфлагов, определяющих внешний вид и поведение добавляемого меню. Начинаются спрефикса MF_.
idNewItem — идентификатор длянового пункта меню либо хэндл добавляемого всплывающего меню (зависит от флагаMF_POPUP, того, установленного во втором параметре).
lpszNewItem — содержимое нового пункта меню. Зависит от установленныхфлагов uFlags. Установлен флаг MF_BITMAP — параметр содержит хэндл bitmap'а.Установлен флаг MF_STRING — параметрсодержит указатель на строку символов и т.д.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE.
BOOL SetMenu (HWNDhWnd, HMENU hMenu)
Параметры:
hWnd — хэндл окна, для которогонужно закрепить меню.
hMenu — хэндл добавляемого меню.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE. BOOL DrawMenuBar (HWND hWnd)
Параметры:
hWnd — хэндл окна,которое имеет меню.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE.
/>
Например. Создадим окно, котороесодержит основное меню (рис.1). Основное меню окна состоит из двух всплывающихменю: «File» и «Help». В первом всплывающем меню находятсядва элемента, «Enable exit» и «Exit», во втором — одинэлемент, «About», который остается запрещенным в течение всегопериода существования окна. Кроме этого, элемент «Exit» при запускеобъявляется «серым», т.е. из программы можно выйти только черезсистемное меню. Однако в случае выбора элемента «Enable exit» «Exit»становится обычным, а вместо «Enable exit» возникает «Disableexit» и наоборот.
Тогда в функцию WinMain () необходимодобавить:
constIDM_Enable_Disable = 0;
const IDM_Exit= 1;
const IDM_About= 2;
……
HMENUhMenu,hFileMenu,hHelpMenu;
hFileMenu=CreatePopupMenu();
AppendMenu (hFileMenu,MF_ENABLED| MF_STRING, IDM_Enable_Disable, "&Enable exit");
AppendMenu (hFileMenu,MF_GRAYED | MF_STRING, DM_Exit,«E&xit»);
hHelpMenu=CreatePopupMenu();
AppendMenu (hHelpMenu,MF_DISABLED| MF_STRING, IDM_About, "&About");
hMenu =CreateMenu ();
AppendMenu (hMenu,MF_ENABLED | MF_POPUP, (UINT) hFileMenu, "&File");
AppendMenu (hMenu,MF_ENABLED | MF_POPUP, (UINT) hHelpMenu,"&Help");
SetMenu (hWnd, hMenu);
/*Прорисовка окна и меню*/
ShowWindow (hWnd,nCmdShow);
UpdateWindow (hWnd);
DrawMenuBar (hWnd);
……. .
/*Добавляемыйфрагмент в WndProc */
static UINTnFlag = MF_ENABLED;
char* pContent[] =
{
«Enableexit»,
«Disableexit»
};
static UINTnIndex = 0;
switch (Message)
{
case WM_COMMAND:
switch (wParam)
{
caseIDM_Enable_Disable:
EnableMenuItem(hFileMenu, IDM_Exit, MF_BYCOMMAND | nFlag);
nFlag = (nFlag== MF_ENABLED)? MF_GRAYED: MF_ENABLED;
nIndex = (nIndex== 0)? 1: 0;
ModifyMenu (hFileMenu,IDM_Enable_Disable, MF_BYCOMMAND | MF_STRING, IDM_Enable_Disable, pContent [nIndex]);
break;
case IDM_Exit:
DestroyWindow (hWnd);
break;
}
….
}
Как видно из примера, приполучении WM_COMMAND, младшееслово wParam которого равно равно IDM_Enable_Disable, производятсяследующие действия:
с помощью функции EnableMenuItem () запрещается или делается доступным элемент«Exit»;
с помощью функции ModifyMenu () изменяется текст элемента, выбор которогоприводит к состоянию элемента «Exit».
Функция EnableMenuItem () позволяетизменять состояние элемента (разрешенный, запрещенный, «серый») менюпо своему усмотрению. Синтаксис функции:
BOOLEnableMenuItem (HMENU hMenu, UINT uItem, UINT uFlags)
Параметры:
hMenu — хэндл меню, которомупринадлежит пункт меню.
uItem — пункт меню, состояниекоторого изменяется.
uFlags — комбинация битовыхфлагов, определяющее новое состояние uItem пункта меню. Флаг MF_BYCOMMANDпоказывает, значение представляет собой идентификатор пункта меню.
Возвращаемое значение: предыдущеесостояние пункта меню (MF_DISABLE, MF_ENABLE, MF_GRAYED), иначе- 0хffffffff (-1).
Функция ModifyMenu() После изменения состояния элемента «Exit» сразрешенного на серое и наоборот, необходимо изменить текст в элементе, откоторого зависит это состояние. Это изменение производится посредством вызовафункции ModifyMenu (), которой передаются пятьаргументов:
BOOL ModifyMenu(HMENU hMenu, UINT uItem, UINT uFlags, UINT uNewItem, LPCTSTR lpszNewItem)
Параметры:
hMenu — хэндл меню, которомупринадлежит пункт меню.
uItem — пункт меню, состояниекоторого изменяется.
uFlags — комбинация битовыхфлагов, во-первых, определяющих элемент, подлежащий изменению (MF_BYCOMMAND илиMF_BYPOSITION), а во-вторых, определяющих состояние элемента после изменения.
uNewItem — указывает илиидентификатор измененного элемента, или хэндл нового меню (если, конечно, втретьем аргументе установлен флаг MF_POPUP).
lpszNewItem — содержимое нового измененного пункта меню. Зависит отустановленных флагов uFlags. Установлен флаг MF_BITMAP — параметр содержит хэндл bitmap'а. Установлен флаг MF_STRING — параметр содержит указатель на строку символов и т.д.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE.
Функция DeleteMenu () удаляетэлемент из меню и освобождает все связанные с ним ресурсы. Если удаляемыйэлемент указывает на временное меню, то функция DeleteMenu удаляет и этовременное меню. Синтаксис функции:
BOOL DeleteMenu(HMENU hMenu, UINT uPosition, UINT uFlags)
Параметры:
hMenu — хэндл меню, которомупринадлежит пункт меню.
uPosition — определяет удаляемыйэлемент. Его значение связано со значением параметра uFlags.
uFlags — задает способ истолкованияпараметра uPosition пункта меню. Если uFlags=MF_BYCOMMAND (значение поумолчанию), то значение uPosition равно идентификатору команды удаляемогоэлемента. Если же uFlags=MF_BYPOSITION, то значение uPosition равно позиции удаляемогоэлемента в меню.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE.
Функция RemoveMenu () удаляетэлемент из меню, не разрушая связанные с ним ресурсы. Эти ресурсы можноиспользовать в дальнейшем. Синтаксис функции:
BOOL RemoveMenu (HMENU hMenu,UINT uPosition, UINT uFlags)
Параметры:
hMenu — хэндл меню, которомупринадлежит пункт меню.
uPosition — определяет удаляемыйэлемент. Его значение связано со значением параметра uFlags.
uFlags — задает способ истолкованияпараметра uPosition пункта меню. Если uFlags=MF_BYCOMMAND (значение поумолчанию), то значение uPosition равно идентификатору команды удаляемогоэлемента. Если же uFlags=MF_BYPOSITION, то значение uPosition равно позиции удаляемогоэлемента в меню.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE.
Для разрушения меню вызываютфункцию DestroyMenu (). Эта функция разрушает заданноеменю и освобождает ресурсы, которые меню занимает. Эту функцию окна вызываютдля разрушения тех меню, которые они создали, но не подключили к себе. ПодключенныеМеню автоматически разрушаются при разрушении окна. Синтаксис функции:
BOOL DestroyMenu (HMENU hMenu)
Параметры:
hMenu — хэндл меню, которомупринадлежит пункт меню.
Возвращаемое значение: приуспешном выполнении — TRUE, иначе — FALSE
Функция GetMenu () возвращаетдескриптор главного меню окна hWnd.
HMENU GetMenu (HWND hWnd)
Параметры:
hWnd — хэндл окна, которому принадлежитглавное меню.
Возвращаемое значение: приуспешном выполнении — дескриптор меню, иначе — NULL.
Функция GetSubMenu () возвращаетдескриптор всплывающего меню, которое расположено в позиции nPos указанногоменю hMenu. Причем первому временному меню в hMenu соответствует нулевоезначение параметра nPos. Если функция GetSubMenu () вернула значение NULL, тоhMenu в позиции nPos не содержит временное меню:
HMENUGetSubMenu (HMENU hMenu, int nPos)
Параметры:
hMenu — хэндл меню.
nPos — позиция требуемого временногоменю.
Возвращаемое значение: приуспешном выполнении — дескриптор меню, иначе — NULL.
Плавающее меню создают обычнымспособом, но не вставляют в другое меню. Для отображения и выбора строк этогоменю вызывают функцию TrackPopupMenu ().
Функция TrackPopupMenu () предназначенадля вывода на экран плавающего меню и создания своего собственного циклаобработки сообщений, завершающего работу после выбора строки. Она не возвращаетуправление до тех пор, пока работа с меню не будет завершена выбором строки илиотказом от выбора. Синтаксис функции:
BOOLTrackPopupMenu (HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWNDhwnd, CONST RECT *prcRect)
Параметры:
hMenu — дескриптор отображаемогоплавающего меню. Он может быть создан функцией CreatePopupMenu () или получен спомощью функции GetSubMenu ().
uFlags — комбинация флагов,которые задают функциональные параметры плавающего меню.
х — координата по горизонтали отлевого края экрана.
у — координата по вертикали отверхнего края экрана.
nReserved — зарезервированныйпараметр, должен быть всегда равен нулю.
hwnd — дескриптор ужесуществующего окна-владельца, которое получит сообщения от меню. СообщениеWM_COMMAND окно получит только после завершения работы функции TrackPopupMenu ().
prcRect — указатель напрямоугольную область, находясь в пределах которой можно работать с меню. Еслисделать щелчок мышью за пределами этого прямоугольника, плавающее меню исчезнет.Если prcRect=NULL, то эта область ограничена прямоугольной рамкой плавающегоменю.
Возвращаемое значение: в случаеуспешного выполнения функция возвращает ненулевое значение. Если в параметреuFlags задано TPM_RETURNCMD, то возвращаемое значение равно идентификаторукоманды выбранной строки. Если элемент не выбран, возвращаемое значение — нуль.
Следующиеконстанты uFlags задают способ размещения меню по горизонтали относительнопараметра х: Константа Пояснение ТРМ_CENTERALIGN Центр меню по горизонтали совпадает с х ТРМ_LEFTALIGN Левый край меню совпадает с х TPM_RIGHTALIGN Правый край меню совпадает с х
Следующиеконстанты uFlags задают способ размещения меню по вертикали относительнопараметра у: Константа Пояснение TPM_BOTTOMALIGN Нижний край меню совпадает с у TPM_TOPALIGN Верхний край меню совпадает с у TPM_VCENTERALIGN Центр меню по вертикали совпадает с у
Следующиеконстанты uFlags задают способ выбора строк меню без указания окна-владельцадля меню: Константа Пояснение ТРМ_NONOTIFY Не посылать сообщения о выборе строки TPM_RETURNCMD Возвращать идентификатор выбранной команды
Следующиеконстанты uFlags задают кнопку мыши, которую прослеживает плавающее меню: Константа Пояснение ТРМ_LEFTBUTTON Прослеживает левую кнопку мыши TPM_RIGHTBUTTON Прослеживает правую кнопку мыши