方法 : カスタム コントロールからインクを選択する
更新 : 2007 年 11 月
IncrementalLassoHitTester をカスタム コントロールに追加することで、InkCanvas がなげなわを使用してインクを選択するのと同様に、ユーザーがなげなわツールを使用してインクを選択できるようにコントロールを有効にすることができます。
この例は、インク対応カスタム コントロールの作成に精通していることを前提としています。インク入力対応のカスタム コントロールを作成するには、「インク入力コントロールの作成」を参照してください。
使用例
ユーザーがなげなわを描画すると、IncrementalLassoHitTester は、ユーザーがなげなわを完了したときに、どのストロークがなげなわのパスの境界内に入っているかを予測します。なげなわのパスの境界内に入っていることが特定されたストロークは、選択されているものと考えることができます。また、選択されたストロークは、選択解除される場合もあります。たとえば、ユーザーがなげなわを描画しながら方向を反転させた場合、IncrementalLassoHitTester は、一部のストロークを選択解除します。
IncrementalLassoHitTester は SelectionChanged イベントを発生させ、ユーザーがなげなわを描画している間でも、カスタム コントロールが応答できるようにします。たとえば、ユーザーの選択および選択解除に合わせて、ストロークの外観を変更することができます。
インク モードの管理
コントロール上でなげなわとインクが異なって表示されると、ユーザーにとって便利です。これを実現するには、ユーザーがインクを書き込んでいるのか選択しているのかを、カスタム コントロールが追跡する必要があります。このような動作を実行する最も簡単な方法は、2 つの値を持つ列挙体を宣言することです。1 つはユーザーがインクを書き込んでいることを示し、もう 1 つはユーザーがインクを選択していることを示します。
' Enum that keeps track of whether StrokeCollectionDemo is in ink mode
' or select mode.
Public Enum InkMode
Ink
[Select]
End Enum 'InkMode
// Enum that keeps track of whether StrokeCollectionDemo is in ink mode
// or select mode.
public enum InkMode
{
Ink, Select
}
次に、2 つの DrawingAttributes をクラスに追加します。1 つはユーザーがインクを書き込んでいる場合に使用し、もう 1 つはユーザーがインクを選択している場合に使用します。コンストラクタで DrawingAttributes を初期化し、両方の AttributeChanged イベントを同じイベント ハンドラに結合します。次に、DynamicRenderer の DrawingAttributes プロパティを、インクの DrawingAttributes に設定します。
Private inkDA As DrawingAttributes
Private selectDA As DrawingAttributes
...
' In the constructor.
' Selection drawing attributes use dark gray ink.
selectDA = New DrawingAttributes()
selectDA.Color = Colors.DarkGray
' ink drawing attributes use default attributes
inkDA = New DrawingAttributes()
inkDA.Width = 5
inkDA.Height = 5
AddHandler inkDA.AttributeChanged, _
AddressOf DrawingAttributesChanged
AddHandler selectDA.AttributeChanged, _
AddressOf DrawingAttributesChanged
DrawingAttributes inkDA;
DrawingAttributes selectDA;
...
// In the constructor.
// Selection drawing attributes use dark gray ink.
selectDA = new DrawingAttributes();
selectDA.Color = Colors.DarkGray;
// ink drawing attributes use default attributes
inkDA = new DrawingAttributes();
inkDA.Width = 5;
inkDA.Height = 5;
inkDA.AttributeChanged += new PropertyDataChangedEventHandler(DrawingAttributesChanged);
selectDA.AttributeChanged += new PropertyDataChangedEventHandler(DrawingAttributesChanged);
選択モードを公開するプロパティを追加します。ユーザーが選択モードを変更したら、DynamicRenderer の DrawingAttributes プロパティを適切な DrawingAttributes オブジェクトに設定し、RootVisual プロパティを InkPresenter に再度結び付けます。
' Property to indicate whether the user is inputting or
' selecting ink.
Public Property Mode() As InkMode
Get
Return Mode
End Get
Set(ByVal value As InkMode)
modeState = value
' Set the DrawingAttributes of the DynamicRenderer
If modeState = InkMode.Ink Then
renderer.DrawingAttributes = inkDA
Else
renderer.DrawingAttributes = selectDA
End If
' Reattach the visual of the DynamicRenderer to the InkPresenter.
presenter.DetachVisuals(renderer.RootVisual)
presenter.AttachVisuals(renderer.RootVisual, renderer.DrawingAttributes)
End Set
End Property
// Property to indicate whether the user is inputting or
// selecting ink.
public InkMode Mode
{
get
{
return mode;
}
set
{
mode = value;
// Set the DrawingAttributes of the DynamicRenderer
if (mode == InkMode.Ink)
{
renderer.DrawingAttributes = inkDA;
}
else
{
renderer.DrawingAttributes = selectDA;
}
// Reattach the visual of the DynamicRenderer to the InkPresenter.
presenter.DetachVisuals(renderer.RootVisual);
presenter.AttachVisuals(renderer.RootVisual, renderer.DrawingAttributes);
}
}
DrawingAttributes をプロパティとして公開し、アプリケーションがインク ストロークおよび選択ストロークの外観を決定できるようにします。
' Property to allow the user to change the pen's DrawingAttributes.
Public ReadOnly Property InkDrawingAttributes() As DrawingAttributes
Get
Return inkDA
End Get
End Property
' Property to allow the user to change the Selector'newStroke DrawingAttributes.
Public ReadOnly Property SelectDrawingAttributes() As DrawingAttributes
Get
Return selectDA
End Get
End Property
// Property to allow the user to change the pen's DrawingAttributes.
public DrawingAttributes InkDrawingAttributes
{
get
{
return inkDA;
}
}
// Property to allow the user to change the Selector'newStroke DrawingAttributes.
public DrawingAttributes SelectDrawingAttributes
{
get
{
return selectDA;
}
}
DrawingAttributes オブジェクトのプロパティが変更された場合は、RootVisual を InkPresenter に再度結び付ける必要があります。AttributeChanged イベントのイベント ハンドラで、RootVisual を InkPresenter に再度結び付けます。
Private Sub DrawingAttributesChanged(ByVal sender As Object, _
ByVal e As PropertyDataChangedEventArgs)
' Reattach the visual of the DynamicRenderer to the InkPresenter
' whenever the DrawingAttributes change.
presenter.DetachVisuals(renderer.RootVisual)
presenter.AttachVisuals(renderer.RootVisual, _
renderer.DrawingAttributes)
End Sub 'DrawingAttributesChanged
void DrawingAttributesChanged(object sender, PropertyDataChangedEventArgs e)
{
// Reattach the visual of the DynamicRenderer to the InkPresenter
// whenever the DrawingAttributes change.
presenter.DetachVisuals(renderer.RootVisual);
presenter.AttachVisuals(renderer.RootVisual, renderer.DrawingAttributes);
}
IncrementalLassoHitTester の使用
選択されたストロークを含む StrokeCollection を作成および初期化します。
' StylusPointCollection that collects the stylus points from the stylus events.
Private stylusPoints As StylusPointCollection
// StylusPointCollection that collects the stylus points from the stylus events.
StylusPointCollection stylusPoints;
ユーザーが、インクまたはなげなわのいずれかのストロークの描画を開始したら、選択されている任意のストロークを選択解除します。次に、ユーザーがなげなわを描画している場合は、GetIncrementalLassoHitTester を呼び出して IncrementalLassoHitTester を作成し、SelectionChanged イベントにサブスクライブして、AddPoints を呼び出します。このコードは独立したメソッドとして、OnStylusDown および OnMouseDown メソッドから呼び出すことができます。
Private Sub InitializeHitTester(ByVal collectedPoints As StylusPointCollection)
' Deselect any selected strokes.
Dim selectedStroke As Stroke
For Each selectedStroke In selectedStrokes
selectedStroke.DrawingAttributes.Color = inkDA.Color
Next selectedStroke
selectedStrokes.Clear()
If modeState = InkMode.Select Then
' Remove the previously drawn lasso, if it exists.
If Not (lassoPath Is Nothing) Then
presenter.Strokes.Remove(lassoPath)
lassoPath = Nothing
End If
selectionTester = presenter.Strokes.GetIncrementalLassoHitTester(80)
AddHandler selectionTester.SelectionChanged, AddressOf selectionTester_SelectionChanged
selectionTester.AddPoints(collectedPoints)
End If
End Sub 'InitializeHitTester
private void InitializeHitTester(StylusPointCollection collectedPoints)
{
// Deselect any selected strokes.
foreach (Stroke selectedStroke in selectedStrokes)
{
selectedStroke.DrawingAttributes.Color = inkDA.Color;
}
selectedStrokes.Clear();
if (mode == InkMode.Select)
{
// Remove the previously drawn lasso, if it exists.
if (lassoPath != null)
{
presenter.Strokes.Remove(lassoPath);
lassoPath = null;
}
selectionTester =
presenter.Strokes.GetIncrementalLassoHitTester(80);
selectionTester.SelectionChanged +=
new LassoSelectionChangedEventHandler(selectionTester_SelectionChanged);
selectionTester.AddPoints(collectedPoints);
}
}
ユーザーがなげなわを描画している間に、スタイラス ポイントを IncrementalLassoHitTester に追加します。次のメソッドを、OnStylusMove、OnStylusUp、OnMouseMove、OnMouseLeftButtonUp の各メソッドから呼び出します。
Private Sub AddPointsToHitTester(ByVal collectedPoints As StylusPointCollection)
If modeState = InkMode.Select AndAlso _
Not selectionTester Is Nothing AndAlso _
selectionTester.IsValid Then
' When the control is selecting strokes, add the
' stylus packetList to selectionTester.
selectionTester.AddPoints(collectedPoints)
End If
End Sub 'AddPointsToHitTester
private void AddPointsToHitTester(StylusPointCollection collectedPoints)
{
if (mode == InkMode.Select &&
selectionTester != null &&
selectionTester.IsValid)
{
// When the control is selecting strokes, add the
// stylus packetList to selectionTester.
selectionTester.AddPoints(collectedPoints);
}
}
ユーザーがストロークを選択および選択解除したときに、IncrementalLassoHitTester.SelectionChanged イベントを処理して応答します。LassoSelectionChangedEventArgs クラスには SelectedStrokes および DeselectedStrokes プロパティが用意されており、それぞれ選択および選択解除されたストロークを取得します。
Private Sub selectionTester_SelectionChanged(ByVal sender As Object, _
ByVal args As LassoSelectionChangedEventArgs)
' Change the color of all selected strokes to red.
Dim selectedStroke As Stroke
For Each selectedStroke In args.SelectedStrokes
selectedStroke.DrawingAttributes.Color = Colors.Red
selectedStrokes.Add(selectedStroke)
Next selectedStroke
' Change the color of all unselected strokes to
' their original color.
Dim unselectedStroke As Stroke
For Each unselectedStroke In args.DeselectedStrokes
unselectedStroke.DrawingAttributes.Color = inkDA.Color
selectedStrokes.Remove(unselectedStroke)
Next unselectedStroke
End Sub 'selectionTester_SelectionChanged
void selectionTester_SelectionChanged(object sender,
LassoSelectionChangedEventArgs args)
{
// Change the color of all selected strokes to red.
foreach (Stroke selectedStroke in args.SelectedStrokes)
{
selectedStroke.DrawingAttributes.Color = Colors.Red;
selectedStrokes.Add(selectedStroke);
}
// Change the color of all unselected strokes to
// their original color.
foreach (Stroke unselectedStroke in args.DeselectedStrokes)
{
unselectedStroke.DrawingAttributes.Color = inkDA.Color;
selectedStrokes.Remove(unselectedStroke);
}
}
ユーザーがなげなわの描画を完了したら、SelectionChanged イベントからサブスクライブを解除し、EndHitTesting を呼び出します。
If modeState = InkMode.Select AndAlso lassoPath Is Nothing Then
' Add the lasso to the InkPresenter and add the packetList
' to selectionTester.
lassoPath = newStroke
lassoPath.DrawingAttributes = selectDA.Clone()
presenter.Strokes.Add(lassoPath)
RemoveHandler selectionTester.SelectionChanged, _
AddressOf selectionTester_SelectionChanged
selectionTester.EndHitTesting()
End If
if (mode == InkMode.Select && lassoPath == null)
{
// Add the lasso to the InkPresenter and add the packetList
// to selectionTester.
lassoPath = newStroke;
lassoPath.DrawingAttributes = selectDA.Clone();
presenter.Strokes.Add(lassoPath);
selectionTester.SelectionChanged -= new LassoSelectionChangedEventHandler
(selectionTester_SelectionChanged);
selectionTester.EndHitTesting();
}
すべての要素を取り入れる
次の例は、ユーザーがなげなわを使用してインクを選択できるようにするカスタム コントロールを示しています。
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Input
Imports System.Windows.Input.StylusPlugIns
Imports System.Windows.Ink
' Enum that keeps track of whether StrokeCollectionDemo is in ink mode
' or select mode.
Public Enum InkMode
Ink
[Select]
End Enum 'InkMode
' This control allows the user to input and select ink. When the
' user selects ink, the lasso remains visible until they erase, or clip
' the selected strokes, or clear the selection. When the control is
' in selection mode, strokes that are selected turn red.
Public Class InkSelector
Inherits Label
Private modeState As InkMode
Private inkDA As DrawingAttributes
Private selectDA As DrawingAttributes
Private presenter As InkPresenter
Private selectionTester As IncrementalLassoHitTester
Private selectedStrokes As New StrokeCollection()
' StylusPointCollection that collects the stylus points from the stylus events.
Private stylusPoints As StylusPointCollection
' Stroke that represents the lasso.
Private lassoPath As Stroke
Private renderer As DynamicRenderer
Public Sub New()
modeState = InkMode.Ink
' Use an InkPresenter to display the strokes on the custom control.
presenter = New InkPresenter()
Me.Content = presenter
' In the constructor.
' Selection drawing attributes use dark gray ink.
selectDA = New DrawingAttributes()
selectDA.Color = Colors.DarkGray
' ink drawing attributes use default attributes
inkDA = New DrawingAttributes()
inkDA.Width = 5
inkDA.Height = 5
AddHandler inkDA.AttributeChanged, _
AddressOf DrawingAttributesChanged
AddHandler selectDA.AttributeChanged, _
AddressOf DrawingAttributesChanged
' Add a DynmaicRenderer to the control so ink appears
' to "flow" from the tablet pen.
renderer = New DynamicRenderer()
renderer.DrawingAttributes = inkDA
Me.StylusPlugIns.Add(renderer)
presenter.AttachVisuals(renderer.RootVisual, _
renderer.DrawingAttributes)
End Sub 'New
Shared Sub New()
' Allow ink to be drawn only within the bounds of the control.
Dim owner As Type = GetType(InkSelector)
ClipToBoundsProperty.OverrideMetadata(owner, _
New FrameworkPropertyMetadata(True))
End Sub 'New
' Prepare to collect stylus packets. If Mode is set to Select,
' get the IncrementalHitTester from the InkPresenter'newStroke
' StrokeCollection and subscribe to its StrokeHitChanged event.
Protected Overrides Sub OnStylusDown(ByVal e As StylusDownEventArgs)
MyBase.OnStylusDown(e)
Stylus.Capture(Me)
' Create a new StylusPointCollection using the StylusPointDescription
' from the stylus points in the StylusDownEventArgs.
stylusPoints = New StylusPointCollection()
Dim eventPoints As StylusPointCollection = e.GetStylusPoints(Me, stylusPoints.Description)
stylusPoints.Add(eventPoints)
InitializeHitTester(eventPoints)
End Sub 'OnStylusDown
Protected Overrides Sub OnMouseLeftButtonDown(ByVal e As MouseButtonEventArgs)
MyBase.OnMouseLeftButtonDown(e)
Mouse.Capture(Me)
If Not (e.StylusDevice Is Nothing) Then
Return
End If
Dim pt As Point = e.GetPosition(Me)
Dim collectedPoints As New StylusPointCollection(New Point() {pt})
stylusPoints = New StylusPointCollection()
stylusPoints.Add(collectedPoints)
InitializeHitTester(collectedPoints)
End Sub 'OnMouseLeftButtonDown
Private Sub InitializeHitTester(ByVal collectedPoints As StylusPointCollection)
' Deselect any selected strokes.
Dim selectedStroke As Stroke
For Each selectedStroke In selectedStrokes
selectedStroke.DrawingAttributes.Color = inkDA.Color
Next selectedStroke
selectedStrokes.Clear()
If modeState = InkMode.Select Then
' Remove the previously drawn lasso, if it exists.
If Not (lassoPath Is Nothing) Then
presenter.Strokes.Remove(lassoPath)
lassoPath = Nothing
End If
selectionTester = presenter.Strokes.GetIncrementalLassoHitTester(80)
AddHandler selectionTester.SelectionChanged, AddressOf selectionTester_SelectionChanged
selectionTester.AddPoints(collectedPoints)
End If
End Sub 'InitializeHitTester
' Collect the stylus packets as the stylus moves.
Protected Overrides Sub OnStylusMove(ByVal e As StylusEventArgs)
If stylusPoints Is Nothing Then
Return
End If
Dim collectedPoints As StylusPointCollection = e.GetStylusPoints(Me, stylusPoints.Description)
stylusPoints.Add(collectedPoints)
AddPointsToHitTester(collectedPoints)
End Sub 'OnStylusMove
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
MyBase.OnMouseMove(e)
If Not (e.StylusDevice Is Nothing) Then
Return
End If
If e.LeftButton = MouseButtonState.Released Then
Return
End If
If stylusPoints Is Nothing Then
stylusPoints = New StylusPointCollection()
End If
Dim pt As Point = e.GetPosition(Me)
Dim collectedPoints As New StylusPointCollection(New Point() {pt})
stylusPoints.Add(collectedPoints)
AddPointsToHitTester(collectedPoints)
End Sub 'OnMouseMove
Private Sub AddPointsToHitTester(ByVal collectedPoints As StylusPointCollection)
If modeState = InkMode.Select AndAlso _
Not selectionTester Is Nothing AndAlso _
selectionTester.IsValid Then
' When the control is selecting strokes, add the
' stylus packetList to selectionTester.
selectionTester.AddPoints(collectedPoints)
End If
End Sub 'AddPointsToHitTester
' When the user lifts the stylus, create a Stroke from the
' collected stylus points and add it to the InkPresenter.
' When the control is selecting strokes, add the
' point data to the IncrementalHitTester.
Protected Overrides Sub OnStylusUp(ByVal e As StylusEventArgs)
If stylusPoints Is Nothing Then
stylusPoints = New StylusPointCollection()
End If
Dim collectedPoints As StylusPointCollection = _
e.GetStylusPoints(Me, stylusPoints.Description)
stylusPoints.Add(collectedPoints)
AddPointsToHitTester(collectedPoints)
AddStrokeToPresenter()
stylusPoints = Nothing
Stylus.Capture(Nothing)
End Sub 'OnStylusUp
Protected Overrides Sub OnMouseLeftButtonUp(ByVal e As MouseButtonEventArgs)
MyBase.OnMouseLeftButtonUp(e)
If Not (e.StylusDevice Is Nothing) Then
Return
End If
If stylusPoints Is Nothing Then
stylusPoints = New StylusPointCollection()
End If
Dim pt As Point = e.GetPosition(Me)
Dim collectedPoints As New StylusPointCollection(New Point() {pt})
stylusPoints.Add(collectedPoints)
AddPointsToHitTester(collectedPoints)
AddStrokeToPresenter()
stylusPoints = Nothing
Mouse.Capture(Nothing)
End Sub 'OnMouseLeftButtonUp
Private Sub AddStrokeToPresenter()
Dim newStroke As New Stroke(stylusPoints)
If modeState = InkMode.Ink Then
' Add the stroke to the InkPresenter.
newStroke.DrawingAttributes = inkDA.Clone()
presenter.Strokes.Add(newStroke)
End If
If modeState = InkMode.Select AndAlso lassoPath Is Nothing Then
' Add the lasso to the InkPresenter and add the packetList
' to selectionTester.
lassoPath = newStroke
lassoPath.DrawingAttributes = selectDA.Clone()
presenter.Strokes.Add(lassoPath)
RemoveHandler selectionTester.SelectionChanged, _
AddressOf selectionTester_SelectionChanged
selectionTester.EndHitTesting()
End If
End Sub 'AddStrokeToPresenter
Private Sub selectionTester_SelectionChanged(ByVal sender As Object, _
ByVal args As LassoSelectionChangedEventArgs)
' Change the color of all selected strokes to red.
Dim selectedStroke As Stroke
For Each selectedStroke In args.SelectedStrokes
selectedStroke.DrawingAttributes.Color = Colors.Red
selectedStrokes.Add(selectedStroke)
Next selectedStroke
' Change the color of all unselected strokes to
' their original color.
Dim unselectedStroke As Stroke
For Each unselectedStroke In args.DeselectedStrokes
unselectedStroke.DrawingAttributes.Color = inkDA.Color
selectedStrokes.Remove(unselectedStroke)
Next unselectedStroke
End Sub 'selectionTester_SelectionChanged
' Property to indicate whether the user is inputting or
' selecting ink.
Public Property Mode() As InkMode
Get
Return Mode
End Get
Set(ByVal value As InkMode)
modeState = value
' Set the DrawingAttributes of the DynamicRenderer
If modeState = InkMode.Ink Then
renderer.DrawingAttributes = inkDA
Else
renderer.DrawingAttributes = selectDA
End If
' Reattach the visual of the DynamicRenderer to the InkPresenter.
presenter.DetachVisuals(renderer.RootVisual)
presenter.AttachVisuals(renderer.RootVisual, renderer.DrawingAttributes)
End Set
End Property
Private Sub DrawingAttributesChanged(ByVal sender As Object, _
ByVal e As PropertyDataChangedEventArgs)
' Reattach the visual of the DynamicRenderer to the InkPresenter
' whenever the DrawingAttributes change.
presenter.DetachVisuals(renderer.RootVisual)
presenter.AttachVisuals(renderer.RootVisual, _
renderer.DrawingAttributes)
End Sub 'DrawingAttributesChanged
' Property to allow the user to change the pen's DrawingAttributes.
Public ReadOnly Property InkDrawingAttributes() As DrawingAttributes
Get
Return inkDA
End Get
End Property
' Property to allow the user to change the Selector'newStroke DrawingAttributes.
Public ReadOnly Property SelectDrawingAttributes() As DrawingAttributes
Get
Return selectDA
End Get
End Property
End Class 'InkSelector
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Ink;
// Enum that keeps track of whether StrokeCollectionDemo is in ink mode
// or select mode.
public enum InkMode
{
Ink, Select
}
// This control allows the user to input and select ink. When the
// user selects ink, the lasso remains visible until they erase, or clip
// the selected strokes, or clear the selection. When the control is
// in selection mode, strokes that are selected turn red.
public class InkSelector : Label
{
InkMode mode;
DrawingAttributes inkDA;
DrawingAttributes selectDA;
InkPresenter presenter;
IncrementalLassoHitTester selectionTester;
StrokeCollection selectedStrokes = new StrokeCollection();
// StylusPointCollection that collects the stylus points from the stylus events.
StylusPointCollection stylusPoints;
// Stroke that represents the lasso.
Stroke lassoPath;
DynamicRenderer renderer;
public InkSelector()
{
mode = InkMode.Ink;
// Use an InkPresenter to display the strokes on the custom control.
presenter = new InkPresenter();
this.Content = presenter;
// In the constructor.
// Selection drawing attributes use dark gray ink.
selectDA = new DrawingAttributes();
selectDA.Color = Colors.DarkGray;
// ink drawing attributes use default attributes
inkDA = new DrawingAttributes();
inkDA.Width = 5;
inkDA.Height = 5;
inkDA.AttributeChanged += new PropertyDataChangedEventHandler(DrawingAttributesChanged);
selectDA.AttributeChanged += new PropertyDataChangedEventHandler(DrawingAttributesChanged);
// Add a DynmaicRenderer to the control so ink appears
// to "flow" from the tablet pen.
renderer = new DynamicRenderer();
renderer.DrawingAttributes = inkDA;
this.StylusPlugIns.Add(renderer);
presenter.AttachVisuals(renderer.RootVisual,
renderer.DrawingAttributes);
}
static InkSelector()
{
// Allow ink to be drawn only within the bounds of the control.
Type owner = typeof(InkSelector);
ClipToBoundsProperty.OverrideMetadata(owner,
new FrameworkPropertyMetadata(true));
}
// Prepare to collect stylus packets. If Mode is set to Select,
// get the IncrementalHitTester from the InkPresenter'newStroke
// StrokeCollection and subscribe to its StrokeHitChanged event.
protected override void OnStylusDown(StylusDownEventArgs e)
{
base.OnStylusDown(e);
Stylus.Capture(this);
// Create a new StylusPointCollection using the StylusPointDescription
// from the stylus points in the StylusDownEventArgs.
stylusPoints = new StylusPointCollection();
StylusPointCollection eventPoints = e.GetStylusPoints(this, stylusPoints.Description);
stylusPoints.Add(eventPoints);
InitializeHitTester(eventPoints);
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
Mouse.Capture(this);
if (e.StylusDevice != null)
{
return;
}
Point pt = e.GetPosition(this);
StylusPointCollection collectedPoints = new StylusPointCollection(new Point[] { pt });
stylusPoints = new StylusPointCollection();
stylusPoints.Add(collectedPoints);
InitializeHitTester(collectedPoints);
}
private void InitializeHitTester(StylusPointCollection collectedPoints)
{
// Deselect any selected strokes.
foreach (Stroke selectedStroke in selectedStrokes)
{
selectedStroke.DrawingAttributes.Color = inkDA.Color;
}
selectedStrokes.Clear();
if (mode == InkMode.Select)
{
// Remove the previously drawn lasso, if it exists.
if (lassoPath != null)
{
presenter.Strokes.Remove(lassoPath);
lassoPath = null;
}
selectionTester =
presenter.Strokes.GetIncrementalLassoHitTester(80);
selectionTester.SelectionChanged +=
new LassoSelectionChangedEventHandler(selectionTester_SelectionChanged);
selectionTester.AddPoints(collectedPoints);
}
}
// Collect the stylus packets as the stylus moves.
protected override void OnStylusMove(StylusEventArgs e)
{
if (stylusPoints == null)
{
return;
}
StylusPointCollection collectedPoints = e.GetStylusPoints(this, stylusPoints.Description);
stylusPoints.Add(collectedPoints);
AddPointsToHitTester(collectedPoints);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.StylusDevice != null)
{
return;
}
if (e.LeftButton == MouseButtonState.Released)
{
return;
}
if (stylusPoints == null)
{
stylusPoints = new StylusPointCollection();
}
Point pt = e.GetPosition(this);
StylusPointCollection collectedPoints = new StylusPointCollection(new Point[] { pt });
stylusPoints.Add(collectedPoints);
AddPointsToHitTester(collectedPoints);
}
private void AddPointsToHitTester(StylusPointCollection collectedPoints)
{
if (mode == InkMode.Select &&
selectionTester != null &&
selectionTester.IsValid)
{
// When the control is selecting strokes, add the
// stylus packetList to selectionTester.
selectionTester.AddPoints(collectedPoints);
}
}
// When the user lifts the stylus, create a Stroke from the
// collected stylus points and add it to the InkPresenter.
// When the control is selecting strokes, add the
// point data to the IncrementalHitTester.
protected override void OnStylusUp(StylusEventArgs e)
{
if (stylusPoints == null)
{
stylusPoints = new StylusPointCollection();
}
StylusPointCollection collectedPoints =
e.GetStylusPoints(this, stylusPoints.Description);
stylusPoints.Add(collectedPoints);
AddPointsToHitTester(collectedPoints);
AddStrokeToPresenter();
stylusPoints = null;
Stylus.Capture(null);
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (e.StylusDevice != null) return;
if (stylusPoints == null) stylusPoints = new StylusPointCollection();
Point pt = e.GetPosition(this);
StylusPointCollection collectedPoints = new StylusPointCollection(new Point[] { pt });
stylusPoints.Add(collectedPoints);
AddPointsToHitTester(collectedPoints);
AddStrokeToPresenter();
stylusPoints = null;
Mouse.Capture(null);
}
private void AddStrokeToPresenter()
{
Stroke newStroke = new Stroke(stylusPoints);
if (mode == InkMode.Ink)
{
// Add the stroke to the InkPresenter.
newStroke.DrawingAttributes = inkDA.Clone();
presenter.Strokes.Add(newStroke);
}
if (mode == InkMode.Select && lassoPath == null)
{
// Add the lasso to the InkPresenter and add the packetList
// to selectionTester.
lassoPath = newStroke;
lassoPath.DrawingAttributes = selectDA.Clone();
presenter.Strokes.Add(lassoPath);
selectionTester.SelectionChanged -= new LassoSelectionChangedEventHandler
(selectionTester_SelectionChanged);
selectionTester.EndHitTesting();
}
}
void selectionTester_SelectionChanged(object sender,
LassoSelectionChangedEventArgs args)
{
// Change the color of all selected strokes to red.
foreach (Stroke selectedStroke in args.SelectedStrokes)
{
selectedStroke.DrawingAttributes.Color = Colors.Red;
selectedStrokes.Add(selectedStroke);
}
// Change the color of all unselected strokes to
// their original color.
foreach (Stroke unselectedStroke in args.DeselectedStrokes)
{
unselectedStroke.DrawingAttributes.Color = inkDA.Color;
selectedStrokes.Remove(unselectedStroke);
}
}
// Property to indicate whether the user is inputting or
// selecting ink.
public InkMode Mode
{
get
{
return mode;
}
set
{
mode = value;
// Set the DrawingAttributes of the DynamicRenderer
if (mode == InkMode.Ink)
{
renderer.DrawingAttributes = inkDA;
}
else
{
renderer.DrawingAttributes = selectDA;
}
// Reattach the visual of the DynamicRenderer to the InkPresenter.
presenter.DetachVisuals(renderer.RootVisual);
presenter.AttachVisuals(renderer.RootVisual, renderer.DrawingAttributes);
}
}
void DrawingAttributesChanged(object sender, PropertyDataChangedEventArgs e)
{
// Reattach the visual of the DynamicRenderer to the InkPresenter
// whenever the DrawingAttributes change.
presenter.DetachVisuals(renderer.RootVisual);
presenter.AttachVisuals(renderer.RootVisual, renderer.DrawingAttributes);
}
// Property to allow the user to change the pen's DrawingAttributes.
public DrawingAttributes InkDrawingAttributes
{
get
{
return inkDA;
}
}
// Property to allow the user to change the Selector'newStroke DrawingAttributes.
public DrawingAttributes SelectDrawingAttributes
{
get
{
return selectDA;
}
}
}