Jenter Алекс
Шрифт:
Обработчики сообщений реализованы примерно одинаково. Они распаковывают параметры сообщений и передают управление специальным функциям, которые и выполняют основную работу. Вот прототипы этих функций.
Именно эти функции вы можете переопределить в производном классе, чтобы реализовать отрисовку контрола. Это удобнее, чем вручную перехватывать сообщения и вспоминать, каким образом в их параметрах запакована информация. Обратите внимание, что класс COwnerDraw<> содержит стандартную реализацию этих функций. Функции DrawItem, CompareItem и DeleteItem ничего полезного не делают, зато функция MeasureItem возвращает размер пункта меню в зависимости от настроек системы и размер элемента в списке в зависимости от размера стандартного системного фонта, который используется в диалогах и меню. Если такое поведение вас не устраивает, измените его на любое другое.
Рассмотрим пример использования класса COwnerDraw<> для рисования нестандартной кнопки.
Механизм пользовательского рисования (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<>, который мы рассмотрели выше. Его реализация выглядит так.