Операционная система Microsoft Windows 3.1 для программиста -том 3

Файл gmenu/gmenu.cpp


// ---------------------------------------------- // Использование графических изображений в меню // ----------------------------------------------

#define STRICT #include <windows.h>
#include <mem.h>
#include "gmenu.hpp"

// Прототипы функций BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

// Имя класса окна char const szClassName[] = "GMenuClass";

// Заголовок окна char const szWindowTitle[] = "Menu Demo";

// Идентификатор меню верхнего уровня HMENU hmenu;

// Идентификаторы временных меню HMENU hmenuFile; // "File" HMENU hmenuLineStyle; // "Edit" HMENU hmenuHelp; // "Help"

// Идентификаторы графических изображений для строк меню HBITMAP hbmpLine1; HBITMAP hbmpLine2; HBITMAP hbmpLine3; HBITMAP hbmpLine4; HBITMAP hbmpLineStyle; HBITMAP hbmpChecked; HBITMAP hbmpUnchecked;

// Идентификатор текущей копии приложения HINSTANCE hInst;

// ===================================== // Функция WinMain // ===================================== #pragma argsused

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения

// Инициализируем приложение if(!InitApp(hInstance)) return FALSE;

// Сохраняем идентификатор текущей копии приложения hInst = hInstance;



// После успешной инициализации приложения создаем // главное окно приложения hwnd = CreateWindow( szClassName, // имя класса окна szWindowTitle, // заголовок окна WS_OVERLAPPEDWINDOW, // стиль окна CW_USEDEFAULT, // задаем размеры и расположение CW_USEDEFAULT, // окна, принятые по умолчанию CW_USEDEFAULT, CW_USEDEFAULT, 0, // идентификатор родительского окна 0, // идентификатор меню hInstance, // идентификатор приложения NULL);
// указатель на дополнительные // параметры // Если создать окно не удалось, завершаем приложение if(!hwnd) return FALSE;

// Рисуем главное окно ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);




// Запускаем цикл обработки сообщений while(GetMessage(&msg, 0, 0, 0)) { DispatchMessage(&msg);
} return msg.wParam; }

// ===================================== // Функция InitApp // Выполняет регистрацию класса окна // =====================================

BOOL InitApp(HINSTANCE hInstance) { ATOM aWndClass; // атом для кода возврата WNDCLASS wc; // структура для регистрации // класса окна // Записываем во все поля структуры нулевые значения memset(&wc, 0, sizeof(wc));

wc.lpszMenuName = NULL; wc.style = 0; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = (LPSTR)szClassName;

// Регистрация класса aWndClass = RegisterClass(&wc);
return (aWndClass != 0);
}

// ===================================== // Функция WndProc // =====================================

LRESULT CALLBACK _export WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { // Загружаем изображения строк меню hbmpLine1 = LoadBitmap(hInst, "LINE1");
hbmpLine2 = LoadBitmap(hInst, "LINE2");
hbmpLine3 = LoadBitmap(hInst, "LINE3");
hbmpLine4 = LoadBitmap(hInst, "LINE4");
hbmpLineStyle = LoadBitmap(hInst, "LINESTYLE");
hbmpChecked = LoadBitmap(hInst, "CHECKED");
hbmpUnchecked = LoadBitmap(hInst, "UNCHECKED");

// Создаем пустое меню верхнего уровня hmenu = CreateMenu();

// Подключаем меню к главному окну приложения SetMenu(hwnd, hmenu);

// Создаем временные меню hmenuFile = CreatePopupMenu();
hmenuHelp = CreatePopupMenu();
hmenuLineStyle = CreatePopupMenu();

// Добавляем строки к меню "File" AppendMenu(hmenuFile, MF_ENABLED | MF_STRING, CM_FILENEW, "&New");
AppendMenu(hmenuFile, MF_ENABLED | MF_STRING, CM_FILEOPEN, "&Open");
AppendMenu(hmenuFile, MF_ENABLED | MF_STRING, CM_FILECLOSE, "&Close");
AppendMenu(hmenuFile, MF_ENABLED | MF_STRING, CM_FILESAVE, "&Save");
AppendMenu(hmenuFile, MF_ENABLED | MF_STRING, CM_FILESAVEAS, "Save &as...");
AppendMenu(hmenuFile, MF_SEPARATOR, 0, NULL);
AppendMenu(hmenuFile, MF_DISABLED | MF_STRING, CM_FILEDEMO, "&Demo Version");
AppendMenu(hmenuFile, MF_SEPARATOR, 0, NULL);
AppendMenu(hmenuFile, MF_ENABLED | MF_STRING, CM_FILEEXIT, "E&xit");



// Для строки "Demo Version" меню "File" определяем // изображения, которые будут использоваться для // вывода строки в отмеченном и неотмеченном состоянии SetMenuItemBitmaps(hmenuFile, CM_FILEDEMO, MF_BYCOMMAND, hbmpUnchecked, hbmpChecked);

// Отмечаем строку "Demo Version" CheckMenuItem(hmenuFile, CM_FILEDEMO, MF_BYCOMMAND | MF_CHECKED);

// Добавляем строки к меню "Line Style". // Вместо текстовых строк используем графические // изображения bitmap AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE1, (LPCSTR)(DWORD)hbmpLine1);
AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE2, (LPCSTR)(DWORD)hbmpLine2);
AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE3, (LPCSTR)(DWORD)hbmpLine3);
AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE4, (LPCSTR)(DWORD)hbmpLine4);

