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


Модель потоков рукописного ввода

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

В следующем списке описаны потоки, которые участвуют в сборе и отображении цифровых чернил:

  • Поток пера — это поток, обрабатывающий данные, получаемые от стилуса. (На самом деле это пул потоков, но эта тема относится к нему как к нити пера.)

  • Поток пользовательского интерфейса приложения — поток, который управляет пользовательским интерфейсом приложения.

  • Динамический поток отрисовки изображения — поток, который отрисовывает чернила, пока пользователь рисует росчерк. Поток динамической отрисовки отличается от потока, который отрисовывает другие элементы пользовательского интерфейса для приложения, как указано в Window Presentation Foundation Threading Model.

Модель рукописного ввода одинакова, независимо от того, использует ли приложение элемент управления InkCanvas или пользовательский элемент, аналогичный тому, который описан в Создание элемента управления рукописного ввода. Хотя это обсуждение касается потоков в контексте InkCanvas, те же понятия применимы и при создании пользовательского элемента управления.

Обзор потоков

На следующей схеме показана модель потоков, когда пользователь рисует штрих:

Модель потоков при рисовании штриха.

  1. Действия, происходящие при рисовании росчерка пользователем

    1. Когда пользователь рисует росчерк, точки пера вступают в поток пера. Подключаемые модули stylus, в том числе DynamicRenderer, принимают точки пера и имеют возможность изменять их до того, как InkCanvas получает их.

    2. DynamicRenderer отрисовывает точки стилуса в потоке динамической отрисовки. Это происходит одновременно с предыдущим шагом.

    3. InkCanvas получает касания стилуса в потоке пользовательского интерфейса.

  2. Действия, происходящие после завершения росчерка пользователя

    1. Когда пользователь завершает рисование росчерка, InkCanvas создает объект Stroke и добавляет его в InkPresenter, который статически отрисовывает его.

    2. Поток пользовательского интерфейса оповещает DynamicRenderer, что штрих статически отрисовывается, поэтому DynamicRenderer удаляет визуальное представление штриха.

Сбор данных рукописного ввода и подключаемые модули для стилуса

Каждый UIElement имеет StylusPlugInCollection. Объекты StylusPlugIn в StylusPlugInCollection получают и могут изменять точки пера в потоке пера. Объекты StylusPlugIn получают точки пера в соответствии с их порядком в StylusPlugInCollection.

На следующей схеме показана гипотетическая ситуация, в которой коллекция StylusPlugInsUIElement содержит stylusPlugin1, DynamicRendererи stylusPlugin2в указанном порядке.

Порядок подключаемых модулей stylus влияет на выходные данные.

На предыдущей схеме происходит следующее поведение:

  1. StylusPlugin1 изменяет значения x и y.

  2. DynamicRenderer получает измененные точки пера и отрисовывает их в динамическом потоке отрисовки.

  3. StylusPlugin2 получает измененные точки пера и изменяет значения x и y.

  4. Приложение собирает точки пера и, когда пользователь завершает штрих, статически отрисовывает штрих.

Предположим, что stylusPlugin1 ограничивает точки пера на прямоугольник, и stylusPlugin2 перемещает точки пера вправо. В предыдущем сценарии DynamicRenderer получает ограниченные координаты пера, но не преобразованные координаты пера. Когда пользователь рисует росчерк, штрих отрисовывается в пределах прямоугольника, но штрих не преобразуется, пока пользователь не поднимет перо.

Выполнение операций с плагином Stylus в UI-потоке

Так как точное тестирование попаданий не может выполняться в потоке пера, некоторые элементы могут иногда получать входные данные пера, предназначенные для других элементов. Если необходимо убедиться, что входные данные были перенаправлены правильно перед выполнением операции, подпишитесь и выполните операцию в методе OnStylusDownProcessed, OnStylusMoveProcessedили OnStylusUpProcessed. Эти методы вызываются потоком приложения после точного определения попадания. Чтобы подписаться на эти методы, вызовите метод NotifyWhenProcessed в методе, выполняющемся в потоке пера.

На следующей схеме показана связь между потоком пера и потоком пользовательского интерфейса относительно событий стилуса StylusPlugIn.

модели потоков рукописного ввода (пользовательский интерфейс и перо)

Отрисовка чернил

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

схема потоков чернил

  1. Пользователь начинает удар.

    1. DynamicRenderer создает визуальное дерево.
  2. Пользователь рисует штрих.

    1. DynamicRenderer создает визуальное дерево.
  3. Пользователь завершает штрих.

    1. InkPresenter добавляет штрих в визуальное дерево.

    2. Уровень интеграции мультимедиа (MIL) статически отрисовывает линии.

    3. DynamicRenderer очищает визуальные элементы.