Программирование для IBM OS/2© Александр Фролов, Григорий ФроловТом 25, М.: Диалог-МИФИ, 1993, 286 стр. 3.8. Приложение MENUMODПриложение MENUMOD демонстрирует описанную выше методику изменения системного меню и динамического добавления временного меню в меню верхнего уровня. На рис. 3.8 показано системное меню приложения, в которое были добавлены разделительная линия и строка Product Information.
Рис. 3.8. Измененное системное меню в приложении MENUMOD (приложение запущено в среде частично локализованной операционной системы, поэтому вы видите русские строки системного меню) Кроме того, в приложении MENUMOD мы показали, как создаются вложенные меню (рис. 3.9).
Рис. 3.9. Использование вложенных меню в приложении MENUMOD Исходные тексты приложения приведены в листинге 3.5. Листинг 3.5. Файл menumod\menumod.c
// ===================================================
// Определения
// ===================================================
#define INCL_WIN
#define INCL_GPI
#define INCL_WINDIALOGS
#include <os2.h>
#include <stdio.h>
#include "menumod.h"
// Прототип функции окна приложения
MRESULT EXPENTRY WndProc(HWND, ULONG, MPARAM, MPARAM);
// ===================================================
// Глобальные переменные
// ===================================================
// Идентификатор Anchor-block
HAB hab;
// Идентификатор окна Frame Window
HWND hWndFrame;
// Идентификатор окна Client Window
HWND hWndClient;
// Заголовок приложения
CHAR szAppTitle[] = "Menu Modification Demo";
// Идентификатор меню Edit
HWND hwndEditMenu;
// Идентификатор меню верхнего уровня
HWND hwndMenu;
// ===================================================
// Главная функция приложения main
// ===================================================
int main ()
{
// Идентификатор очереди сообщений
HMQ hmq;
// Структура, в которую записывается сообщение,
// извлеченное из очереди
QMSG qmsg;
// Переменная для хранения кода возврата
BOOL fRc;
// Флаги для создания окна Frame Window
ULONG flFrameFlags =
FCF_SYSMENU | FCF_TITLEBAR | FCF_MINMAX |
FCF_SIZEBORDER | FCF_SHELLPOSITION | FCF_TASKLIST |
FCF_ICON | FCF_MENU;
// Имя класса главного окна
CHAR szWndClass[] = "MENUMODDEMO";
// Инициализация приложения, необходимая для
// использования функций Presentation Manager
hab = WinInitialize (0);
if(hab == NULLHANDLE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка инициализации",
"Ошибка", 0, MB_ICONHAND | MB_OK);
return(-1);
}
// Создаем очередь сообщений
hmq = WinCreateMsgQueue (hab, 0);
if(hmq == NULLHANDLE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка при создании очереди сообщений",
"Ошибка", 0, MB_ICONHAND | MB_OK);
WinTerminate (hab);
return(-1);
}
// Регистрация главного окна приложения
fRc = WinRegisterClass (hab, szWndClass,
(PFNWP)WndProc, 0, 0);
if(fRc == FALSE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка при регистрации класса главного окна",
"Ошибка", 0, MB_ICONHAND | MB_OK);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return(-1);
}
// Создаем главное окно приложения
hWndFrame = WinCreateStdWindow (HWND_DESKTOP,
WS_VISIBLE ,
&flFrameFlags, szWndClass, szAppTitle,
0, 0, ID_APP_FRAMEWND, &hWndClient);
if(hWndFrame == NULLHANDLE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка при создании главного окна",
"Ошибка", 0, MB_ICONHAND | MB_OK);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return(-1);
}
// Запускаем цикл обработки сообщений
while(WinGetMsg (hab, &qmsg, 0, 0, 0))
WinDispatchMsg (hab, &qmsg);
// Уничтожаем главное окно приложения
WinDestroyWindow(hWndFrame);
// Удаляем очередь сообщений и вызываем
// функцию WinTerminate
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
// Возвращаем управление операционной системе
return(0);
}
// ===================================================
// Функция главного окна приложения
// ===================================================
MRESULT EXPENTRY
WndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
// Временный буфер для подготовки сообщения
CHAR szMsg[100];
MENUITEM mi;
switch (msg)
{
case WM_CREATE :
{
HWND hwndSystemMenu;
HWND hwndSystemSubMenu;
SHORT sSysMeniID;
// ---------------------------------------------
// Добавляем строку к системному меню
// ---------------------------------------------
// Определяем идентификатор окна системного меню
hwndSystemMenu = WinWindowFromID (
WinQueryWindow (hWnd, QW_PARENT ), FID_SYSMENU );
// Определяем идентификатор системного меню
sSysMeniID = (SHORT)WinSendMsg (hwndSystemMenu,
MM_ITEMIDFROMPOSITION , MPFROMSHORT(0), NULL);
// Определяем характеристики системного меню
WinSendMsg (hwndSystemMenu, MM_QUERYITEM ,
MPFROMSHORT(sSysMeniID), MPFROMP(&mi));
// Идентификатор окна временного системного меню
hwndSystemSubMenu = mi.hwndSubMenu;
// Заполняем структуру для разделительной линии
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);
// Заполняем структуру для добавляемой строки
mi.afStyle = MIS_TEXT;
mi.id = IDM_HELP_ABOUT;
// Добавляем строку Product Information
WinSendMsg (hwndSystemSubMenu, MM_INSERTITEM ,
MPFROMP(&mi), "Product Information...");
// ---------------------------------------------
// Добавляем временное меню Edit
// ---------------------------------------------
// Получаем идентификатор окна меню
// верхнего уровня
hwndMenu = WinWindowFromID (
WinQueryWindow (hWnd, QW_PARENT ), FID_MENU );
// Создаем пустое меню Edit
hwndEditMenu = WinCreateMenu (HWND_OBJECT , NULL);
// Присваиваем меню Edit идентификатор IDM_EDIT
WinSetWindowUShort(hwndEditMenu, QWS_ID,
IDM_EDIT);
// Добавляем строки в меню
mi.iPosition = MIT_END;
mi.afStyle = MIS_TEXT;
mi.afAttribute = 0;
mi.hwndSubMenu = 0;
mi.hItem = 0;
mi.id = IDM_EDIT_UNDO;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Undo");
mi.id = IDM_EDIT_REDO;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Redo");
mi.id = IDM_EDIT_CUT;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "Cu~t");
mi.id = IDM_EDIT_COPY;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Copy");
mi.id = IDM_EDIT_PASTE;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Paste");
mi.id = IDM_EDIT_CLEAR;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "C~lear");
// Добавляем разделительную линию
mi.afStyle = MIS_SEPARATOR;
mi.id = -1;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Duplicate");
// Добавляем еще две строки
mi.afStyle = MIS_TEXT;
mi.id = IDM_EDIT_DUPLICATE;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Duplicate");
mi.id = IDM_EDIT_SELECTALL;
WinSendMsg (hwndEditMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Select all");
// Добавляем меню Edit в меню верхнего уровня
mi.iPosition = 1;
mi.afStyle = MIS_TEXT | MIS_SUBMENU;
mi.afAttribute = 0;
mi.id = IDM_EDIT;
mi.hwndSubMenu = hwndEditMenu;
WinSendMsg (hwndMenu, MM_INSERTITEM ,
MPFROMP(&mi), "~Edit");
return FALSE;
}
case WM_ERASEBACKGROUND :
return(MRFROMLONG(1L));
// Сообщение WM_COMMAND поступает в функцию окна,
// кодгда пользователь выбирает одну из строк меню
case WM_COMMAND :
{
// Анализируем код строки меню
switch(LOUSHORT(mp1))
{
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
case IDM_FILE_SAVE:
case IDM_FILE_SAVEAS:
case IDM_EDIT_UNDO:
case IDM_EDIT_REDO:
case IDM_EDIT_CUT:
case IDM_EDIT_COPY:
case IDM_EDIT_PASTE:
case IDM_EDIT_CLEAR:
case IDM_EDIT_DUPLICATE:
case IDM_EDIT_SELECTALL:
case IDM_OPTIONS_FONT_NORMAL:
case IDM_OPTIONS_FONT_BOLD:
case IDM_OPTIONS_FONT_ITALIC:
case IDM_OPTIONS_FONT_UNDERLINE:
case IDM_OPTIONS_PARA_LEFT:
case IDM_OPTIONS_PARA_CENTER:
case IDM_OPTIONS_PARA_RIGHT:
case IDM_OPTIONS_PARA_JUSTIFY:
case IDM_HELP_INDEX:
case IDM_HELP_GENERAL:
case IDM_HELP_USING:
case IDM_HELP_KEYS:
{
WinMessageBox (HWND_DESKTOP, hWnd,
"Функция не реализована",
szAppTitle, 0, MB_INFORMATION | MB_OK);
break;
}
case IDM_HELP_ABOUT:
{
WinMessageBox (HWND_DESKTOP, hWnd,
"Приложение MenuMod, (C) Frolov A., 1996",
szAppTitle, 0, MB_INFORMATION | MB_OK);
break;
}
// Если из меню File выбрана строка Exit,
// завершаем работу приложения
case IDM_FILE_EXIT:
{
WinPostMsg (hWnd, WM_QUIT , 0L, 0L);
break;
}
}
return(WinDefWindowProc (hWnd, msg, mp1, mp2));
}
default:
return(WinDefWindowProc (hWnd, msg, mp1, mp2));
}
}
Глобальные переменныеСреди глобальных переменных, обычных для наших приложений, имеются переменные hwndEditMenu и hwndMenu. В первой из них хранится идентификатор динамически создаваемого временного меню Edit, вторая предназначена для хранения идентификатора окна меню верхнего уровня. Функция mainФункция main в этом приложении не имеет никаких особенностей. Так как первоначально меню верхнего уровня загружается из ресурсов приложения, при создании главного окна мы указали флаг FCF_MENU . Функция окна WndProcИзменение системного меню и создание нового временного меню Edit выполняется обработчиком сообщения WM_CREATE . При этом используется методика, описанная нами ранее. Обработка остальных сообщений выполняется обычным образом, поэтому мы не будем на этом останавливаться. Файл menumod.hФайл menumod.h, содержащий определения всех необходимых констант, представлен в листинге 3.6. Листинг 3.6. Файл menumod\menumod.h #define ID_APP_FRAMEWND 1 #define IDM_FILE 100 #define IDM_FILE_NEW 101 #define IDM_FILE_OPEN 102 #define IDM_FILE_SAVE 103 #define IDM_FILE_SAVEAS 104 #define IDM_FILE_EXIT 105 #define IDM_EDIT 200 #define IDM_EDIT_UNDO 201 #define IDM_EDIT_REDO 202 #define IDM_EDIT_CUT 203 #define IDM_EDIT_COPY 204 #define IDM_EDIT_PASTE 205 #define IDM_EDIT_CLEAR 206 #define IDM_EDIT_DUPLICATE 207 #define IDM_EDIT_SELECTALL 208 #define IDM_HELP 300 #define IDM_HELP_INDEX 301 #define IDM_HELP_GENERAL 302 #define IDM_HELP_USING 303 #define IDM_HELP_KEYS 304 #define IDM_HELP_ABOUT 305 #define IDM_OPTIONS 500 #define IDM_OPTIONS_FONT 501 #define IDM_OPTIONS_FONT_NORMAL 502 #define IDM_OPTIONS_FONT_BOLD 503 #define IDM_OPTIONS_FONT_ITALIC 504 #define IDM_OPTIONS_FONT_UNDERLINE 505 #define IDM_OPTIONS_PARA 600 #define IDM_OPTIONS_PARA_LEFT 601 #define IDM_OPTIONS_PARA_CENTER 602 #define IDM_OPTIONS_PARA_RIGHT 603 #define IDM_OPTIONS_PARA_JUSTIFY 604 Файл ресурсов menumod.rcФайл описания ресурсов приложения menumod.rc (листинг 3.7) содержит описание пиктограммы и меню верхнего уровня. Обратите внимание, что в меню Options определены два вложенных меню Font и Alighnment. Определение временного меню Edit отсутствует, так как это меню создается динамически при обработке сообщения WM_CREATE . Листинг 3.7. Файл menumod\menumod.rc
#include <os2.h>
#include "menumod.h"
ICON ID_APP_FRAMEWND MENUMOD.ICO
MENU ID_APP_FRAMEWND
BEGIN
SUBMENU "~File", IDM_FILE
BEGIN
MENUITEM "~New...", IDM_FILE_NEW
MENUITEM "~Open...", IDM_FILE_OPEN
MENUITEM SEPARATOR
MENUITEM "~Save...", IDM_FILE_SAVE
MENUITEM "Save ~as...", IDM_FILE_SAVEAS
MENUITEM SEPARATOR
MENUITEM "~Exit", IDM_FILE_EXIT
END
SUBMENU "~Options", IDM_OPTIONS
BEGIN
SUBMENU "~Font",IDM_OPTIONS_FONT
BEGIN
MENUITEM "~Normal", IDM_OPTIONS_FONT_NORMAL
MENUITEM "~Bold", IDM_OPTIONS_FONT_BOLD
MENUITEM "~Italic", IDM_OPTIONS_FONT_ITALIC
MENUITEM "~Underline",IDM_OPTIONS_FONT_UNDERLINE
END
SUBMENU "~Alighnment",IDM_OPTIONS_PARA
BEGIN
MENUITEM "~Left", IDM_OPTIONS_PARA_LEFT
MENUITEM "~Center", IDM_OPTIONS_PARA_CENTER
MENUITEM "~Right", IDM_OPTIONS_PARA_RIGHT
MENUITEM "~Justify", IDM_OPTIONS_PARA_JUSTIFY
END
END
SUBMENU "~Help", IDM_HELP
BEGIN
MENUITEM "Help ~index...", IDM_HELP_INDEX
MENUITEM "~General help...", IDM_HELP_GENERAL
MENUITEM "~Using help...", IDM_HELP_USING
MENUITEM "~Keys help...", IDM_HELP_KEYS
MENUITEM SEPARATOR
MENUITEM "~Product information...",IDM_HELP_ABOUT
END
END
Файл определения модуляФайл определения модуля приложения MENUMOD представлен в листинге 3.8. Листинг 3.8. Файл menumod\menumod.def NAME MENUMOD WINDOWAPI DESCRIPTION 'MenuMod Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc |

