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


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

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

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

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

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

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

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

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

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

Клавиатура 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

Суррогатный цикл сообщений обрабатывает управление клавиатурой. Поэтому метод 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.

  • Клавиши Tab и стрелки.

  • Клавиши командной строки и диалоговые окна.

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

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

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

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

Класс HwndSource реализует интерфейсы IKeyboardInputSink и IKeyboardInputSite.

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

Управление клавишами Tab и стрелками

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

Клавиши командной строки и диалоговые окна

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

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

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

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

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

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

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

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

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

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

См. также