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


Windows Forms и архитектура ввода взаимодействия WPF

Взаимодействие между WPF и Windows Forms требует, чтобы обе технологии имели соответствующую обработку ввода с клавиатуры. В этом разделе описывается, как эти технологии реализуют обработку клавиатуры и сообщений для обеспечения плавного взаимодействия в гибридных приложениях.

В этом разделе содержатся следующие подразделы:

  • Безрежимные формы и диалоговые окна

  • Обработка клавиатуры и сообщений WindowsFormsHost

  • Обработка клавиатуры и сообщений ElementHost

Безрежимные формы и диалоговые окна

Чтобы открыть безрежимную форму или диалоговое окно из приложения на основе WPF, вызовите метод EnableWindowsFormsInterop элемента WindowsFormsHost.

Чтобы открыть безрежимную страницу WPF приложения на основе Windows Forms, вызовите метод EnableModelessKeyboardInterop элемента ElementHost.

Обработка клавиатуры и сообщений WindowsFormsHost

При размещении в приложении на основе WPF обработка клавиатуры и сообщений Windows Forms включает в себя следующие составляющие.

  • Класс WindowsFormsHost получает сообщения из цикла сообщений WPF, который реализуется в классе ComponentDispatcher.

  • Класс WindowsFormsHost создает заменяющий цикл сообщений Windows Forms, чтобы обеспечить надлежащую обработку клавиатуры Windows Forms.

  • В классе WindowsFormsHost реализуется интерфейс IKeyboardInputSink для координации управления фокусом с помощью WPF.

  • Элементы управления WindowsFormsHost регистрируются и запускают собственные циклы сообщений.

В следующих разделах эти этапы процесса описываются более подробно.

Получение сообщений из цикла сообщений WPF

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

Реализация взаимодействия обрабатывает событие ComponentDispatcher.ThreadFilterMessage, которое позволяет элементам управления Windows Forms обрабатывать сообщения до элементов управления WPF.

Заменяющий цикл сообщений Windows Forms

По умолчанию класс System.Windows.Forms.Application содержит основной цикл сообщений для приложений Windows Forms. Во время взаимодействия цикл сообщений Windows Forms не обрабатывает сообщения. Поэтому эту логику необходимо воспроизвести. Обработчик события ComponentDispatcher.ThreadFilterMessage выполняет следующие действия.

  1. Фильтрует сообщение с помощью интерфейса IMessageFilter.

  2. Вызывает метод Control.PreProcessMessage.

  3. Преобразует и отправляет сообщение, если это необходимо.

  4. Передает сообщение в размещающий элемент управления, если его не обрабатывают другие элементы управления.

IKeyboardInputSink Implementation

Заменяющий цикл сообщений обрабатывает управление клавиатурой. Таким образом, метод IKeyboardInputSink.TabInto является единственным членом IKeyboardInputSink, требующим реализации в классе WindowsFormsHost.

По умолчанию класс HwndHost возвращает false для своей реализации метода IKeyboardInputSink.TabInto. Это предотвращает переход табулирования из элемента управления WPF в элемент управления Windows Forms.

Реализация WindowsFormsHost метода IKeyboardInputSink.TabInto выполняет следующие действия.

  1. Находит первый или последний элемент управления Windows Forms, который содержится элементом управления WindowsFormsHost, и может получать фокус. Осуществляет выбор элемента управления, который зависит от данных обхода.

  2. Задает фокус для элемента управления и возвращает значение true.

  3. Если нет элементов управления, которые могут получать фокус, возвращает false.

Регистрация класса WindowsFormsHost

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

Во время регистрации WindowsFormsHost элемент управления проверяет цикл сообщений. Если цикл сообщений не запущен, создается обработчик событий ComponentDispatcher.ThreadFilterMessage. Цикл сообщений считается запущенным при присоединении обработчика событий ComponentDispatcher.ThreadFilterMessage.

