Пример использования пользовательских точечных рисунков "галочки"
Пример в этой теме связывает пользовательские точечные рисунки (значки) типа "галочки" с пунктами меню в двух меню. Пункты меню в первом меню определяют атрибуты символа: полужирный, курсивный и подчеркивание. Каждый пункт меню может быть или отмечен или не отмечен "галочкой". Для этих пунктов меню пример использует значки "галочки ", которые похожи на орган управления типа окошка отметки для выбранного и невыбранного состояния.
Пункты второго меню определяют параметры настройки выравнивания параграфа: слева, по центру и справа. Только один из этих пунктов меню в одно и тоже данное время может быть отмечен "галочкой". Для этих пунктов меню, пример использует значки, которые похожи на орган управления типа радио-кнопки для выбранного и невыбранного состояния.
Оконная процедура обрабатывает сообщение WM_CREATE путем вызова определяемой программой функции OnCreate. OnCreate создает четыре значка "галочки", а затем связывает их со своими соответствующими пунктами меню при помощи использования функции SetMenuItemBitmaps.
Чтобы создать каждый значок, OnCreate вызывает определяемую программой функцию CreateMenuBitmaps, устанавливая указатель на конкретную функцию рисования значка. Функция CreateMenuBitmaps создает одноцветный значок требуемого размера, выбирает его в памяти контекста устройства и стирает фон. Затем она вызывает заданную функцию рисования, чтобы закрасить в цвет активного состояния.
Имеется четыре определяемые программой функции рисования - DrawCheck, DrawUncheck, DrawRadioCheck и DrawRadioUncheck. Они рисуют прямоугольник с X (крестиком), пустой прямоугольник, эллипс, содержащий меньший затемненный эллипс и, соответственно, пустой эллипс.
Оконная процедура обрабатывает сообщение WM_DESTROY, удаляя значки типа "галочки". Она извлекает дескриптор каждый картинки при помощи использования функции GetMenuItemInfo, а затем переправляет дескриптор функции DeleteObject.
Когда пользователь выбирает пункт меню, окну владельцу отправляется сообщение WM_COMMAND. Для пунктов в меню Character, оконная процедура вызывает определяемую программой функцию CheckCharacterItem. Для пунктов в меню Paragraph, оконная процедура вызывает определяемую программой функцию CheckParagraphItem.
Каждый пункт в меню Character, независимо друг от друга, может быть выбран (отмечен) или не выбран (не отмечен) значком типа "галочки". Следовательно, CheckCharacterItem просто включает состояние отметки ("галочки") определяемого пункта меню. Сначала функция вызывает функцию GetMenuItemInfo, чтобы получить текущее состояние пункта меню. Затем она включает флажок состояния MFS_CHECKED и устанавливает новое состояние путем вызова функции SetMenuItemInfo.
В отличие от атрибутов символа, одновременно может выбираться для выравнивания только один параграф. Поэтому, функция CheckParagraphItem проверяет заданный пункт меню и удаляет галочку из всех других пунктов на меню. Чтобы сделать так, она вызывает функцию CheckMenuRadioItem.
Ниже следуют относящиеся к теме части заголовочного файла прикладной программы.
// Идентификаторы пунктов меню Character #define IDM_CHARACTER 10 #define IDM_BOLD 11 #define IDM_ITALIC 12 #define IDM_UNDERLINE 13 // Идентификаторы пунктов меню Paragraph #define IDM_PARAGRAPH 20 #define IDM_LEFT 21 #define IDM_CENTER 22 #define IDM_RIGHT 23 // Тип указателя функций для функций рисования typedef VOID (WINAPI * DRAWFUNC)(HDC hdc, SIZE size);
|
Ниже перечислены относящиеся к примеру части оконной процедуры приложения и связанных с ним функций.
LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch (uMsg) { case WM_CREATE: if (!OnCreate(hwnd)) return -1; break; case WM_DESTROY: OnDestroy(hwnd); PostQuitMessage(0); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_BOLD: case IDM_ITALIC: case IDM_UNDERLINE: CheckCharacterItem(hwnd, LOWORD(wParam)); break; case IDM_LEFT: case IDM_CENTER: case IDM_RIGHT: CheckParagraphItem(hwnd, LOWORD(wParam)); break; // Здесь обработаем другие команды. } break; // Здесь обработаем другие сообщения. default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } VOID WINAPI CheckCharacterItem(HWND hwnd, UINT uID) { HMENU hmenuBar = GetMenu(hwnd); HMENU hmenuPopup; MENUITEMINFO mii; // Получим дескриптор меню Character. mii.fMask = MIIM_SUBMENU; // информация, которую получим GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii); hmenuPopup = mii.hSubMenu; // Получим состояние заданного пункта меню. mii.fMask = MIIM_STATE; // информация, которую получим GetMenuItemInfo(hmenuPopup, uID, FALSE, &mii); // Переключим состояние выбора. mii.fState ^= MFS_CHECKED; SetMenuItemInfo(hmenuPopup, uID, FALSE, &mii); } VOID WINAPI CheckParagraphItem(HWND hwnd, UINT uID) { HMENU hmenuBar = GetMenu(hwnd); HMENU hmenuPopup; MENUITEMINFO mii; // Получим дескриптор меню Paragraph. mii.fMask = MIIM_SUBMENU; // информация, которую получим GetMenuItemInfo(hmenuBar, IDM_PARAGRAPH, FALSE, &mii); hmenuPopup = mii.hSubMenu; // Установим в состояние выбора заданный пункт и сбросим его // во всех других пунктах. CheckMenuRadioItem( hmenuPopup, // дескриптор меню IDM_LEFT, // первый пункт в ряду IDM_RIGHT, // последний пункт в ряду uID, // пункт, который выбран MF_BYCOMMAND // IDs (идентификаторы), без позиции ); } BOOL WINAPI OnCreate(HWND hwnd) { HMENU hmenuBar = GetMenu(hwnd); HMENU hmenuPopup; MENUITEMINFO mii; UINT uID; HBITMAP hbmChecked; HBITMAP hbmUnchecked; // Получим дескриптор меню Character. mii.fMask = MIIM_SUBMENU; // информация, которую получим GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii); hmenuPopup = mii.hSubMenu; // Создадим значки выбора и не выбора. hbmChecked = CreateMenuBitmap(DrawCheck); hbmUnchecked = CreateMenuBitmap(DrawUncheck); // Установим значок "галочки" в каждом пункте меню. for (uID = IDM_BOLD; uID <= IDM_UNDERLINE; uID++) { SetMenuItemBitmaps(hmenuPopup, uID, MF_BYCOMMAND, hbmUnchecked, hbmChecked); } // Получим дескриптор выскакивающего меню Paragraph. mii.fMask = MIIM_SUBMENU; // информация, которую получим GetMenuItemInfo(hmenuBar, IDM_PARAGRAPH, FALSE, &mii); hmenuPopup = mii.hSubMenu; // Создадим значки выбора и не выбора. hbmChecked = CreateMenuBitmap(DrawRadioCheck); hbmUnchecked = CreateMenuBitmap(DrawRadioUncheck); // Установим значок "галочки" в каждом пункте меню. for (uID = IDM_LEFT; uID <= IDM_RIGHT; uID++) { SetMenuItemBitmaps(hmenuPopup, uID, MF_BYCOMMAND, hbmUnchecked, hbmChecked); } // Сначала отметим IDM_LEFT пункт параграфа. CheckMenuRadioItem(hmenuPopup, IDM_LEFT, IDM_RIGHT, IDM_LEFT, MF_BYCOMMAND); return TRUE; } HBITMAP WINAPI CreateMenuBitmap(DRAWFUNC lpfnDraw) { // Создадим совместимый DC с DC рабочего стола окна. HWND hwndDesktop = GetDesktopWindow(); HDC hdcDesktop = GetDC(hwndDesktop); HDC hdcMem = CreateCompatibleDC(hdcDesktop); // Определим требуемый размер значка. SIZE size = { GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK) }; // Создадим черно-белый значок и выберем его. HBITMAP hbm = CreateBitmap(size.cx, size.cy, 1, 1, NULL); HBITMAP hbmOld = SelectObject(hdcMem, hbm); // Очистим фон и вызовем рисующую функцию. PatBlt(hdcMem, 0, 0, size.cx, size.cy, WHITENESS); (*lpfnDraw)(hdcMem, size); // Очистим. SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); ReleaseDC(hwndDesktop, hdcDesktop); return hbm; } VOID WINAPI DrawCheck(HDC hdc, SIZE size) { HBRUSH hbrOld; hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH)); Rectangle(hdc, 0, 0, size.cx, size.cy); MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, size.cx, size.cy); MoveToEx(hdc, 0, size.cy - 1, NULL); LineTo(hdc, size.cx - 1, 0); SelectObject(hdc, hbrOld); } VOID WINAPI DrawUncheck(HDC hdc, SIZE size) { HBRUSH hbrOld; hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH)); Rectangle(hdc, 0, 0, size.cx, size.cy); SelectObject(hdc, hbrOld); } VOID WINAPI DrawRadioCheck(HDC hdc, SIZE size) { HBRUSH hbrOld; hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH)); Ellipse(hdc, 0, 0, size.cx, size.cy); SelectObject(hdc, GetStockObject(BLACK_BRUSH)); Ellipse(hdc, 2, 2, size.cx - 2, size.cy - 2); SelectObject(hdc, hbrOld); } VOID WINAPI DrawRadioUncheck(HDC hdc, SIZE size) { HBRUSH hbrOld; hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH)); Ellipse(hdc, 0, 0, size.cx, size.cy); SelectObject(hdc, hbrOld); } VOID WINAPI OnDestroy(HWND hwnd) { HMENU hmenuBar = GetMenu(hwnd); HMENU hmenuPopup; MENUITEMINFO mii; // Получим дескриптор меню Character. mii.fMask = MIIM_SUBMENU; // информация, которую получаем GetMenuItemInfo(hmenuBar, IDM_CHARACTER, FALSE, &mii); hmenuPopup = mii.hSubMenu; // Получим значки "галочек" и удалим их. mii.fMask = MIIM_CHECKMARKS; GetMenuItemInfo(hmenuPopup, IDM_BOLD, FALSE, &mii); DeleteObject(mii.hbmpChecked); DeleteObject(mii.hbmpUnchecked); // Получим дескриптор меню Paragraph. mii.fMask = MIIM_SUBMENU; // информация, которую получаем GetMenuItemInfo(hmenuBar, IDM_PARAGRAPH, FALSE, &mii); hmenuPopup = mii.hSubMenu; // Получим значки "галочек" и удалим их. mii.fMask = MIIM_CHECKMARKS; GetMenuItemInfo(hmenuPopup, IDM_LEFT, FALSE, &mii); DeleteObject(mii.hbmpChecked); DeleteObject(mii.hbmpUnchecked); }
|