Программирование для IBM OS2
4cab9ef0

Изменение системного меню


В некоторых случаях приложения изменяют системное меню, доступное пользователю через пиктограмму, расположенную в верхнем левом углу главного окна приложения. Создавая простейшее приложение, вы можете организовать интерфейс с пользователем при помощи нескольких строк, добавленных к системному меню.

Процедура добавления строк к системному меню достаточно проста, хотя и состоит из нескольких шагов.

Прежде всего вы должны определить идентификатор окна системного меню. Это можно сделать при помощи функций WinWindowFromID и WinQueryWindow в обработчике сообщения WM_CREATE , например, так:

HWND hwndSystemMenu; hwndSystemMenu = WinWindowFromID ( WinQueryWindow (hWnd, QW_PARENT ), FID_SYSMENU );

В качестве первого параметра функции WinQueryWindow мы передали идентификатор окна Client Window , который передается в функцию окна. Второй параметр, равный константе QW_PARENT , сообщает функции WinQueryWindow о необходимости вернуть идентификатор окна, которое является родительским по отношению к окну hWnd. При этом мы получим идентификатор окна Frame Window , которое, очевидно, является родительским для окна системного меню.

Приведем прототип для функции WinQueryWindow :

HWND WinQueryWindow ( HWND hwnd, // идентификатор окна LONG lCode); // тип информации об окне

В зависимости от значения параметра lCode функция возвращает различную информацию об окне. Вы можете использовать для параметра lCode одну из следующих констант:



Константа Информация, возвращаемая функцией
QW_BOTTOM Дочернее окно самого нижнего уровня
QW_FRAMEOWNER Возвращается идентификатор окна-владельца для окна hwnd. Это окно имеет такое же родительское окно, что и окно hwnd
QW_NEXT Идентификатор окна, расположенного под окном, заданным параметром hwnd
QW_NEXTTOP Идентификатор следующего окна в иерархии окна-владельца
QW_OWNER Идентификатор окна-владельца
QW_PARENT Идентификатор родительского окна
QW_PREV Аналогично, но для окна, расположенного над заданным
QW_PREVTOP Идентификатор предыдущего окна в иерархии окна-владельца
QW_TOP Дочернее окно самого верхнего уровня
<
Функция WinWindowFromID возвращает идентификатор дочернего окна, заданного своим идентификатором ресурса. Она имеет такой прототип:

HWND WinWindowFromID ( HWND hwndParent, // идентификатор родительского окна ULONG id); // идентификатор ресурса дочернего окна

Так как системное меню имеет идентификатор ресурса, равный FID_SYSMENU , зная его, мы легко сможем определить идентификатор окна системного меню.

На следующем этапе нам необходимо определить идентификатор ресурса для системного меню. Для этого окну системного меню необходимо послать сообщение MM_ITEMIDFROMPOSITION , как это показано ниже:

SHORT sSysMeniID; sSysMeniID = (SHORT)WinSendMsg (hwndSystemMenu, MM_ITEMIDFROMPOSITION , MPFROMSHORT(0), NULL);

Младшее слово параметра mp1 сообщения MM_ITEMIDFROMPOSITION должно содержать порядковый номер элемента меню. В нашем случае требуется определить идентификатор для самого первого элемента, имеющего нулевой номер. Этот элемент является временным системным меню, которое появляется на экране, если сделать щелчок левой или правой клавишей мыши по пиктограмме системного меню.

Для того чтобы вставить строку в это временное меню, нам нужно знать его идентификатор. Этот идентификатор можно узнать, если послать окну системного меню сообщение MM_QUERYITEM , передав вместе с ним через первый параметр идентификатор ресурса системного меню, а через второй параметр - адрес структуры типа MENUITEM :

MENUITEM mi; HWND hwndSystemSubMenu; WinSendMsg (hwndSystemMenu, MM_QUERYITEM , MPFROMSHORT(sSysMeniID), MPFROMP(&mi)); hwndSystemSubMenu = mi.hwndSubMenu;

В поле hwndSubMenu этой структуры будет записан искомый идентификатор временного меню.

Структура MENUITEM и указатель на нее определены следующим образом:

typedef struct _MENUITEM { SHORT iPosition; // позиция элемента USHORT afStyle; // стиль USHORT afAttribute; // атрибуты USHORT id; // идентификатор ресурса HWND hwndSubMenu; // вложенное меню ULONG hItem; // идентификатор объекта отображения } MENUITEM ; typedef MENUITEM *PMENUITEM;



В поле iPosition хранится порядковый номер элемента (т. е. его позиция). Нумерация начинается с нуля. Для обозначения последней позиции (например, при вставке элемента в конец) можно использовать значение MIT_END .

Поля afStyle и afAttribute определяют, соответственно, стиль и атрибуты элемента меню. Здесь вы можете использовать константы с префиксом имени MIS_ и MIA_, описанные в начале этой главы в разделе "Подготовка шаблона меню".

В поле id при добавлении нового элемента необходимо записать его идентификатор. Этот идентификатор будет потом проверяться обработчиком сообщения WM_COMMAND . Если добавляется разделительная линия, в качестве идентификатора можно использовать значение -1.

Если данный элемент является вложенным меню, то в поле hwndSubMenu должен храниться идентификатор окна вложенного меню. Для обычной строки меню здесь располагается значение NULL.

Поле hItem содержит идентификатор объекта отображения, однако если элемент описывает строку меню, имеющую стиль MIS_TEXT , в поле находится нулевое значение. Это поле нужно в том случае, если в стоках меню отображаются графические пиктограммы.

Теперь, когда вы познакомились со структурой MENUITEM , покажем, как выполняется добавление строк в меню. Начнем с добавления разделительной линии к системному меню:

mi.afStyle = MIS_SEPARATOR; mi.afAttribute = 0; mi.hwndSubMenu = 0; mi.hItem = 0; mi.id = -1; mi.iPosition = MIT_END; WinSendMsg (hwndSystemSubMenu, MM_INSERTITEM , MPFROMP(&mi), NULL);

Так как мы добавляем разделительную линию, в поле стиля afStyle записываем константу MIS_SEPARATOR . Поля afAttribute, hwndSubMenu и hItem будут иметь нулевые значения.

Разделительная линия не посылает сообщение WM_COMMAND , поэтому ее идентификатор устанавливаем равным -1. Мы решили добавить разделительную линию в конец меню, поэтому устанавливаем позицию, равную MIT_END.

Для добавления строки посылаем окну временного системного меню сообщение MM_INSERTITEM . В качестве первого параметра вместе с этим сообщением необходимо передать адрес подготовленной струткуры MENUITEM , а в качестве второго - текстовую строку, которая будет отображаться в меню.При добавлении разделительной линии текстовая строка не нужна, поэтому второй параметр имеет значение NULL.

Для вставки обычной строки после разделительной линии мы снова готовим структуру MENUITEM и посылаем окну временного системного меню сообщение MM_INSERTITEM :

mi.afStyle = MIS_TEXT; mi.afAttribute = 0; mi.hwndSubMenu = 0; mi.hItem = 0; mi.iPosition = MIT_END; mi.id = IDM_HELP_ABOUT; WinSendMsg (hwndSystemSubMenu, MM_INSERTITEM , MPFROMP(&mi), "Product Information...");

На этот раз в поле стиля находится константа MIS_TEXT, а в поле id - константа IDM_HELP_ABOUT. Во втором параметре сообщения MM_INSERTITEM мы указываем адрес текстовой строки Product Information..., которая будет отображаться в нижней части измененного нами системного меню.


Содержание раздела