Файл 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).