Пример создания значков пунктов меню
Пример в этом разделе создает два меню, каждый из которых содержит несколько значков пунктов меню. Для каждого меню, прикладная программа добавляет соответствующее имя в меню строки основного окна.
Первое меню содержит пункты меню, которые показывают каждую из трех типов диаграмм: круговую, линейную и гистограмму. Значки для этих пунктов меню определены как ресурсы и загружаются при помощи использования функции LoadBitmap. С этим меню, в строке меню, связано имя "Chart" (Диаграмма).
Второе меню содержит пункты меню, которые показывают каждый из пяти типов линии, использующихся функцией CreatePen: PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT и PS_DASHDOTDOT. Прикладная программа создает значки для этих пунктов меню во время выполнения программы, используя, рисующие функции GDI. С этим меню, в горизонтальном меню, связано имя меню "Lines" (Линии).
В оконной процедуре прикладной программы заданы два статических массива дескрипторов значков. Один массив содержит дескрипторы трех значков, используемых для меню Chart, другой содержит дескрипторы из пяти значков, используемых для меню Lines. При обработке сообщения WM_CREATE, оконная процедура загружает значки диаграмм, создает значки линий, а затем добавляет соответствующие пункты меню. При обработке сообщения WM_DESTROY, оконная процедура удаляет все значки.
Ниже следуют необходимые части заголовочного файла приложения.
// Идентификаторы пунктов меню #define IDM_PIE 1 #define IDM_LINE 2 #define IDM_BAR 3 #define IDM_SOLID 4 #define IDM_DASH 5 #define IDM_DASHDOT 6 #define IDM_DASHDOTDOT 7 // Число пунктов в меню Chart и Lines #define C_LINES 5 #define C_CHARTS 3 // Идентификаторы ресурсов значков #define IDB_PIE 1 #define IDB_LINE 2 #define IDB_BAR 3 // Размеры значков линий #define CX_LINEBMP 40 #define CY_LINEBMP 10 |
Ниже следуют необходимые части оконной процедуры. Оконная процедура выполняет большинство инициализаций путем вызова определяемой программой функции LoadChartBitmaps, CreateLineBitmaps и AddBitmapMenu, описанные ниже в этом разделе.
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HBITMAP aHbmLines[C_LINES]; static HBITMAP aHbmChart[C_CHARTS]; int i; switch (uMsg) { case WM_CREATE: // Вызываем определяемые программой функции, чтобы // загрузить значки для меню Chart и создаем их для // меню Lines. LoadChartBitmaps(aHbmChart); CreateLineBitmaps(aHbmLines); // Вызываем определяемые программой функцию, чтобы // создать меню, содержащее пункты меню. Функция также // добавляет имя меню в строку меню окна. AddBitmapMenu( hwnd, // строка меню окна владельца "&Chart", // текст имени меню в строке меню IDM_PIE, // идентификатор первого пункта меню aHbmChart, // массив дескрипторов значков C_CHARTS // число пунктов меню ); AddBitmapMenu(hwnd, "&Lines", IDM_SOLID, aHbmLines, C_LINES); break; case WM_DESTROY: for (i = 0; i < C_LINES; i++) DeleteObject(aHbmLines[i]); for (i = 0; i < C_CHARTS; i++) DeleteObject(aHbmChart[i]); PostQuitMessage(0); break; // Здесь обработаем дополнительные сообщения. default: return (DefWindowProc(hwnd, uMsg, wParam, lParam)); } return 0; } |
Определяемая программой функция LoadChartBitmaps загружает ресурсы значков для меню диаграмм путем вызова функции LoadBitmap, как ниже указано.
VOID WINAPI LoadChartBitmaps(HBITMAP *paHbm) { paHbm[0] = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_PIE)); paHbm[1] = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_LINE)); paHbm[2] = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_BAR)); } |
Определяемая программой функция CreateLineBitmaps создает значки для меню Lines при помощи использования, рисующих функций GDI. Функция создает контекст устройства в памяти (DC) с теми же самыми свойствами, что и DC главного окна программы. Для каждого типа линии, функция создает значок, выбирает его в DC в памяти и рисует в нем.
VOID WINAPI CreateLineBitmaps(HBITMAP *paHbm) { HWND hwndDesktop = GetDesktopWindow(); HDC hdcDesktop = GetDC(hwndDesktop); HDC hdcMem = CreateCompatibleDC(hdcDesktop); COLORREF clrMenu = GetSysColor(COLOR_MENU); HBRUSH hbrOld; HPEN hpenOld; HBITMAP hbmOld; int fnDrawMode; int i; // Создадим кисть, которая используется для цвета фона меню // и выберем ее в DC в памяти. hbrOld = SelectObject(hdcMem, CreateSolidBrush(clrMenu)); // Создадим значки. Выберем каждый из созданных значков // в DC в памяти и нарисуем в нем. for (i = 0; i < C_LINES; i++) { // Создадим значок и выберем его в DC. paHbm[i] = CreateCompatibleBitmap(hdcDesktop, CX_LINEBMP, CY_LINEBMP); hbmOld = SelectObject(hdcMem, paHbm[i]); // Закрасим фон, используя кисть. PatBlt(hdcMem, 0, 0, CX_LINEBMP, CY_LINEBMP, PATCOPY); // Создадим перо и выберем его в DC. hpenOld = SelectObject(hdcMem, CreatePen(PS_SOLID + i, 1, RGB(0, 0, 0))); // Нарисуем линию. Чтобы сохранить цвет фона где // перо белое, используем режим рисования R2_MASKPEN. fnDrawMode = SetROP2(hdcMem, R2_MASKPEN); MoveToEx(hdcMem, 0, CY_LINEBMP / 2, NULL); LineTo(hdcMem, CX_LINEBMP, CY_LINEBMP / 2); SetROP2(hdcMem, fnDrawMode); // Удалим перо и выберем прежние перо и значок. DeleteObject(SelectObject(hdcMem, hpenOld)); SelectObject(hdcMem, hbmOld); } // Удалим кисть и выберем первоначальную кисть. DeleteObject(SelectObject(hdcMem, hbrOld)); // Удалим DC в памяти и освободим DC рабочего стола. DeleteDC(hdcMem); ReleaseDC(hwndDesktop, hdcDesktop); } |
Определяемая программой функция AddBitmapMenu создает меню и добавляет заданное число значков меню к его пунктам. Затем она добавляет соответствующее название меню к строке меню определяемого окна.
VOID WINAPI AddBitmapMenu( HWND hwnd, // окно, которое владеет строкой меню LPSTR lpszText, // текст имени меню в строке меню UINT uID, // идентификатор первого значка пункта меню HBITMAP *paHbm, // значки для пунктов меню int cItems) // число значков пунктов меню { HMENU hmenuBar = GetMenu(hwnd); HMENU hmenuPopup = CreatePopupMenu(); MENUITEMINFO mii; int i; // Добавляем значок пункта меню к меню. for (i = 0; i < cItems; i++) { mii.fMask = MIIM_ID | MIIM_BITMAP | MIIM_DATA; mii.wID = uID + i; mii.hbmpItem = &paHbm[i]; InsertMenuItem(hmenuPopup, i, TRUE, &mii); } // Добавляем имя меню к строке меню. mii.fMask = MIIM_STRING | MIIM_DATA | MIIM_SUBMENU; mii.fType = MFT_STRING; mii.hSubMenu = hmenuPopup; mii.dwTypeData = lpszText; InsertMenuItem(hmenuBar, GetMenuItemCount(hmenuBar), TRUE, &mii); } |