Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование для 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
[Назад] [Содеожание] [Дальше]