Чтение онлайн

на главную - закладки

Жанры

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

Рассмотрим основные этапы отрисовки контрола, имеющего стиль xx_OWNERDRAW.

1. Родительскому окну контрола приходит сообщение WM_MEASUREITEM, в котором передается указатель на структуру MEASUREITEMSTRUCT через параметр lParam. Обработчик сообщения должен установить значения полей itemWidth и itemHeight структуры так, чтобы они содержали ширину и высоту контрола соответственно. Если мы обработали сообщение, обработчик должен вернуть значение TRUE из оконной процедуры. Это сообщение приходит владельцу один раз при создании контрола.

2. Каждый раз при необходимости перерисовать контрол его владельцу

приходит сообщение WM_DRAWITEM. Параметр lParam сообщения содержит указатель на структуру DRAWITEMSTRUCT, подготовленную системой. В задачу данного сообщения входит предоставление контекста, в котором будет происходить отрисовка контрола. Хэндл контекста сопровождает дополнительная информация о внутреннем состоянии контрола, необходимая (возможно) для изменения его внешнего вида, а также информация о виде действия, производимого в настоящий момент с контролом. Далее мы увидим, каким образом эта информация может быть использована для изменения внешнего вида кнопки. И, опять-таки, если мы обрабатываем данное сообщение, обработчик обязан вернуть из оконной процедуры значение TRUE.

Поскольку мы реализуем, хотя и самостоятельно отрисовываемую, но все же кнопку, то было бы неплохо, если бы она имела поведение обычной кнопки – края кнопки в нормальном состоянии должны имитировать выпуклый контрол, при нажатом состоянии – вдавленный, при установленном фокусе кнопка должна иметь на себе прямоугольник, выполненный пунктирной линией, и в неактивном состоянии кнопка должна резко отличаться по цвету (либо фона, либо надписи, либо и того, и другого).

Выполняя указанные требования, мы можем подготовить четыре битмапа, реализующие внешний вид каждого из состояний кнопки, и отрисовывать в нужный момент (вот где появляется необходимость знать текущее состояние кнопки) одно из них. В этом случае мы сами полностью контролируем внешний вид кнопки в каждом из состояний. Впечатление, которое вы произведете на пользователя, будет целиком зависеть от вашего вкуса и умения создавать растровые изображения.

Что касается кода, реализующего необходимую логику работы, то его реализация может быть следующей:

BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {

 static HBITMAP hBm[BM_COUNT] = {NULL, NULL, NULL, NULL};

 ...

 case WM_DRAWITEM:

return DrawFreeStyleBtn((LPDRAWITEMSTRUCT)lParam, hBm);

 ...

}

BOOL DrawFreeStyleBtn(LPDRAWITEMSTRUCT pis, HBITMAP* phBm) {

 if (IDC_BMPBTN == pis->CtlID) {

HBITMAP hOld = NULL;

HBITMAP hbm = phBm[BM_UP];

switch(pis->itemAction) {

case ODA_DRAWENTIRE:

case ODA_SELECT:

if (pis->itemState & ODS_DISABLED) hbm = phBm[BM_DISABLE];

else if (pis->itemState & ODS_SELECTED) hbm = phBm[BM_DOWN];

break;

case ODA_FOCUS:

if (pis->hwndItem == GetFocus) hbm = phBm[BM_FOCUS];

break;

}

HDC hCompDC = CreateCompatibleDC(pis->hDC);

hOld = (HBITMAP)SelectObject(hCompDC, hbm);

BitBlt(pis->hDC, pis->rcItem.left, pis->rcItem.top,

pis->rcItem.right - pis->rcItem.left, pis->rcItem.bottom - pis->rcItem.top,

hCompDC, 0, 0, SRCCOPY);

SelectObject(pis->hDC, hOld);

DeleteDC(hCompDC);

return TRUE;

 }

 return FALSE;

}

Как

видим, ничего сложного. Код распадается на две части: в первой на основе сведений о выполняемых действиях (itemAction) и текущем состоянии кнопки (itemState) производится выбор необходимого битмапа, во второй части происходит вывод выбранного битмапа в контекст кнопки. Код обрамляется проверкой на необходимый идентификатор контрола, поскольку в рабочей программе подобных контролов может быть несколько.

Внимательный читатель готов задать вопрос о том, что в самом начале упоминались не только механизмы (реализованные, как мы выяснили, через сообщения WM_MEASUREITEM и WM_DRAWITEM), но и API?

Действительно, имеется несколько функций, облегчающих придание стандартного вида OWNERDRAW-контролам. Разработчик готовит только основной битмап для кнопки, а для отрисовки границ и состояний кнопки (неактивное и в фокусе) пользуется функциями WinAPI – DrawEdge (границы контрола – "выпуклый/вдавленный"), DrawState (состояние "активный/неактивный") и DrawFocusRect (состояние "в фокусе"). В таком случае вышеприведенный код примет вид:

BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {

 static HBITMAP hBm = NULL;

 ...

 case WM_DRAWITEM:

return DrawClassicStyleBtn((LPDRAWITEMSTRUCT)lParam, hBm);

 ...

}

void DrawClassicStyleBtn(LPDRAWITEMSTRUCT pis, HBITMAP hBm, int deflate = 4) {

 UINT uState = DSS_NORMAL;

 UINT uEdge = EDGE_RAISED;

 int x = 0, y = 0;

 BOOL bFocus = FALSE;

 RECT rFocus;

 if (IDC_BMPBTN == pis->CtlID) {

switch(pis->itemAction) {

case ODA_DRAWENTIRE:

case ODA_SELECT:

if (pis->itemState & ODS_DISABLED) {

uState = DSS_DISABLED;

} else if (pis->itemState & ODS_SELECTED) {

x += 1; // сдвиг всего рисунка вправо-вниз подчеркивает

Поделиться:
Популярные книги

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

О, мой бомж

Джема
1. Несвятая троица
Любовные романы:
современные любовные романы
5.00
рейтинг книги
О, мой бомж

Возвышение Меркурия. Книга 2

Кронос Александр
2. Меркурий
Фантастика:
фэнтези
5.00
рейтинг книги
Возвышение Меркурия. Книга 2

Вы не прошли собеседование

Олешкевич Надежда
1. Укротить миллионера
Любовные романы:
короткие любовные романы
5.00
рейтинг книги
Вы не прошли собеседование

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Эволюция мага

Лисина Александра
2. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эволюция мага

Попаданка для Дракона, или Жена любой ценой

Герр Ольга
Любовные романы:
любовно-фантастические романы
7.17
рейтинг книги
Попаданка для Дракона, или Жена любой ценой

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Сумеречный Стрелок 5

Карелин Сергей Витальевич
5. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 5

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Возвышение Меркурия. Книга 17

Кронос Александр
17. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 17

Переиграть войну! Пенталогия

Рыбаков Артем Олегович
Переиграть войну!
Фантастика:
героическая фантастика
альтернативная история
8.25
рейтинг книги
Переиграть войну! Пенталогия

Волков. Гимназия №6

Пылаев Валерий
1. Волков
Фантастика:
попаданцы
альтернативная история
аниме
7.00
рейтинг книги
Волков. Гимназия №6

Картофельное счастье попаданки

Иконникова Ольга
Фантастика:
фэнтези
5.00
рейтинг книги
Картофельное счастье попаданки