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


Перехват входных данных со стилуса

Архитектура System.Windows.Input.StylusPlugIns предоставляет механизм реализации низкоуровневого управления входными данными Stylus и создания цифровых чернильных Stroke объектов. Класс StylusPlugIn предоставляет механизм реализации пользовательского поведения и применения его к потоку данных, поступающих с устройства пера для оптимальной производительности.

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

Архитектура

StylusPlugIn — это эволюция API StylusInput, описанные в разделе Доступ и управление вводом пера.

У каждого UIElement есть свойство StylusPlugIns, которое является StylusPlugInCollection. Вы можете добавить StylusPlugIn к свойству StylusPlugIns элемента для управления StylusPoint данными по мере их создания. StylusPoint данные состоят из всех свойств, поддерживаемых системным дигитайзером, включая данные точки X и Y, а также данные PressureFactor.

Объекты StylusPlugIn вставляются непосредственно в поток данных, поступающих с устройства Stylus, когда вы добавляете StylusPlugIn в свойство StylusPlugIns. Порядок добавления подключаемых модулей в коллекцию StylusPlugIns определяет порядок, в котором они будут получать данные StylusPoint. Например, если добавить подключаемый модуль фильтра, ограничивающий входные данные в определенном регионе, а затем добавьте подключаемый модуль, который распознает жесты по мере записи, подключаемый модуль, который распознает жесты, будет получать отфильтрованные StylusPoint данные.

Внедрение подключаемых модулей Stylus

Чтобы реализовать подключаемый модуль, наследуйте класс из StylusPlugIn. Этот класс применяется к потоку данных по мере поступления из Stylus. В этом классе можно изменить значения данных StylusPoint.

Осторожность

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

В следующем примере показан плагин, ограничивающий данные, вводимые с пера, путем изменения значений X и Y в данных StylusPoint, получаемых от устройства Stylus.

using System;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Input;
using System.Windows.Ink;
Imports System.Windows.Media
Imports System.Windows
Imports System.Windows.Input.StylusPlugIns
Imports System.Windows.Input
Imports System.Windows.Ink
// A StylusPlugin that restricts the input area.
class FilterPlugin : StylusPlugIn
{
    protected override void OnStylusDown(RawStylusInput rawStylusInput)
    {
        // Call the base class before modifying the data.
        base.OnStylusDown(rawStylusInput);

        // Restrict the stylus input.
        Filter(rawStylusInput);
    }

    protected override void OnStylusMove(RawStylusInput rawStylusInput)
    {
        // Call the base class before modifying the data.
        base.OnStylusMove(rawStylusInput);

        // Restrict the stylus input.
        Filter(rawStylusInput);
    }

    protected override void OnStylusUp(RawStylusInput rawStylusInput)
    {
        // Call the base class before modifying the data.
        base.OnStylusUp(rawStylusInput);

        // Restrict the stylus input
        Filter(rawStylusInput);
    }

