攔截手寫筆的輸入
更新:2007 年 11 月
System.Windows.Input.StylusPlugIns 架構提供一套機制,可以實作 Stylus 輸入的低階控制並且建立數位筆墨 Stroke 物件。StylusPlugIn 類別提供一種機制,讓您實作自訂行為,並且可以將自訂行為套用到手寫筆裝置所傳入的資料流以達到最佳效能。
本主題包含下列子章節:
架構
實作手寫筆外掛程式
將外掛程式加入 InkCanvas
結論
架構
StylusPlugIn 由 StylusInput API 演進而來,如 Microsoft Windows XP Tablet PC Edition Software Development Kit 1.7 中的存取及管理畫筆輸入所述。
每個 UIElement 都有做為 StylusPlugInCollection 的 StylusPlugIns 屬性。您可以將 StylusPlugIn 加入項目的 StylusPlugIns 屬性以操作所產生的 StylusPoint 資料。StylusPoint 資料是由系統數位板支援的所有屬性組成,包含 X 和 Y 點資料和 PressureFactor 資料。
當您將 StylusPlugIn 加入 StylusPlugIns 屬性時,StylusPlugIn 物件會直接插入來自 Stylus 裝置的資料流。將外掛程式加入 StylusPlugIns 集合的順序表示他們接收 StylusPoint 資料的順序。例如,如果您將限制輸入的篩選外掛程式加入特定區域,然後加入可辨識撰寫動作的外掛程式,可辨識動作的外掛程式會接收到篩選的 StylusPoint 資料。
實作手寫筆外掛程式
若要實作衍生自 StylusPlugIn 的類別。此類別會在資料流來自於 Stylus 時應用資料流。在此類別中,您可以修改 StylusPoint 資料的值。
![]() |
---|
如果 StylusPlugIn 擲出或造成例外狀況,應用程式就會關閉。您應該徹底測試使用 StylusPlugIn 的控制項,並且只有在確定 StylusPlugIn 不會擲出例外狀況時,才使用控制項。 |
下列範例會在資料來自於 Stylus 裝置時,修改 StylusPoint 資料中的 X 和 Y 值,藉以示範限制手寫筆輸入的外掛程式。
Imports System
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
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 'OnStylusDown
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 'OnStylusMove
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 'OnStylusUp
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 'Filter
End Class 'FilterPlugin
using System;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Input;
using 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);
}
}
將外掛程式加入 InkCanvas
使用自訂外掛程式最簡單的方法是實作衍生自 InkCanvas 的類別並將它加入 StylusPlugIns 屬性。
下列範例示範篩選筆墨的自訂 InkCanvas。
Public Class FilterInkCanvas
Inherits InkCanvas
Private filter As New FilterPlugin()
Public Sub New()
Me.StylusPlugIns.Add(filter)
End Sub 'New
End Class 'FilterInkCanvas
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
Inherits InkCanvas
Private filter As New FilterPlugin()
Public Sub New()
Dim dynamicRenderIndex As Integer = Me.StylusPlugIns.IndexOf(Me.DynamicRenderer)
Me.StylusPlugIns.Insert(dynamicRenderIndex, filter)
End Sub 'New
End Class 'DynamicallyFilteredInkCanvas
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 資料的存取權限非常低,所以能夠以最佳的應用程式效能,實作筆墨收集並且呈現筆墨。