Win32 API. Меню
Страница 25. Моделирование окошек для флажка \"галочкой\" в меню



Моделирование окошек для флажка "галочкой" в меню

Эта тема содержит пример, который показывает, как моделировать окошки для флажка "галочкой" в меню. Пример содержит меню 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;
}
}
 
« Предыдущая статья   Следующая статья »