Win32 API. Меню - Моделирование окошек для флажка "галочкой" в меню
ОГЛАВЛЕНИЕ
Моделирование окошек для флажка "галочкой" в меню
Эта тема содержит пример, который показывает, как моделировать окошки для флажка "галочкой" в меню. Пример содержит меню 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;
}
}