Моделирование окошек меток в меню
Эта тема содержит пример, который показывает, как моделировать окошки меток "галочкой" в меню. Пример содержит меню
Character, пункты которого позволяют пользователю устанавливать атрибуты текущего шрифта, такие как полужирный, курсивный и подчеркнутый. Когда атрибут шрифта действует, галочка отображается в окошке метки рядом с соответствующим пунктом меню; иначе, рядом с этим пунктом отображается пустое окошко для флажка.Пример заменяет заданный по умолчанию точечный рисунок "галочки " на два точечных рисунка (значка): значок с установленным в окне маркером и значок с пустым окном (без маркера). Точечный рисунок окошка для маркера отображается рядом с пунктом меню Bold, Italic или Underline, когда атрибут "галочки " пункта установлен в значение MF_CHECKED. Снятый маркер "галочки" или пустой точечный рисунок окошка для маркера отображается тогда, когда атрибут "галочки " установлен в значение MF_UNCHECKED.
Система предоставляет предопределенный точечный рисунок (значок), который содержит изображения, используемые для окошек с маркером "галочка" и радио-кнопок. Пример разделяет пустые окошки и с галочкой, копирует их в два отдельных точечных рисунка (значка), а затем использует их как значки установки и снятия отметки "галочкой" для пунктов в меню Character .
Чтобы получить дескриптор заданного системой рисунка окошка для флажка, пример вызывает функцию LoadBitmap, устанавливая значение ПУСТО (NULL) в параметре hInstance и OBM_CHECKBOXES в параметре lpBitmapName. Поскольку все изображения значков одного и того же размера, пример может разделять их, поделив ширину и высоту точечного рисунка на число изображений в строках и столбцах.
Нижеследующая часть файла определения ресурса показывает, как определены пункты меню в меню Character. Обратите внимание!, что сначала атрибуты шрифта не действуют, так как атрибут "галочки " для пункта (Regular) установлен в выбранное состояние, а, по умолчанию, атрибут "галочки " оставшихся пунктов установлен в невыбранное состояние (без "галочки").
#include "men3.h" MainMenu MENU BEGIN POPUP "&Character" BEGIN MENUITEM "&Regular", IDM_REGULAR, CHECKED MENUITEM SEPARATOR MENUITEM "&Bold", IDM_BOLD MENUITEM "&Italic", IDM_ITALIC MENUITEM "&Underline", IDM_ULINE END END |
Здесь находится относящееся к примеру содержание заголовочного файла прикладной программы.
// Идентификаторы пунктов меню #define IDM_REGULAR 0x1 #define IDM_BOLD 0x2 #define IDM_ITALIC 0x4 #define IDM_ULINE 0x8 // Флажки "галочки" #define CHECK 1 #define UNCHECK 2 // Маска атрибута шрифта #define ATTRIBMASK 0xe // Прототипы функций LRESULT APIENTRY MainWndProc(HWND, UINT, WPARAM, LPARAM); HBITMAP GetMyCheckBitmaps(UINT); BYTE CheckOrUncheckMenuItem(BYTE, HMENU); |
Следующий пример показывает части оконной процедуры, которые создают значки "галочек "; устанавливает атрибут "галочки" пунктов меню Bold , Italic и Underline и уничтожает значки "галочек".
LRESULT APIENTRY
MainWndProc(HWND hwndMain, UINT uMsg, WPARAM
wParam,
LPARAM lParam) { static HBITMAP hbmpCheck; // дескриптор значка с отметкой static HBITMAP hbmpUncheck; // дескриптор значка без отметки static HMENU hmenu; // дескриптор главного меню BYTE fbFontAttrib; // флажки атрибутов шрифта switch (uMsg) { case WM_CREATE: // Вызовем определяемую программой функцию GetMyCheckBitmaps, // чтобы получить предопределенные точечные рисунки окошка для // установки и снятия отметки "галочкой". hbmpCheck = GetMyCheckBitmaps(CHECK); hbmpUncheck = GetMyCheckBitmaps(UNCHECK); // Установим значки с галочкой и без нее // в пунктах меню. hmenu = GetMenu(hwndMain); SetMenuItemBitmaps(hmenu, IDM_BOLD, MF_BYCOMMAND, hbmpUncheck, hbmpCheck); SetMenuItemBitmaps(hmenu, IDM_ITALIC, MF_BYCOMMAND, hbmpUncheck, hbmpCheck); SetMenuItemBitmaps(hmenu, IDM_ULINE, MF_BYCOMMAND, hbmpUncheck, hbmpCheck); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { // Обработка команд меню. case IDM_REGULAR: case IDM_BOLD: case IDM_ITALIC: case IDM_ULINE: // Программно-определяемая функция CheckOrUncheckMenuItem // устанавливает в пунктах меню "галочки" и возвращает // значения атрибутов шрифта, которые // выбрал пользователь. fbFontAttrib = CheckOrUncheckMenuItem( (BYTE) LOWORD(wParam), hmenu); // Устанавливаем атрибуты шрифта. return 0; // Обработаем другие командные сообщения. default: break; } break; // Обработаем другие сообщения окна. case WM_DESTROY: // Разрушим значки с меткой и без метки. DeleteObject(hbmpCheck); DeleteObject(hbmpUncheck); PostQuitMessage(0); break; default: return DefWindowProc(hwndMain, uMsg, wParam, lParam); } return NULL; } HBITMAP GetMyCheckBitmaps(UINT fuCheck) { COLORREF crBackground; // цвет фона HBRUSH hbrBackground; // кисть фона HBRUSH hbrTargetOld; // первоначальная кисть фона HDC hdcSource; // источниковый контекст устройства HDC hdcTarget; // целевой контекст устройства HBITMAP hbmpCheckboxes; // дескриптор значка отметки BITMAP bmCheckbox; // структура для данных значка HBITMAP hbmpSourceOld; // дескриптор исходного источникового // значка HBITMAP hbmpTargetOld; // дескриптор исходного целевого значка HBITMAP hbmpCheck; // дескриптор значка "галочки" RECT rc; // прямоугольник для значка "галочки" WORD wBitmapX; // ширина значка "галочки" WORD wBitmapY; // высота значка "галочки" // Получим цвет фона меню и создадим сплошную кисть // этого цвета. crBackground = GetSysColor(COLOR_MENU); hbrBackground = CreateSolidBrush(crBackground); // Создадим контекст устройства в памяти для источникового значка // и значка предназначения. hdcSource = CreateCompatibleDC((HDC) NULL); hdcTarget = CreateCompatibleDC(hdcSource); // Получим системный по умолчанию размер значка "галочки" // и создадим совместимый точечный рисунок такого же размера. wBitmapX = GetSystemMetrics(SM_CXMENUCHECK); wBitmapY = GetSystemMetrics(SM_CYMENUCHECK); hbmpCheck = CreateCompatibleBitmap(hdcSource, wBitmapX, wBitmapY); // Выберем кисть фона и значок в DC. hbrTargetOld = SelectObject(hdcTarget, hbrBackground); hbmpTargetOld = SelectObject(hdcTarget, hbmpCheck); // Используем выбранную кисть для инициализации цвета фона // значка в целевом контексте устройства. PatBlt(hdcTarget, 0, 0, wBitmapX, wBitmapY, PATCOPY); // Загрузим предопределенный рисунок окошка отметки и выберем его // в источниковом DC. hbmpCheckboxes = LoadBitmap((HINSTANCE) NULL, (LPTSTR) OBM_CHECKBOXES); hbmpSourceOld = SelectObject(hdcSource, hbmpCheckboxes); // Заполним структуру BITMAP информацией о точечном рисунке // окошка отметки, а затем найдем левый верхний угол окошка // для установки или снятия флажка “галочки”. GetObject(hbmpCheckboxes, sizeof(BITMAP), &bmCheckbox); if (fuCheck == UNCHECK) { rc.left = 0; rc.right = (bmCheckbox.bmWidth / 4); } else { rc.left = (bmCheckbox.bmWidth / 4); rc.right = (bmCheckbox.bmWidth / 4) * 2; } rc.top = 0; rc.bottom = (bmCheckbox.bmHeight / 3); // Скопируем соответствующий точечный рисунок в целевой DC. Если // рисунок окошка отметки больше чем значок галочки по умолчанию, // используйте StretchBlt, чтобы она подогнала по размерам // значок; в противном случае она всего лишь скопирует его. if (((rc.right - rc.left) > (int) wBitmapX) || ((rc.bottom - rc.top) > (int) wBitmapY)) { StretchBlt(hdcTarget, 0, 0, wBitmapX, wBitmapY, hdcSource, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SRCCOPY); } else { BitBlt(hdcTarget, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdcSource, rc.left, rc.top, SRCCOPY); } // Выберем старый исходный и целевой точечные рисунки в исходном // и целевом DC, а затем удалим контексты устройств и // кисть фона. SelectObject(hdcSource, hbmpSourceOld); SelectObject(hdcTarget, hbrTargetOld); hbmpCheck = SelectObject(hdcTarget, hbmpTargetOld); DeleteObject(hbrBackground); DeleteObject(hdcSource); DeleteObject(hdcTarget); // Возвратим дескриптор нового значка "галочки". return hbmpCheck; } BYTE CheckOrUncheckMenuItem(BYTE bMenuItemID, HMENU hmenu) { DWORD fdwMenu; static BYTE fbAttributes; switch (bMenuItemID) { case IDM_REGULAR: // Всякий раз, когда выбран пункт меню Regular, добавим // к нему, а затем удалим галочки из // любых пунктов меню с атрибутами шрифта. CheckMenuItem(hmenu, IDM_REGULAR, MF_BYCOMMAND | MF_CHECKED); if (fbAttributes & ATTRIBMASK) { CheckMenuItem(hmenu, IDM_BOLD, MF_BYCOMMAND | MF_UNCHECKED); CheckMenuItem(hmenu, IDM_ITALIC, MF_BYCOMMAND | MF_UNCHECKED); CheckMenuItem(hmenu, IDM_ULINE, MF_BYCOMMAND | MF_UNCHECKED); } fbAttributes = IDM_REGULAR; return fbAttributes; case IDM_BOLD: case IDM_ITALIC: case IDM_ULINE: // Переключим галочку для выбранного пункта меню и // установим соответствующие флажки атрибутов шрифта. fdwMenu = GetMenuState(hmenu, (UINT) bMenuItemID, MF_BYCOMMAND); if (!(fdwMenu & MF_CHECKED)) { CheckMenuItem(hmenu, (UINT) bMenuItemID, MF_BYCOMMAND | MF_CHECKED); fbAttributes |= bMenuItemID; } else { CheckMenuItem(hmenu, (UINT) bMenuItemID, MF_BYCOMMAND | MF_UNCHECKED); fbAttributes ^= bMenuItemID; } // Если какие-либо атрибуты шрифта в настоящее время // выбраны, удалим галочку из пункта меню Regular; // если никакие атрибуты не выбраны, добавим галочку // в пункт меню Regular. if (fbAttributes & ATTRIBMASK) { CheckMenuItem(hmenu, IDM_REGULAR, MF_BYCOMMAND | MF_UNCHECKED); fbAttributes &= (BYTE) ~IDM_REGULAR; } else { CheckMenuItem(hmenu, IDM_REGULAR, MF_BYCOMMAND | MF_CHECKED); fbAttributes = IDM_REGULAR; } return fbAttributes; } } |