ПОВІДОМЛЕННЯ МЕНЮ ДОДАТКІВ 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 дорівнює дескриптору меню.
Молодше слово параметра l Param одно позиції цього меню в меню верхнього рівня:
uItem = (UINT) LOWORD (lParam);
Старше слово l Param дорівнює 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 (HWND hWnd, 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" виникає "Disable exit" і навпаки.
Тоді у функцію WinMain () необхідно додати:
const IDM_Enable_Disable = 0;
const IDM_Exit = 1;
const IDM_About = 2;
... ...
HMENU hMenu, 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 UINT nFlag = MF_ENABLED;
char * pContent [] =
{
"Enable exit",
"Disable exit"
};
static UINT nIndex = 0;
switch (Message)
{
case WM_COMMAND:
switch (wParam)
{
case IDM_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 () дозволяє змінювати стан елемента (дозволений, заборонений, "сірий") меню на свій розсуд. Синтаксис функції:
BOOL EnableMenuItem (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 не містить тимчасове меню:
HMENU GetSubMenu (HMENU hMenu, int nPos)
Параметри:
hMenu - Хендлі меню.
nPos - позиція необхідного тимчасового меню.
Значення, що повертається: при успішному виконанні - дескриптор меню, інакше - NULL.
Плаваюче меню створюють звичайним способом, але не вставляють в інше меню. Для відображення і вибору рядків цього меню викликають функцію TrackPopupMenu ().
Функція TrackPopupMenu () призначена для виводу на екран плаваючого меню і створення свого власного циклу обробки повідомлень, завершального роботу після вибору рядка. Вона не повертає управління до тих пір, поки робота з меню не буде завершена вибором рядки або відмовою від вибору. Синтаксис функції:
BOOL TrackPopupMenu (HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hwnd, 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 _RI GHTBUTTON | Простежує праву кнопку миші |