Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This topic provides the complete code sample used in Quickstart: Capturing ink data.
This topic contains these sections:
- Technologies
- Requirements
- View the code ()
Download location
This sample is not available for download.
Technologies
Programming languages | C#, XAML |
Programming models | Windows Runtime |
Requirements
Minimum supported client | Windows 8 |
Minimum supported server | Windows Server 2012 |
Minimum required SDK | Microsoft Visual Studio Express 2012 for Windows 8 |
View the code ()
InkPage.xaml
<Page
x:Class="CaptureInkData.InkPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CaptureInkData"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Page title -->
<Grid x:Name="titlePanel">
<TextBlock x:Name="pageTitle" Text="Capturing ink data" Style="{StaticResource HeaderTextBlockStyle}" Margin="62,0,0,40"/>
</Grid>
<!-- Inking area -->
<Grid x:Name="inkPanel" Grid.Row="1" Margin="0,0,0,61">
<Canvas x:Name="InkCanvas" Background="White" Margin="62,0,62,10" />
</Grid>
</Grid>
</Page>
InkPage.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Input.Inking;
using Windows.Devices.Input;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Xaml.Shapes;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
namespace CaptureInkData
{
public sealed partial class InkPage : Page
{
InkPage rootPage = null;
// Scenario specific constants and variables.
const double STROKETHICKNESS = 5;
Point _previousContactPt;
uint _penID = 0;
uint _touchID = 0;
// Create the InkManager instance.
InkManager _inkManager = new Windows.UI.Input.Inking.InkManager();
public InkPage()
{
this.InitializeComponent();
// Add pointer event handlers to the Canvas object.
InkCanvas.PointerPressed += new PointerEventHandler(InkCanvas_PointerPressed);
InkCanvas.PointerMoved += new PointerEventHandler(InkCanvas_PointerMoved);
InkCanvas.PointerReleased += new PointerEventHandler(InkCanvas_PointerReleased);
InkCanvas.PointerExited += new PointerEventHandler(InkCanvas_PointerReleased);
}
// Initiate ink capture.
public void InkCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Get information about the pointer location.
PointerPoint pt = e.GetCurrentPoint(InkCanvas);
_previousContactPt = pt.Position;
// Accept input only from a pen or mouse with the left button pressed.
PointerDeviceType pointerDevType = e.Pointer.PointerDeviceType;
if (pointerDevType == PointerDeviceType.Pen ||
pointerDevType == PointerDeviceType.Mouse &&
pt.Properties.IsLeftButtonPressed)
{
// Pass the pointer information to the InkManager.
_inkManager.ProcessPointerDown(pt);
_penID = pt.PointerId;
e.Handled = true;
}
else if (pointerDevType == PointerDeviceType.Touch)
{
// Process touch input
}
}
// Draw on the canvas and capture ink data as the pointer moves.
public void InkCanvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == _penID)
{
PointerPoint pt = e.GetCurrentPoint(InkCanvas);
// Render a red line on the canvas as the pointer moves.
// Distance() is an application-defined function that tests
// whether the pointer has moved far enough to justify
// drawing a new line.
Point currentContactPt = pt.Position;
if (Distance(currentContactPt, _previousContactPt) > 2)
{
Line line = new Line()
{
X1 = _previousContactPt.X,
Y1 = _previousContactPt.Y,
X2 = currentContactPt.X,
Y2 = currentContactPt.Y,
StrokeThickness = STROKETHICKNESS,
Stroke = new SolidColorBrush(Windows.UI.Colors.Red)
};
_previousContactPt = currentContactPt;
// Draw the line on the canvas by adding the Line object as
// a child of the Canvas object.
InkCanvas.Children.Add(line);
// Pass the pointer information to the InkManager.
_inkManager.ProcessPointerUpdate(pt);
}
}
else if (e.Pointer.PointerId == _touchID)
{
// Process touch input
}
e.Handled = true;
}
// Finish capturing ink data and use it to render ink strokes on
// the canvas.
public void InkCanvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == _penID)
{
PointerPoint pt = e.GetCurrentPoint(InkCanvas);
// Pass the pointer information to the InkManager.
_inkManager.ProcessPointerUp(pt);
}
else if (e.Pointer.PointerId == _touchID)
{
// Process touch input
}
_touchID = 0;
_penID = 0;
// Call an application-defined function to render the ink strokes.
RenderAllStrokes();
e.Handled = true;
}
// Render ink strokes as cubic bezier segments.
private void RenderAllStrokes()
{
// Clear the canvas.
InkCanvas.Children.Clear();
// Get the InkStroke objects.
IReadOnlyList<InkStroke> inkStrokes = _inkManager.GetStrokes();
// Process each stroke.
foreach (InkStroke inkStroke in inkStrokes)
{
PathGeometry pathGeometry = new PathGeometry();
PathFigureCollection pathFigures = new PathFigureCollection();
PathFigure pathFigure = new PathFigure();
PathSegmentCollection pathSegments = new PathSegmentCollection();
// Create a path and define its attributes.
Windows.UI.Xaml.Shapes.Path path = new Windows.UI.Xaml.Shapes.Path();
path.Stroke = new SolidColorBrush(Colors.Red);
path.StrokeThickness = STROKETHICKNESS;
// Get the stroke segments.
IReadOnlyList<InkStrokeRenderingSegment> segments;
segments = inkStroke.GetRenderingSegments();
// Process each stroke segment.
bool first = true;
foreach (InkStrokeRenderingSegment segment in segments)
{
// The first segment is the starting point for the path.
if (first)
{
pathFigure.StartPoint = segment.BezierControlPoint1;
first = false;
}
// Copy each ink segment into a bezier segment.
BezierSegment bezSegment = new BezierSegment();
bezSegment.Point1 = segment.BezierControlPoint1;
bezSegment.Point2 = segment.BezierControlPoint2;
bezSegment.Point3 = segment.Position;
// Add the bezier segment to the path.
pathSegments.Add(bezSegment);
}
// Build the path geometerty object.
pathFigure.Segments = pathSegments;
pathFigures.Add(pathFigure);
pathGeometry.Figures = pathFigures;
// Assign the path geometry object as the path data.
path.Data = pathGeometry;
// Render the path by adding it as a child of the Canvas object.
InkCanvas.Children.Add(path);
}
}
private double Distance(Point currentContact, Point previousContact)
{
return Math.Sqrt(Math.Pow(currentContact.X - previousContact.X, 2) +
Math.Pow(currentContact.Y - previousContact.Y, 2));
}
#region Template-Related Code - Do not remove
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Get a pointer to our main page
rootPage = e.Parameter as InkPage;
}
#endregion
/// <summary>
/// Handles when the Save button is clicked on the app bar.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
///
async void Save_Click(object sender, RoutedEventArgs e)
{
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add("GIF file", new List<string>() { ".gif" });
savePicker.DefaultFileExtension = ".gif";
savePicker.SuggestedFileName = "New Ink Image";
StorageFile savedItem = await savePicker.PickSaveFileAsync();
if (null != savedItem)
{
WriteInk(savedItem);
}
}
async void WriteInk(StorageFile storageFile)
{
if (storageFile != null)
{
IRandomAccessStream writeStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);
IOutputStream outputStream = writeStream.GetOutputStreamAt(0);
await _inkManager.SaveAsync(outputStream);
await outputStream.FlushAsync();
Windows.Storage.FileProperties.BasicProperties props = await storageFile.GetBasicPropertiesAsync();
// Call an application-defined function to display the file size.
DisplayStatus("Saved " + props.Size.ToString() + " bytes.");
}
}
async void Load_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.List;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Clear();
openPicker.FileTypeFilter.Add(".gif");
StorageFile openedItem = await openPicker.PickSingleFileAsync();
if (null != openedItem)
{
ReadInk(openedItem);
}
}
async void ReadInk(StorageFile storageFile)
{
if (storageFile != null)
{
IRandomAccessStream readStream = await storageFile.OpenAsync(FileAccessMode.Read);
IInputStream inputStream = readStream.GetInputStreamAt(0);
await _inkManager.LoadAsync(inputStream);
IReadOnlyList<InkStroke> strokes = _inkManager.GetStrokes();
int c = strokes.Count;
if (c == 0)
{
DisplayStatus("File does not contain any ink strokes.");
}
else
{
DisplayStatus("Loaded " + c + " strokes.");
RenderAllStrokes();
}
Windows.Storage.FileProperties.BasicProperties props = await storageFile.GetBasicPropertiesAsync();
// Call an application-defined function to display the file size.
DisplayStatus("Loaded " + props.Size.ToString() + " bytes.");
}
}
async void DisplayStatus(String message)
{
Windows.UI.Popups.MessageDialog messagePopup = new Windows.UI.Popups.MessageDialog(message, "Status");
await messagePopup.ShowAsync();
}
}
}