スタイラスからの入力のインターセプト
System.Windows.Input.StylusPlugIns アーキテクチャには、Stylus の入力およびデジタル インクの Stroke オブジェクトの作成に対する低レベルの制御を実装するためのメカニズムが用意されています。 StylusPlugIn クラスでは、パフォーマンスを最適にするために、カスタム動作を実装し、スタイラス デバイスから送信されるデータ ストリームにそれを適用するためのメカニズムが提供されています。
このトピックは、次の内容で構成されています。
アーキテクチャ
StylusPlugIn は、「ペン入力へのアクセスとその操作」で説明されている StylusInput API が進化したものです。
各 UIElement には、StylusPlugInCollection である StylusPlugIns プロパティがあります。 要素の StylusPlugIns プロパティに StylusPlugIn を追加して、生成時に StylusPoint のデータを操作できます。 StylusPoint のデータは、X および Y のポイント データや PressureFactor など、システム デジタイザーによってサポートされているすべてのプロパティで構成されます。
StylusPlugIn を StylusPlugIns プロパティに追加すると、Stylus デバイスから送信されるデータ ストリームに、StylusPlugIn オブジェクトが直接挿入されます。 プラグインが StylusPlugIns コレクションに追加される順序によって、StylusPoint データを受信する順序が決まります。 たとえば、入力を特定の領域に制限するフィルター プラグインを追加した後、書き込まれたジェスチャを認識するプラグインを追加した場合、ジェスチャを認識するプラグインは、フィルター処理された StylusPoint データを受け取ります。
スタイラス プラグインの実装
プラグインを実装するには、StylusPlugIn の派生クラスを作成します。 このクラスは、Stylus から送られてくるデータのストリームに適用されます。 このクラスでは、StylusPoint データの値を変更できます。
注意事項
StylusPlugIn で例外がスローされた場合、またはそれが例外の原因になった場合、アプリケーションは終了します。 StylusPlugIn を使用するコントロールを十分にテストし、StylusPlugIn で例外がスローされないことが確実な場合にのみ、コントロールを使用する必要があります。
次の例では、Stylus デバイスから送られてきた StylusPoint データの X と Y の値を変更することによって、スタイラスの入力を制限するプラグインを示します。
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 のデータにアクセスできるため、アプリケーションに最適なパフォーマンスでインクのコレクションとレンダリングを実装できます。
関連項目
.NET Desktop feedback