攔截手寫筆的輸入
System.Windows.Input.StylusPlugIns 結構提供的機制,可實作低階控制 Stylus 輸入,以及建立數位筆跡 Stroke 物件。 StylusPlugIn 類別提供的機制,可讓您實作自訂行為,並將其套用至來自手寫筆裝置的資料流,以獲得最佳效能。
本主題包含下列子章節:
架構
StylusPlugIn 是 StylusInput API 的演進,如存取和操作手寫筆輸入中所述。
每個 UIElement 都有一個 StylusPlugIns 屬性,其為 StylusPlugInCollection。 您可以將 StylusPlugIn 新增至元素的 StylusPlugIns 屬性,以在產生 StylusPoint 資料時操作資料。 StylusPoint 資料是由系統數位板支援的所有屬性所組成,包括 X 和 Y 點資料,以及 PressureFactor 資料。
當您將 StylusPlugIn 新增至 StylusPlugIns 屬性時,您的 StylusPlugIn 物件會直接插入來自 Stylus 裝置的資料流中。 將外掛程式新增至 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 資料具有低層級存取權,因此您可以實作筆跡集合,並以應用程式的最佳效能轉譯。