    private void Filter(RawStylusInput rawStylusInput)
    {
        // Get the StylusPoints that have come in.
        StylusPointCollection stylusPoints = rawStylusInput.GetStylusPoints();

        // Modify the (X,Y) data to move the points
        // inside the acceptable input area, if necessary.
        for (int i = 0; i < stylusPoints.Count; i++)
        {
            StylusPoint sp = stylusPoints[i];
            if (sp.X < 50) sp.X = 50;
            if (sp.X > 250) sp.X = 250;
            if (sp.Y < 50) sp.Y = 50;
            if (sp.Y > 250) sp.Y = 250;
            stylusPoints[i] = sp;
        }

        // Copy the modified StylusPoints back to the RawStylusInput.
        rawStylusInput.SetStylusPoints(stylusPoints);
    }
}
' A StylusPlugin that restricts the input area.
Class FilterPlugin
    Inherits StylusPlugIn

    Protected Overrides Sub OnStylusDown(ByVal rawStylusInput As RawStylusInput)
        ' Call the base class before modifying the data.
        MyBase.OnStylusDown(rawStylusInput)

        ' Restrict the stylus input.
        Filter(rawStylusInput)

    End Sub


    Protected Overrides Sub OnStylusMove(ByVal rawStylusInput As RawStylusInput)
        ' Call the base class before modifying the data.
        MyBase.OnStylusMove(rawStylusInput)

        ' Restrict the stylus input.
        Filter(rawStylusInput)

    End Sub


    Protected Overrides Sub OnStylusUp(ByVal rawStylusInput As RawStylusInput)
        ' Call the base class before modifying the data.
        MyBase.OnStylusUp(rawStylusInput)

        ' Restrict the stylus input
        Filter(rawStylusInput)

    End Sub


    Private Sub Filter(ByVal rawStylusInput As RawStylusInput)
        ' Get the StylusPoints that have come in.
        Dim stylusPoints As StylusPointCollection = rawStylusInput.GetStylusPoints()

        ' Modify the (X,Y) data to move the points 
        ' inside the acceptable input area, if necessary.
        Dim i As Integer
        For i = 0 To stylusPoints.Count - 1
            Dim sp As StylusPoint = stylusPoints(i)
            If sp.X < 50 Then
                sp.X = 50
            End If
            If sp.X > 250 Then
                sp.X = 250
            End If
            If sp.Y < 50 Then
                sp.Y = 50
            End If
            If sp.Y > 250 Then
                sp.Y = 250
            End If
            stylusPoints(i) = sp
        Next i

        ' Copy the modified StylusPoints back to the RawStylusInput.
        rawStylusInput.SetStylusPoints(stylusPoints)

    End Sub
End Class

Добавление вашего подключаемого модуля в InkCanvas

Самый простой способ использовать настраиваемый подключаемый модуль — реализовать класс, производный от InkCanvas, и добавить его в свойство StylusPlugIns.

В следующем примере показан пользовательский InkCanvas, который фильтрует чернила.

public class FilterInkCanvas : InkCanvas
{
    FilterPlugin filter = new FilterPlugin();

    public FilterInkCanvas()
        : base()
    {
        this.StylusPlugIns.Add(filter);
    }
}

Если вы добавите в приложение FilterInkCanvas и запустите его, вы заметите, что рукописные чернила не ограничены одним регионом до тех пор, пока пользователь не завершит линию. Это связано с тем, что InkCanvas имеет свойство DynamicRenderer, которое является StylusPlugIn и уже является членом коллекции StylusPlugIns. Пользовательская StylusPlugIn, добавленная в коллекцию StylusPlugIns, получает данные StylusPoint после того, как DynamicRenderer получает данные. В результате данные StylusPoint не будут отфильтрованы до тех пор, пока пользователь не поднимет перо, чтобы завершить штрих. Чтобы отфильтровать рукописный ввод, когда пользователь рисует, необходимо вставить FilterPlugin перед DynamicRenderer.

В следующем коде C# представлен пользовательский элемент InkCanvas, который фильтрует чернила в процессе рисования.

public class DynamicallyFilteredInkCanvas : InkCanvas
{
    FilterPlugin filter = new FilterPlugin();

    public DynamicallyFilteredInkCanvas()
        : base()
    {
        int dynamicRenderIndex =
            this.StylusPlugIns.IndexOf(this.DynamicRenderer);

        this.StylusPlugIns.Insert(dynamicRenderIndex, filter);
    }
}

Заключение

Создав собственные классы StylusPlugIn и вставив их в коллекции StylusPlugInCollection, вы можете значительно улучшить работу с цифровыми чернилами. У вас есть доступ к данным StylusPoint по мере их создания, что позволяет вам настраивать входные данные Stylus. Поскольку у вас есть такой низкоуровневый доступ к данным StylusPoint, вы можете реализовать сбор данных и визуализацию с оптимальной производительностью для вашего приложения.

См. также