Поделиться через


Создание подклассов элементов управления при помощи управляемой процедуры окна

Обновлен: Ноябрь 2007

Платформа .NET Compact Framework предоставляет возможность вызова управляемого кода из машинного кода при помощи делегата обратного вызова. Путем создания подклассов управляемого элемента управления для получения обратного вызова от соответствующего неуправляемого элемента управления можно создавать элементы управления с функциональными возможностями, недоступными в .NET Compact Framework напрямую.

Это дополнительный раздел для разработчиков, знакомых с программированием в Windows и созданием подклассов элемента управления. Чтобы создать подкласс элемента управления, необходимо знать внутреннее устройство неуправляемых элементов управления и то, как они соответствуют функциональным возможностям, которые необходимо предоставить в качестве дополнения к управляемому элементу управления. Необходимо знать, какие сообщения Windows нужно отслеживать, и какие неуправляемые функции Windows Embedded CE следует вызывать для обеспечения необходимых функциональных возможностей.

В этом разделе описывается создание подклассов элементов управления TreeView и Button, а в следующем разделе предоставляются примеры кода и инструкции по построению приложений.

Практическое руководство

Демонстрирует

Практическое руководство. Реализация подкласса TreeView с помощью функций обратного вызова на машинном коде

Создание подклассов элемента управления TreeView с целью реализации события NodeMouseClick. Платформа .NET Compact Framework не поддерживает этот метод напрямую из-за необходимости ограничения размера платформы ввиду нехватки ресурсов.

Практическое руководство. Реализация подкласса кнопки с помощью функций обратного вызова на машинном коде

Создание подкласса элемента управления Button для отображения цветной градиентной заливки.

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

Обе программы, создающие подклассы, включают класс WndProcHooker и вспомогательный класс неуправляемых структур Win32, объявления вызовов неуправляемого кода и делегат WndProc. Листинги кода см. в разделах Пошаговое руководство. Использование класса для подключения процедур Windows и Практическое руководство. Использование вспомогательного класса для вызова неуправляемого кода.

Класс WndProcHooker

Класс WndProcHooker предоставляет неуправляемому элементу управления или окну возможность выполнить обратный вызов к управляемому коду при получении сообщения Windows, предназначенного для этого элемента управления. Это достигается путем замены процедуры окна неуправляемого элемента управления (WndProc) универсальной процедурой окна, WindowProc, которая определяет, находится ли этот элемент управления в списке элементов управления, связанных с вызываемыми методами обратного вызова, которые необходимо вызывать. Если это так, то элемент управления считается обрабатываемым.

Если элемент управления связан с обработчиком, то процедура WindowProc определяет, должен ли элемент управления реагировать на конкретное сообщение Windows. За сопоставление сообщений Windows с делегатом WndProcCallback, который вызывает управляемый метод, содержащий необходимые функциональные возможности, отвечает схема сообщений. Если схема сообщений содержит сообщение, то делегат WndProcCallback вызывает код, используя параметры сообщения, переданные процедуре WindowProc.

Связывание элементов управления с обработчиками

Метод HookWndProc связывает дескриптор элемента управления со схемой сообщений, которая должна использоваться универсальной процедурой окна WindowProc. Это называется связыванием элемента управления с обработчиком.

Метод HookWndProc определяет, не были ли элемент управления связан с обработчиком ранее. Если это не так, то он создает объект HookedProcInformation для этого элемента управления. Этот объект содержит ссылки на элемент управления и на схему сообщений. Если дескриптор элемента управления уже был создан, то он связывает окно с обработчиком, создавая указатель на исходную процедуру окна с целью последующего восстановления. Если дескриптор не был создан, то он будет связан с обработчиком методом ctrl_HandleCreated, который обрабатывает событие HandleCreated.

После этого метод HookWndProc добавляет объект HookedProcInformation к одной из двух универсальных коллекций-словарей:

  • Словарь hwindDict содержит глобальный список всех связанных оконных дескрипторов. Ключом является hwnd. В этот словарь входят элементы управления, для которых были созданы дескрипторы. Процедура WindowProc проверяет элементы управления в этом словаре в случае появления любых связанных сообщений.

  • Словарь ctlDict содержит элементы управления, для которых не созданы дескрипторы. При вызове метода ctrl_HandleCreated элемент управления перемещается в словарь hwndDict.

Отмена связывания элементов управления с обработчиками

Метод UnhookWndProc предоставляет два способа отмены связывания элемента управления:

  • Удаление сообщения из схемы сообщений для элемента управления, при котором элемент управления остается в словаре связанных окон hwndDict. Этот метод также восстанавливает исходную процедуру окна для элемента управления, используя указатель, сохраненный в объекте HookedProcInformation.

  • Удаление элемента управления из словаря привязанных элементов управления, hwndDict, с удалением его дескриптора и помещением его в словарь ctrlDict или же полным уничтожением элемента управления. Этот метод также восстанавливает исходную процедуру окна элемента управления, используя дескриптор, сохраненный в объекте HookedProcInformation.

Создание подкласса для элемента управления TreeView

Класс TreeViewBonus из программы-примера, представленный в разделе Практическое руководство. Реализация подкласса TreeView с помощью функций обратного вызова на машинном коде, расширяет элемент управления TreeView, включая событие NodeMouseClick, недоступное в .NET Compact Framework напрямую.

