Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

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

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

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

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; // сдвиг всего рисунка вправо-вниз подчеркивает

  • Читать дальше
  • 1
  • ...
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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