// Добавляем строки к меню "Help" AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING, CM_HELPINDEX, "&Index\tF1");
AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING, CM_HELPKEYBOARD, "&Keyboard");
AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING, CM_HELPCOMMANDS, "&Commands");
AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING, CM_HELPPROCEDURES, "&Procedures");
AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING, CM_HELPUSING_HELP, "&Using help");
AppendMenu(hmenuHelp, MF_SEPARATOR, 0, NULL);
AppendMenu(hmenuHelp, MF_ENABLED | MF_STRING, CM_HELPABOUT, "&About...");

// Добавляем временные меню к меню верхнего уровня AppendMenu(hmenu, MF_ENABLED | MF_POPUP, (UINT)hmenuFile, "&File");

// Для временного меню "Line Style" используем // изображение bitmap AppendMenu(hmenu, MF_ENABLED | MF_POPUP | MF_BITMAP, (UINT)hmenuLineStyle, (LPCSTR)(DWORD)hbmpLineStyle);

AppendMenu(hmenu, MF_ENABLED | MF_POPUP, (UINT)hmenuHelp, "&Help");

// Перерисовываем меню DrawMenuBar(hwnd);
return 0; }

case WM_COMMAND: { switch (wParam) { // Сообщения от меню case CM_HELPUSING_HELP: case CM_HELPPROCEDURES: case CM_HELPCOMMANDS: case CM_HELPKEYBOARD: case CM_HELPINDEX: case CM_FILESAVEAS: case CM_FILESAVE: case CM_FILEOPEN: case CM_FILENEW: case CM_FILECLOSE: { // Выводим сообщение об ошибке MessageBox(hwnd, "Функция не реализована", NULL, MB_OK);
return 0; }



// Выбрали строку "About..." в меню "Help" case CM_HELPABOUT: { MessageBox(hwnd, "Приложение GMENU\n(C) Фролов А.В., 1994", szWindowTitle, MB_OK | MB_ICONINFORMATION);
return 0; }

// Завершаем работу приложения case CM_FILEEXIT: { DestroyWindow(hwnd);
return 0; } default: return 0; } }

case WM_DESTROY: { // Уничтожаем созданные ранее меню DestroyMenu(hmenuFile);
DestroyMenu(hmenuHelp);
DestroyMenu(hmenuLineStyle);
DestroyMenu(hmenu);

// Удаляем изображения DeleteObject(hbmpLine1);
DeleteObject(hbmpLine2);
DeleteObject(hbmpLine3);
DeleteObject(hbmpLine4);
DeleteObject(hbmpLineStyle);
DeleteObject(hbmpChecked);
DeleteObject(hbmpUnchecked);

PostQuitMessage(0);
return 0; } default: break; } return DefWindowProc(hwnd, msg, wParam, lParam);
}

При обработке сообщения WM_CREATE приложение, наряду с другими инициализирующими действиями, загружает из ресурсов приложения все необходимые для меню изображения bitmap:

hbmpLine1 = LoadBitmap(hInst, "LINE1");
hbmpLine2 = LoadBitmap(hInst, "LINE2");
hbmpLine3 = LoadBitmap(hInst, "LINE3");
hbmpLine4 = LoadBitmap(hInst, "LINE4");
hbmpLineStyle = LoadBitmap(hInst, "LINESTYLE");
hbmpChecked = LoadBitmap(hInst, "CHECKED");
hbmpUnchecked = LoadBitmap(hInst, "UNCHECKED");

Для строки "Demo Version" мы используем созданные нами и описанные в ресурсах приложения изображения bitmap, для чего вызываем функцию SetMenuItemBitmaps :

SetMenuItemBitmaps(hmenuFile, CM_FILEDEMO, MF_BYCOMMAND, hbmpUnchecked, hbmpChecked);

Далее мы отмечаем указанную строку:

CheckMenuItem(hmenuFile, CM_FILEDEMO, MF_BYCOMMAND | MF_CHECKED);

Затем мы переходим к формированию временного меню, содержащего графические изображения. Для этого в меню hmenuLineStyle, созданное ранее как пустое, мы добавляем четыре строки:

AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE1, (LPCSTR)(DWORD)hbmpLine1);
AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE2, (LPCSTR)(DWORD)hbmpLine2);
AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE3, (LPCSTR)(DWORD)hbmpLine3);
AppendMenu(hmenuLineStyle, MF_ENABLED | MF_BITMAP, CM_LINE4, (LPCSTR)(DWORD)hbmpLine4);

Как видно из рис. 1.21, для строки "Line Style" используется нестандартный шрифт. Точнее говоря, для этой строки мы использовали изображение bitmap, на котором написаны слова "Line Style":

AppendMenu(hmenu, MF_ENABLED | MF_POPUP | MF_BITMAP, (UINT)hmenuLineStyle, (LPCSTR)(DWORD)hbmpLineStyle);

Перед завершением работы приложения мы удаляем все загруженные изображения bitmap для освобождения системных ресурсов:

DeleteObject(hbmpLine1);
DeleteObject(hbmpLine2);
DeleteObject(hbmpLine3);
DeleteObject(hbmpLine4);
DeleteObject(hbmpLineStyle);
DeleteObject(hbmpChecked);
DeleteObject(hbmpUnchecked);

Символические константы, использованные в приложении GMENU, описаны в файле gmenu.cpp (листинг 1.17).


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