Событие NodeMouseClick получается путем добавления сообщения WM_NOTIFY в схему сообщений для элемента управления с помощью класса WndProcHooker. Управляемый метод обратного вызова WM_Notify_Handler вызывает неуправляемую функцию GetMessagePos для получения координат указателя мыши в момент отправки сообщений Windows.

Обратите внимание, что эти координаты задаются относительно видимой клиентской области экрана, а не относительно элемента управления TreeView. Класс TreeViewBonus преобразует экранные координаты в клиентские координаты при помощи метода PointToClient элемента управления. Затем эти клиентские координаты пересылаются вместе с сообщением TVM_HITTEST, чтобы определить, был ли выполнен и где был выполнен щелчок объекта TreeViewBonus.

Класс TreeViewBonus содержит код для получения координат, заданных относительно элемента управления при помощи сообщения TVM_HITTEST неуправляемого элемента управления.

Если был выполнен щелчок одного из узлов дерева, неуправляемая структура TVHITTESTINFO будет содержать дескриптор соответствующего узла. Последним шагом является рекурсивное прохождение управляемых узлов TreeView, выполняемое методом FindTreeNodeFromHandle с целью поиска необходимого дескриптора и инициирования события NodeMouseClick. Класс TreeNodeMouseClickEventArgs содержит следующие данные:

  • узел, который был щелкнут;

  • кнопка, которая была нажата;

  • число щелчков, изначально равное 1;

  • координата места выполнения щелчка по оси X;

  • координата места выполнения щелчка по оси Y.

Класс TreeViewBonus связывает родительский элемент неуправляемого элемента управления иерархического представления с управляемой процедурой окна в соответствии порядком действий класса WndProcHooker. Он реагирует на событие OnParentChanged, связывая родительский элемент управления с обработчиком, тем самым учитывая вероятность того, что TreeView перемещается к новому родительскому элементу — например, от Form к Panel.

Создание подкласса для элемента управления Button

Классы GradientFilledButton и GradientFill, описанные в разделе Практическое руководство. Реализация подкласса кнопки с помощью функций обратного вызова на машинном коде, расширяют возможности элемента управления Button путем отображения двухцветной градиентной заливки. Эта программа в основном предназначена для демонстрации способов создания подклассов. Тем не менее, более простой способ отображения градиентной заливки на кнопке заключается в создании пользовательского элемента управления, производного от класса Control, в соответствии с разделом Пошаговое руководство. Отображение градиентной заливки.

Конструктор класса GradientFilledButton создает экземпляры класса WndProcHooker для сопоставления сообщений Windows с управляемыми обратными вызовами. Эти методы обратного вызова рисуют кнопку в соответствующем состоянии, зависящем от сообщения Windows и состояния свойства Capture элемента управления. В следующей таблице перечисляются сопоставляемые сообщения Windows и соответствующие им обратные вызовы:

Сообщение Windows

Управляемый метод обратного вызова и его описание

WM_KEYDOWN

WM_KeyDown_Handler — Перерисовывает кнопку в нажатом состоянии, если нажата клавиша ПРОБЕЛ или ВВОД (или ДЕЙСТВИЕ).

WM_KEYUP

WM_KeyUp_Handler — Перерисовывает кнопку в отпущенном состоянии и инициирует событие Click, если нажата клавиша ПРОБЕЛ или ВВОД (ДЕЙСТВИЕ).

WM_LBUTTONDOWN

WM_LeftButtonDown_Hander — Перерисовывает кнопку в нажатом состоянии и задает для свойства мыши Capture элемента управления значение true.

WM_LBUTTONUP

WM_LButtonUp_Handler — Перерисовывает кнопку в отпущенном состоянии, инициирует событие MouseUp, если указатель отпущен в пределах клиентской области элемента управления, и задает для свойства мыши Capture элемента управления значение false.

WM_MOUSEMOVE

WM_MouseMove_Handler — Перерисовывает кнопку, если до этого она была нажата, и присваивает свойству Capture значение true.

WM_PAINT

WM_Paint_Handler — Перерисовывает кнопку в необходимом состоянии.

Эти управляемые методы обратного вызова используют метод DrawButton для отрисовки кнопки в необходимом состоянии. Этот метод имеет две перегрузки для рисования кнопки либо в окне, как делалось в этом примере, либо на объекте Graphics. Обе перегрузки принимают логическое значение, равное true, если кнопка нажата.

Класс GradientFilledButton использует класс GradientFill для выполнения вызовов неуправляемого кода для заливки. Класс GradientFill предоставляет свойства для установки начального и конечного цветов и для задания направления заливки (слева направо или сверху вниз).

См. также

Задачи

Пошаговое руководство. Использование класса для подключения процедур Windows

Практическое руководство. Использование вспомогательного класса для вызова неуправляемого кода

Практическое руководство. Реализация подкласса TreeView с помощью функций обратного вызова на машинном коде

Пошаговое руководство. Отображение градиентной заливки

Основные понятия

Разделы руководства по платформе .NET Compact Framework

Другие ресурсы

Взаимодействие в платформе .NET Compact Framework