截获触笔输入Intercepting Input from the Stylus

System.Windows.Input.StylusPlugIns体系结构提供了一种机制,用于实现对Stylus输入和数字墨迹Stroke对象创建的低级别控制。The System.Windows.Input.StylusPlugIns architecture provides a mechanism for implementing low-level control over Stylus input and the creation of digital ink Stroke objects. StylusPlugIn类提供一种机制,用于实现自定义行为,并将其应用于来自触笔设备的数据流,以获得最佳性能。The StylusPlugIn class provides a mechanism for you to implement custom behavior and apply it to the stream of data coming from the stylus device for the optimal performance.

本主题包含以下小节:This topic contains the following subsections:

体系结构Architecture

在 Microsoft Windows XP Tablet PC Edition 软件开发工具包 1.7中,在访问和操作笔输入中介绍了 StylusInput api 的发展 StylusPlugInThe StylusPlugIn is the evolution of the StylusInput APIs, described in Accessing and Manipulating Pen Input, in the Microsoft Windows XP Tablet PC Edition Software Development Kit 1.7.

UIElement个都有StylusPlugInCollection一个的属性。StylusPlugInsEach UIElement has a StylusPlugIns property that is a StylusPlugInCollection. 可以向元素的StylusPlugIn StylusPlugIns属性添加,以便在生成数据StylusPoint时对数据进行操作。You can add a StylusPlugIn to an element's StylusPlugIns property to manipulate StylusPoint data as it is generated. StylusPoint数据包含系统数字化器支持的所有属性,包括XYPressureFactor数据以及数据。StylusPoint data consists of all the properties supported by the system digitizer, including the X and Y point data, as well as PressureFactor data.

StylusPlugIn Stylus 你将StylusPlugIn添加到属性中时,你的对象将直接插入来自设备的数据流。StylusPlugInsYour StylusPlugIn objects are inserted directly into the stream of data coming from the Stylus device when you add the StylusPlugIn to the StylusPlugIns property. 插件添加到StylusPlugIns集合中的顺序指示它们将接收StylusPoint数据的顺序。The order in which plug-ins are added to the StylusPlugIns collection dictates the order in which they will receive StylusPoint data. 例如,如果添加一个筛选器插件,该插件将输入限制为特定区域,然后添加一个可在写入时识别手势的插件,则识别手势的插件将接收筛选StylusPoint的数据。For example, if you add a filter plug-in that restricts input to a particular region, and then add a plug-in that recognizes gestures as they are written, the plug-in that recognizes gestures will receive filtered StylusPoint data.

实现触笔插件Implementing Stylus Plug-ins

若要实现某个插件,请从StylusPlugIn派生一个类。To implement a plug-in, derive a class from StylusPlugIn. 此类应用于从Stylus传入的数据流的输出。This class is applied o the stream of data as it comes in from the Stylus. 在此类中,您可以修改StylusPoint数据的值。In this class you can modify the values of the StylusPoint data.

注意

StylusPlugIn如果引发或导致异常,应用程序将关闭。If a StylusPlugIn throws or causes an exception, the application will close. 你应全面测试使用的StylusPlugIn控件,并且仅当你StylusPlugIn确定不会引发异常时,才使用控件。You should thoroughly test controls that consume a StylusPlugIn and only use a control if you are certain the StylusPlugIn will not throw an exception.

下面的示例演示一个插件,该插件X通过修改StylusPoint数据Stylus中来自设备的和Y值来限制触笔输入。The following example demonstrates a plug-in that restricts the stylus input by modifying the X and Y values in the StylusPoint data as it comes in from the Stylus device.

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

将插件添加到 InkCanvasAdding Your Plug-in to an InkCanvas

使用自定义插件的最简单方法是实现从 InkCanvas 派生的类并将其添加到StylusPlugIns属性。The easiest way to use your custom plug-in is to implement a class that derives from InkCanvas and add it to the StylusPlugIns property.

下面的示例演示用于筛选InkCanvas墨迹的自定义。The following example demonstrates a custom InkCanvas that filters the ink.

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

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

如果你将添加FilterInkCanvas到应用程序并运行它,你会注意到,在用户完成笔划之前,不会将墨迹限制在某个区域。If you add a FilterInkCanvas to your application and run it, you will notice that the ink isn't restricted to a region until after the user completes a stroke. InkCanvas是因为DynamicRenderer具有一个StylusPlugIn属性,该属性是,并且已经是StylusPlugIns集合的成员。This is because the InkCanvas has a DynamicRenderer property, which is a StylusPlugIn and is already a member of the StylusPlugIns collection. 添加StylusPlugIn StylusPoint到集合中的自定义接收数据后DynamicRenderer接收数据。 StylusPlugInsThe custom StylusPlugIn you added to the StylusPlugIns collection receives the StylusPoint data after DynamicRenderer receives data. 因此,在用户将StylusPoint笔提起到结束笔划之前,将不会对数据进行筛选。As a result, the StylusPoint data will not be filtered until after the user lifts the pen to end a stroke. 若要在用户绘制墨迹时筛选墨迹,必须在FilterPlugin DynamicRenderer之前插入。To filter the ink as the user draws it, you must insert the FilterPlugin before the DynamicRenderer.

下面C#的代码演示了一个InkCanvas自定义,它在绘制时对墨迹进行筛选。The following C# code demonstrates a custom InkCanvas that filters the ink as it is drawn.

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

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

结束语Conclusion

通过派生你自己StylusPlugIn的类并将它们StylusPlugInCollection插入到集合中,你可以极大地增强数字墨迹的行为。By deriving your own StylusPlugIn classes and inserting them into StylusPlugInCollection collections, you can greatly enhance the behavior of your digital ink. 您可以在生成StylusPoint数据时对其进行访问,从而为您提供Stylus自定义输入的机会。You have access to the StylusPoint data as it is generated, giving you the opportunity to customize the Stylus input. 由于你对StylusPoint数据具有这样的低级别访问权限,因此你可以实现墨迹收集并使用应用程序的最佳性能进行呈现。Because you have such low-level access to the StylusPoint data, you can implement ink collection and rendering with optimal performance for your application.

请参阅See also