스타일러스에서 입력 가로채기
System.Windows.Input.StylusPlugIns 아키텍처에서는 Stylus 입력 및 디지털 잉크 Stroke 개체 생성에 대한 하위 수준 제어를 구현하는 메커니즘을 제공합니다. StylusPlugIn 클래스에서는 사용자 지정 동작을 구현하고 최적의 성능을 위해 스타일러스 장치를 통해 입력되는 데이터 스트림에 해당 동작을 적용하는 메커니즘을 제공합니다.
이 항목에는 다음과 같은 하위 단원이 포함되어 있습니다.
아키텍처
스타일러스 플러그 인 구현
InkCanvas에 플러그 인 추가
결론
아키텍처
StylusPlugIn은 Microsoft Windows XP Tablet PC Edition Software Development Kit 1.7의 Accessing and Manipulating Pen Input에 설명되어 있는 StylusInput API의 진화된 형태입니다.
각 UIElement에는 StylusPlugInCollection인 StylusPlugIns 속성이 있습니다. 요소의 StylusPlugIns 속성에 StylusPlugIn을 추가하면 StylusPoint 데이터가 생성될 때 이 데이터를 조작할 수 있습니다. StylusPoint 데이터는 X 및 Y 포인트 데이터뿐만 아니라 PressureFactor 데이터를 비롯하여 시스템 디지타이저가 지원하는 모든 속성으로 구성됩니다.
StylusPlugIns 속성에 StylusPlugIn을 추가하면 StylusPlugIn 개체가 Stylus 장치를 통해 입력되는 데이터 스트림에 직접 삽입됩니다. 플러그 인이 StylusPlugIns 컬렉션에 추가되는 순서에 따라 플러그 인에서 StylusPoint 데이터를 받는 순서가 결정됩니다. 예를 들어 입력을 특정 영역으로 제한하는 필터 플러그 인을 추가한 다음 작성되는 제스처를 인식하는 플러그 인을 추가한 경우 제스처를 인식하는 플러그 인은 필터링된 StylusPoint 데이터를 받습니다.
스타일러스 플러그 인 구현
플러그 인을 구현하려면 StylusPlugIn에서 클래스를 파생시킵니다. 이 클래스는 Stylus를 통해 입력되는 데이터 스트림에 적용됩니다. 이 클래스에서 StylusPoint 데이터 값을 수정할 수 있습니다.
![]() |
---|
StylusPlugIn에서 예외를 throw하거나 예외를 일으키면 응용 프로그램이 종료되므로StylusPlugIn을 사용하는 컨트롤을 철저하게 테스트하여 StylusPlugIn이 예외를 throw하지 않는 것이 확실한 경우에만 컨트롤을 사용해야 합니다. |
다음 예제에서는 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에 StylusPlugIn이며 이미 StylusPlugIns 컬렉션의 멤버인 DynamicRenderer 속성이 있기 때문입니다. 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 데이터에 대한 하위 수준 액세스가 제공되므로 응용 프로그램에 사용할 잉크 컬렉션을 구현하고 최적의 성능으로 렌더링할 수 있습니다.