Моделирование окошек меток в меню

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

Назад в оглавление
На главную страницу

Hosted by uCoz