Ink support for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

Ink refers to handwriting or drawing content that has been input with a stylus or by touch. Windows Phone apps can support ink by using the InkPresenter element.

This topic contains the following sections.

Getting started with ink in Windows Phone

The following illustration shows InkPresenter displaying ink strokes.

InkPresenter element

The InkPresenter element provides a drawing surface to support ink features. InkPresenter derives from Canvas and can display one or more UIElement objects and a StrokeCollection.

The following code example shows how you can create an InkPresenter element in XAML.

<Canvas>
    <TextBlock Text="InkPresenter Control" FontWeight="Bold" Margin="50,30,0,0" />
    <Rectangle Height="500" Width="500" Margin="50,50,0,0" Stroke="Black" />
    <InkPresenter x:Name="MyIP" Height="500" Width="500"
              Margin="50,50,0,0"
              MouseLeftButtonDown="MyIP_MouseLeftButtonDown" 
              LostMouseCapture="MyIP_LostMouseCapture" 
              MouseMove="MyIP_MouseMove" 
              Background="Transparent" Opacity="1" />
</Canvas>

In the preceding example, a Rectangle is added to the Canvas with the same margin as the InkPresenter element. This is because the InkPresenter does not have properties to provide visual boundaries. The Stroke property of the Rectangle is set to Black, which acts as the border for the InkPresenter. The z-order of the InkPresenter must be higher than that of the Rectangle. Otherwise, the Rectangle will hide the InkPresenter.

Ink data

Ink in Windows Phone is a StrokeCollection object, which contains individual Stroke objects. Each Stroke corresponds to a stylus-down, stylus-move, and stylus-up sequence. A Stroke can be a dot, a straight line, or a curving line. Each Stroke contains a StylusPointCollection object, which contains individual StylusPoint objects. StylusPoint objects are collected when the stylus moves while it is in contact with the digitizer. The Stroke also has characteristics, such as height, width, color, and outline color, all of which are contained in the DrawingAttributes class.

Collecting ink

You can create or capture strokes programmatically by responding to the events on the InkPresenter. The events to handle are MouseLeftButtonDown, MouseMove, and LostMouseCapture.

When the InkPresenter element receives a MouseLeftButtonDown event, a new Stroke object is created and added to the StrokeCollection object of the InkPresenter element. When the stylus moves while it is in contact with the screen, the MouseMove event is called and StylusPoint objects are collected and added to that Stroke. When the LostMouseCapture event is raised, the Stroke created is completed.

Code example

The following code example shows basic techniques for capturing input on an InkPresenter surface and using the input to create strokes for display.

public Page()
{
    InitializeComponent();
    SetBoundary();
}
Stroke NewStroke;

//A new stroke object named MyStroke is created. MyStroke is added to the StrokeCollection of the InkPresenter named MyIP
private void MyIP_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
    MyIP.CaptureMouse();
    StylusPointCollection MyStylusPointCollection = new StylusPointCollection();
    MyStylusPointCollection.Add(e.StylusDevice.GetStylusPoints(MyIP));
    NewStroke = new Stroke(MyStylusPointCollection);
    MyIP.Strokes.Add(NewStroke);
}

//StylusPoint objects are collected from the MouseEventArgs and added to MyStroke. 
private void MyIP_MouseMove(object sender, MouseEventArgs e)
{
    if (NewStroke != null)
        NewStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(MyIP));
}

//MyStroke is completed
private void MyIP_LostMouseCapture(object sender, MouseEventArgs e)
{
    NewStroke = null;
    
}

//Set the Clip property of the inkpresenter so that the strokes
//are contained within the boundary of the inkpresenter
private void SetBoundary()
{
    RectangleGeometry MyRectangleGeometry = new RectangleGeometry();
    MyRectangleGeometry.Rect = new Rect(0, 0, MyIP.ActualWidth, MyIP.ActualHeight);
    MyIP.Clip = MyRectangleGeometry;
}
Public Sub New()
    MyBase.New()
    InitializeComponent()
    SetBoundary()
End Sub

'A new stroke object, MyStroke, is created and is added to the StrokeCollection object
'of the InkPresenter, MyIP
Private Sub MyIP_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseEventArgs)
    MyIP.CaptureMouse()
    Dim MyStylusPointCollection As StylusPointCollection = New StylusPointCollection
    MyStylusPointCollection.Add(e.StylusDevice.GetStylusPoints(MyIP))
    NewStroke = New Stroke(MyStylusPointCollection)
    MyIP.Strokes.Add(NewStroke)
End Sub

'StylusPoint objects are collected from the MouseEventArgs and added to MyStroke. 
Private Sub MyIP_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
    If (Not (NewStroke) Is Nothing) Then
        NewStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(MyIP))
    End If
End Sub

'MyStroke is completed
Private Sub MyIP_LostMouseCapture(ByVal sender As Object, ByVal e As MouseEventArgs)
    NewStroke = Nothing
End Sub

'Set the Clip property of the inkpresenter so that the strokes
'are contained within the boundary of the inkpresenter
Private Sub SetBoundary()
    Dim MyRectangleGeometry As RectangleGeometry = New RectangleGeometry
    MyRectangleGeometry.Rect = New Rect(0, 0, MyIP.ActualWidth, MyIP.ActualHeight)
    MyIP.Clip = MyRectangleGeometry
End Sub

You can accomplish the following InkPresenter-related tasks with the example code at the specified location.

Task

Example location

Use the InkPresenter element.

InkPresenter

Specify drawing attributes, such as height, width, color, and outline color.

DrawingAttributes

Iterate through the stylus points and manipulate the stroke collection.

StylusPoints

Use the properties of a stylus point, such as X coordinate, Y coordinate, and pressure.

StylusPoint

Retrieve the bounding box for a stroke.

Stroke..::.GetBounds

Retrieve the bounding box for a stroke collection.

StrokeCollection..::.GetBounds

Determine whether stroke objects intersect.

Stroke..::.HitTest

Determine whether stroke collections intersect.

StrokeCollection..::.HitTest