При уничтожении дескриптора окна элемент управления WindowsFormsHost удаляет регистрацию.

Обработка клавиатуры и сообщений ElementHost

При размещении в приложении на основе Windows Forms обработка клавиатуры и сообщений WPF включает в себя следующие составляющие.

  • Реализации интерфейсов HwndSource, IKeyboardInputSink и IKeyboardInputSite.

  • Табулирование и клавиши со стрелками.

  • Командные клавиши и кнопки диалоговых окон.

  • Обработка акселераторов Windows Forms.

В следующих разделах эти составляющие обсуждаются более подробно.

Реализации интерфейсов

В Windows Forms сообщения клавиатуры направляются в дескриптор окна элемента управления, который имеет фокус. В элементе управления ElementHost эти сообщения направляются в размещенный элемент. Для этого элемент управления ElementHost предоставляет экземпляр источника дескриптора HwndSource. Если элемент управления ElementHost имеет фокус, то экземпляр HwndSource направляет большую часть ввода с клавиатуры, чтобы его можно было обработать классом WPF InputManager.

В классе HwndSource реализованы интерфейсы IKeyboardInputSink и IKeyboardInputSite.

Взаимодействие с клавиатурой полагается на реализацию метода OnNoMoreTabStops для обработки ввода клавиши TAB и клавиш со стрелками, которые перемещают фокус между размещенными элементами.

Табулирование и клавиши со стрелками

Логика выбора Windows Forms сопоставляется с методами IKeyboardInputSink.TabInto и OnNoMoreTabStops реализации навигации с помощью клавиши TAB и клавиш со стрелками. Переопределение метода Select позволяет выполнить это сопоставление.

Командные клавиши и кнопки диалоговых окон

Чтобы предоставить WPF возможность обрабатывать командные клавиши и кнопки диалоговых окон до Windows Forms, предварительная обработка команд Windows Forms присоединяется к методу TranslateAccelerator. Переопределение метода Control.ProcessCmdKey соединяет две технологии.

С помощью метода TranslateAccelerator размещенные элементы могут обрабатывать любое сообщение, поступающее от клавиш, например WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN или WM_SYSKEYUP, включая сообщения командных клавиш, таких, как TAB, ВВОД, ESC и клавиши со стрелками. Если сообщение клавиши не обрабатывается, оно направляется для обработки вверх по иерархии предков Windows Forms.

Обработка ускорителей

Обработку ускорителей Windows Forms необходимо присоединить к классу WPF AccessKeyManager, чтобы она происходила корректно. Кроме того, все сообщения WM_CHAR должны быть правильно перенаправлены в размещенные элементы.

Так как реализация по умолчанию HwndSource метода TranslateChar возвращает false, сообщения WM_CHAR обрабатываются с помощью следующей логики.

  • Метод Control.IsInputChar переопределяется, чтобы убедиться, что все WM_CHAR сообщения перенаправляются в размещенные элементы.

  • Если нажата клавиша ALT, сообщение меняется на WM_SYSCHAR. Windows Forms не выполняет предварительную обработку этого сообщения с помощью метода IsInputChar. Таким образом, метод ProcessMnemonic переопределяется, чтобы отправить запрос менеджеру WPF AccessKeyManager для возврата зарегистрированного ускорителя. Если зарегистрированный ускоритель обнаружен, AccessKeyManager обрабатывает его.

  • Если клавиша ALT не нажата, классу WPF InputManager передаются необработанные входные данные. Если входные данные являются ускорителем, они обрабатываются AccessKeyManager. Событие PostProcessInput вызывается для сообщений WM_CHAR, которые не были обработаны.

Когда пользователь нажимает клавишу ALT, визуальные подсказки акселератора отображаются во всей форме. Для поддержки этого поведения все элементы управления ElementHost активной формы получают сообщение WM_SYSKEYDOWN независимо от того, какой элемент управления имеет фокус.

Сообщения отправляются только элементам управления ElementHost на активной форме.

См. также