TN014. Пользовательские элементы управления
В этой заметке описывается поддержка MFC для пользовательских и саморисовки элементов управления. Он также описывает динамическое подклассирование и описывает связь между объектами CWnd и HWND
s.
Пример приложения MFC CTRLTEST показывает, как использовать множество пользовательских элементов управления. См. исходный код для примера CTRLTEST и справки по сети MFC.
Элементы управления и меню владельца
Windows обеспечивает поддержку элементов управления и меню владельца с помощью сообщений Windows. Родительское окно любого элемента управления или меню получает эти сообщения и вызывает функции в ответ. Эти функции можно переопределить, чтобы настроить внешний вид и поведение элемента управления или меню владельца.
MFC напрямую поддерживает рисование владельца со следующими функциями:
Эти функции можно переопределить в CWnd
производном классе для реализации пользовательского поведения рисования.
Этот подход не приводит к повторному использовании кода. Если у вас есть два аналогичных элемента управления в двух разных CWnd
классах, необходимо реализовать поведение пользовательского элемента управления в двух расположениях. Архитектура саморисовки, поддерживаемая MFC, решает эту проблему.
Самостоятельное рисование элементов управления и меню
MFC предоставляет реализацию по умолчанию (в CWnd
классах CMenu ) для стандартных сообщений нарисовки владельцев. Эта реализация по умолчанию декодирует параметры рисования владельца и делегирует сообщения, нарисованные владельцем, элементам управления или меню. Это называется самостоятельным рисованием, так как код рисования находится в классе элемента управления или меню, а не в окне владельца.
С помощью элементов управления самообслуживания можно создавать повторно используемые классы элементов управления, использующие семантику рисования владельца для отображения элемента управления. Код для рисования элемента управления находится в классе элемента управления, а не в родительском. Это объектно-ориентированный подход к программированию пользовательского элемента управления. Добавьте следующий список функций в собственные классы рисования:
Для кнопок самостоятельного рисования:
CButton:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this button
Для меню самостоятельного рисования:
CMenu:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this menu CMenu:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this menu
Для полей списка самостоятельного рисования:
CListBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this list box CListBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this list box CListBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this list box if LBS_SORT CListBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this list box
Для саморисовки полей со списком:
CComboBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this combo box CComboBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this combo box CComboBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this combo box if CBS_SORT CComboBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this combo box
Дополнительные сведения о структурах рисования владельца (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT и DELETEITEMSTRUCT) см. в документации по MFC для CWnd::OnDrawItem
, CWnd::OnMeasureItem
CWnd::OnCompareItem
и CWnd::OnDeleteItem
соответственно.
Использование элементов управления и меню самостоятельного рисования
Для самостоятельного рисования меню необходимо переопределить как методы, так OnMeasureItem
и OnDrawItem
методы.
Для саморисовки списков и полей со списком OnMeasureItem
необходимо переопределить и OnDrawItem
. Необходимо указать стиль LBS_OWNERDRAWVARIABLE для полей списка или CBS_OWNERDRAWVARIABLE стиля для полей со списком в шаблоне диалога. Стиль OWNERDRAWFIXED не будет работать с элементами самостоятельного рисования, так как фиксированная высота элемента определяется перед присоединением элементов управления самостоятельной рисования к списку. (Методы можно использоватьCListBox::SetItemHeight и CComboBox::SetItemHeight, чтобы преодолеть это ограничение.)
Переключение на стиль OWNERDRAWVARIABLE приведет к применению к элементу управления стиля NOINTEGRALHEIGHT. Так как элемент управления не может вычислить целочисленную высоту с элементами переменной размера, стиль ПО умолчанию ЦЕЛОЧИСЛЕННОГО ЭЛЕМЕНТА не учитывается, и элемент управления всегда NOINTEGRALHEIGHT. Если элементы имеют фиксированную высоту, можно предотвратить рисование частичных элементов, указав размер элемента управления для целочисленного умножения размера элемента.
Для самостоятельного рисования списков и полей со списком с помощью стиля LBS_SORT или CBS_SORT необходимо переопределить OnCompareItem
метод.
Для саморисовки списков OnDeleteItem
и полей со списком обычно не переопределяется. Можно переопределить OnDeleteItem
, если вы хотите выполнить любую специальную обработку. Один из случаев, когда это может быть применимо, заключается в том, что при хранении дополнительной памяти или других ресурсов с каждым полем списка или элементом поля со списком.
Примеры элементов управления и меню самостоятельного рисования
В примере CTRLTEST для MFC приведены примеры меню самостоятельного рисования и поле списка самостоятельного рисования.
Наиболее типичным примером самостоятельной кнопки рисования является кнопка растрового рисунка. Кнопка растрового изображения — это кнопка, показывающая один, два или три растровых изображения для разных состояний. Пример этого представлен в классе MFC CBitmapButton.
Динамическое подклассирование
Иногда требуется изменить функциональные возможности уже существующего объекта. Предыдущие примеры требуют настройки элементов управления до их создания. Динамическое подклассирование позволяет настроить элемент управления, который уже создан.
Подкласс — это термин Windows для замены WndProc окна настроенным WndProc
и вызовом старой WndProc
функции по умолчанию.
Это не следует путать с производным классом C++. Для уточнения базовый класс И производный класс C++ аналогичен суперклассу и подклассу в объектной модели Windows. Производные C++ с подклассами MFC и Windows функционально похожи, за исключением того, что C++ не поддерживает динамическое подклассирование.
Класс CWnd
обеспечивает соединение между объектом C++ (производным отCWnd
) и объектом окна Windows (известным как ).HWND
Существует три распространенных способа:
CWnd
HWND
создает объект . Поведение в производном классе можно изменить, создав класс, производный отCWnd
. СоздаетсяHWND
при вызове приложения CWnd::Create.Приложение присоединяет приложение
CWnd
к существующемуHWND
. Поведение существующего окна не изменяется. Это случай делегирования и это возможно путем вызова CWnd::Attach к псевдониму существующегоHWND
CWnd
объекта.CWnd
присоединен к существующемуHWND
и можно изменить поведение в производном классе. Это называется динамическим подклассом, так как мы изменяем поведение и, следовательно, класс объекта Windows во время выполнения.
Динамическое подклассирование можно достичь с помощью методов CWnd::SubclassWindow иCWnd::SubclassDlgItem.
Обе подпрограммы присоединяют CWnd
объект к существующему HWND
объекту. SubclassWindow
принимает напрямую HWND
. SubclassDlgItem
является вспомогательной функцией, которая принимает идентификатор элемента управления и родительское окно. SubclassDlgItem
предназначен для присоединения объектов C++ к элементам управления диалогом, созданным на основе шаблона диалогового окна.
Пример CTRLTEST см. в нескольких примерах использования SubclassWindow
и SubclassDlgItem
.
См. также
Технические примечания по номеру
Технические примечания по категории