Страница 25 из 26
Моделирование окошек для флажка "галочкой" в меню Эта тема содержит пример, который показывает, как моделировать окошки для флажка "галочкой" в меню. Пример содержит меню Character (Символ), пункты которого позволяют пользователю устанавливать атрибуты текущего шрифта, такие как полужирный, курсивный и подчеркнутый. Когда атрибут шрифта действует, галочка отображается в окошке для флажка рядом с соответствующим пунктом меню; иначе, рядом с этим пунктом отображается пустое окошко для флажка. Пример заменяет заданный по умолчанию точечный рисунок "галочки " на два точечных рисунка (значка): точечный рисунок с установленным в окне маркером и точечным рисунком с пустым окном (без маркера). Точечный рисунок окошка для маркера отображается рядом с пунктом меню Bold (Полужирный), Italic (Курсивный) или Underline (Подчеркнутый), когда атрибут "галочки " пункта установлен в значение MF_CHECKED. Снятый маркер "галочки" или пустой точечный рисунок окошка для маркера отображается тогда, когда атрибут "галочки " установлен в значение MF_UNCHECKED. Windows предоставляет предопределенный точечный рисунок (значок), который содержит изображения, используемые для окошек с маркером "галочка" и радио-кнопок. Пример разделяет пустые окошки для "галочки" и с маркером, копирует их в два отдельных точечных рисунка (значки), а затем использует их как значки установки и снятия отметки "галочкой" для пунктов в меню 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(hwndMain, uMsg, wParam, lParam) 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(fuCheck) UINT fuCheck; // флажки CHECK или UNCHECK { COLORREF crBackground;// цвет фона HBRUSH hbrBackground;// кисть фона HBRUSH hbrTargetOld;// первоначальная кисть фона HDC hdcSource;// исходный контекст устройства HDC hdcTarget;// контекст устройства цели
HBITMAP hbmpCheckboxes;// дескриптор значка маркера BITMAP bmCheckbox;// структура для данных значка HBITMAP hbmpSourceOld;// дескриптор значка первоисточника HBITMAP hbmpTargetOld;// дескриптор первоначального целевого значка HBITMAP hbmpCheck;// дескриптор значка маркера RECT rc;// прямоугольник для точечного рисунка окна маркера DWORD dwCheckXY;// размеры значка маркера WORD wBitmapX;// ширина значка маркера WORD wBitmapY;// высота значка маркера
// Получим цвет фона меню и создадим объемную кисть с этим цветом.
crBackground = GetSysColor(COLOR_MENU); hbrBackground = CreateSolidBrush(crBackground);
// Создадим контекст устройства в памяти для значков источника и цели.
hdcSource = CreateCompatibleDC((HDC) NULL); hdcTarget = CreateCompatibleDC(hdcSource);
// Получим размер значка "галочки ", который Windows // устанавливает по умолчанию и создадим совместимый точечный // рисунок (значок) того же самого размера.
dwCheckXY = GetMenuCheckMarkDimensions(); wBitmapX = LOWORD(dwCheckXY); wBitmapY = LOWORD(dwCheckXY);
hbmpCheck = CreateCompatibleBitmap(hdcSource, wBitmapX, wBitmapY);
// Выберем кисть фона и значок в целевом значке.
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, а затем удалим DC и кисть фона.
SelectObject(hdcSource, hbmpSourceOld); SelectObject(hdcTarget, hbrTargetOld); hbmpCheck = SelectObject(hdcTarget, hbmpTargetOld);
DeleteObject(hbrBackground); DeleteObject(hdcSource); DeleteObject(hdcTarget);
// Возвратим дескриптор нового точечного рисунка "галочки ".
return hbmpCheck; }
BYTE CheckOrUncheckMenuItem(bMenuItemID, hmenu) 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; } } |