スタイラスからの入力のインターセプト

System.Windows.Input.StylusPlugIns アーキテクチャには、Stylus の入力およびデジタル インクの Stroke オブジェクトの作成に対する低レベルの制御を実装するためのメカニズムが用意されています。 StylusPlugIn クラスでは、パフォーマンスを最適にするために、カスタム動作を実装し、スタイラス デバイスから送信されるデータ ストリームにそれを適用するためのメカニズムが提供されています。

このトピックは、次の内容で構成されています。

アーキテクチャ

StylusPlugIn は、「ペン入力へのアクセスとその操作」で説明されている StylusInput API が進化したものです。

UIElement には、StylusPlugInCollection である StylusPlugIns プロパティがあります。 要素の StylusPlugIns プロパティに StylusPlugIn を追加して、生成時に StylusPoint のデータを操作できます。 StylusPoint のデータは、X および Y のポイント データや PressureFactor など、システム デジタイザーによってサポートされているすべてのプロパティで構成されます。

StylusPlugInStylusPlugIns プロパティに追加すると、Stylus デバイスから送信されるデータ ストリームに、StylusPlugIn オブジェクトが直接挿入されます。 プラグインが StylusPlugIns コレクションに追加される順序によって、StylusPoint データを受信する順序が決まります。 たとえば、入力を特定の領域に制限するフィルター プラグインを追加した後、書き込まれたジェスチャを認識するプラグインを追加した場合、ジェスチャを認識するプラグインは、フィルター処理された StylusPoint データを受け取ります。

スタイラス プラグインの実装

プラグインを実装するには、StylusPlugIn の派生クラスを作成します。 このクラスは、Stylus から送られてくるデータのストリームに適用されます。 このクラスでは、StylusPoint データの値を変更できます。

注意事項

StylusPlugIn で例外がスローされた場合、またはそれが例外の原因になった場合、アプリケーションは終了します。 StylusPlugIn を使用するコントロールを十分にテストし、StylusPlugIn で例外がスローされないことが確実な場合にのみ、コントロールを使用する必要があります。

次の例では、Stylus デバイスから送られてきた StylusPoint データの XY の値を変更することによって、スタイラスの入力を制限するプラグインを示します。

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 コレクションのメンバーになっているためです。 StylusPlugIns コレクションに追加したカスタム StylusPlugIn は、DynamicRenderer がデータを受け取った後で、StylusPoint データを受け取ります。 その結果、ユーザーがペンを上げてストロークを終了するまで、StylusPoint データはフィルター処理されません。 ユーザーが描画するのと同時にインクをフィルター処理するには、DynamicRenderer の前に FilterPlugin を挿入する必要があります。

次の 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 のデータにアクセスできるため、アプリケーションに最適なパフォーマンスでインクのコレクションとレンダリングを実装できます。

関連項目