Программирование для 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 |