Приложение 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)); } }