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

Jenter Алекс

Шрифт:

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

void DrawItem(LPDRAWITEMSTRUCT);

void MeasureItem(LPMEASUREITEMSTRUCT);

int CompareItem(LPCOMPAREITEMSTRUCT);

void DeleteItem(LPDELETEITEMSTRUCT);

Именно эти функции вы можете переопределить в производном классе, чтобы реализовать отрисовку контрола. Это удобнее, чем вручную перехватывать сообщения и вспоминать, каким образом в их параметрах запакована информация. Обратите внимание, что класс COwnerDraw<> содержит стандартную реализацию этих функций. Функции DrawItem, CompareItem и DeleteItem ничего полезного не делают, зато функция MeasureItem возвращает размер пункта меню в зависимости от настроек системы и размер элемента в списке в зависимости от размера стандартного системного фонта, который используется в диалогах и меню. Если такое поведение вас не устраивает, измените его на любое другое.

Рассмотрим пример использования класса COwnerDraw<> для рисования нестандартной кнопки.

class CButtonDemoDlg : public CSimpleDialog<IDD_BUTTON_DIALOG>, public COwnerDraw<CButtonDemoDlg>, ... {

private:

 HICON m_hIcon1, m_hIcon2;

 ...

public:

 BEGIN_MSG_MAP(CButtonDemoDlg)

...

CHAIN_MSG_MAP(COwnerDraw<CButtonDemoDlg>)

 END_MSG_MAP

 void DrawItem(LPDRAWITEMSTRUCT pDIS) {

if ((pDIS->itemState & ODS_SELECTED) != 0) {

// Кнопка нажата

DrawIcon(pDIS->hDC, 0, 0, m_hIcon2);

} else {

// Кнопка отпущена

DrawIcon(pDIS->hDC, 0, 0, m_hIcon1);

}

 }

};

Класс CCustomDraw<>: пользовательское рисование в стиле WTL

Механизм пользовательского рисования (custom draw) иногда путают с owner draw. Он предназначен для той же цели – изменить внешний вид контролов. Однако он появился несколько позже (вместе с набором общих контролов из библиотеки comctl32.dll) и используется для более новых контролов (таких, как ListView и TreeView).

Пользовательское рисование работает следующим образом. Когда контрол перерисовывается, он посылает родительскому окну одно или несколько уведомлений NM_CUSTOMDRAW, упакованных в сообщение WM_NOTIFY. Каждое уведомление соответствует некоторой фазе перерисовки (до/после рисования контрола целиком или отдельного элемента и т. д.). Фазу можно определить по полю dwDrawStage структуры NMCUSTOMDRAW, указатель на которую передаётся вместе с уведомлением. В зависимости от фазы родительское окно может выполнить некоторые действия (например, изменить цвет или фонт отдельного элемента списка). Подробности можно найти в MSDN (см. статью "Customizing a Control's Appearance Using Custom Draw").

В WTL есть класс CCustomDraw<> (описан в файле atlctls.h), который помогает вам перехватывать уведомление NM_CUSTOMDRAW и распаковывать его параметры. Он очень похож на класс COwnerDraw<>, который мы рассмотрели выше. Его реализация выглядит так.

template <class T> class CCustomDraw {

public:

 // Message map and handlers

 BEGIN_MSG_MAP(CCustomDraw<T>)

NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)

 ALT_MSG_MAP(1)

REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)

 END_MSG_MAP

 // message handler

 LRESULT OnCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) {

T* pT = static_cast<T*>(this);

pT->SetMsgHandled(TRUE);

LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW)pnmh;

DWORD dwRet = 0;

switch(lpNMCustomDraw->dwDrawStage) {

case CDDS_PREPAINT:

dwRet = pT->OnPrePaint(idCtrl, lpNMCustomDraw);

break;

case CDDS_POSTPAINT:

dwRet = pT->OnPostPaint(idCtrl, lpNMCustomDraw);

break;

// Остальные фазы отрисовки

// ...

default:

pT->SetMsgHandled(FALSE);

break;

}

bHandled = pT->IsMsgHandled;

return dwRet;

 }

 // Overrideables

 DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) {

return CDRF_DODEFAULT;

 }

 DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) {

  • Читать дальше
  • 1
  • ...
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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