Смекни!
smekni.com

Сообщения меню приложения Windows (стр. 1 из 2)

СООБЩЕНИЯ МЕНЮ ПРИЛОЖЕНИЙ 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 (HWND hWnd, HMENU hMenu)

Параметры:

hWnd - хэндл окна, для которого нужно закрепить меню.

hMenu - хэндл добавляемого меню.

Возвращаемое значение: при успешном выполнении - TRUE, иначе - FALSE. BOOLDrawMenuBar (HWNDhWnd)

Параметры:

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 (), которой передаются пять аргументов: