This Quickstart walks you through capturing ink data from an input digitizer.
Objective: After completing this Quickstart you will understand how to use the ink platform to detect and capture input from a pointer device (mouse, pen/stylus, or touch) in a Windows Store app using JavaScript.
Prerequisites
We assume that you can create a basic Windows Store app using JavaScript that uses the Windows Library for JavaScript template.
To complete this tutorial, you need:
- Windows 8 and Microsoft Visual Studio Express 2012 for Windows 8. To download them, see Get the tools.
- A developer license. For instructions, see Get a developer license.
- For instructions on creating your first Windows Store app, see Getting started with Windows Store apps using JavaScript.
- For info on using Windows Library for JavaScript objects and controls, see Quickstart: Adding WinJS controls and styles.
Instructions
1. Set up a drawing surface in your UI
This sample uses an HTML 5 Canvas element as the ink drawing and rendering surface. A canvas is an HTML5 element that acts as a surface for dynamically drawing, rendering, and manipulating graphical elements in a Windows Store app using JavaScript.
Note A Scalable Vector Graphics (SVG) object can also be used.
Here we declare a canvas element with an id of inkCanvas that you'll use to reference the element in JavaScript.
<body> <div id="applicationTitle">Ink sample</div> <div> <canvas id="inkCanvas"></canvas> <div> <button id="load">Load</button> <button id="save">Save</button> <button id="draw">Draw</button> <button id="select">Select</button> <button id="selectall">Select all</button> <button id="erase">Erase</button> <button id="eraseAll">Erase all</button> <button id="recognize" value="selected">Handwriting recognition</button> </div> </div> <div id="modeMessage"></div> <div id="deviceMessage"></div> <div id="statusMessage"></div> </body>
2. Create an ink manager
Initialize an InkManager object that will process and manipulate the ink-related data obtained from the pointer input.
// Create an ink manager.
// InkManager is documented at http://go.microsoft.com/fwlink/?LinkID=260648.
var inkManager = new Windows.UI.Input.Inking.InkManager();
3. Connect your app to the drawing surface
To work with the canvas and its child elements, you need to define two variables. The first is assigned a reference to the canvas element, inkCanvas, using getElementById and the other is assigned the drawing context (a 2-D surface in this case) for the canvas element by calling the getContext method.
// Obtain reference to the specified element. function get(elementId) { return document.getElementById(elementId); }
inkCanvas = get("inkCanvas"); inkContext = inkCanvas.getContext("2d");
4. Attach input event listeners to the drawing surface
Using the reference to the canvas element, attach the following three MSPointerEvent listeners for pointer device input. (The event handler functions identified in this example are discussed later in this Quickstart.)
- MSPointerDown fires when a user presses down on the digitizer surface with a pen or finger, or they click the left button on a mouse.
- MSPointerMove fires when the pointer associated with the MSPointerDown event moves across the canvas.
- MSPointerUp fires when the user lifts the pen or finger from the digitizer surface, or they release the left mouse button.
// Set up the handlers for input processing. inkCanvas.addEventListener("MSPointerDown", onPointerDown, false); inkCanvas.addEventListener("MSPointerMove", onPointerMove, false); inkCanvas.addEventListener("MSPointerUp", onPointerUp, false);
5. Define the event handler functions
In this section, we define the event handlers to be associated with the event listeners that you added in the previous step.
-
MSPointerDown is the event that is used to initiate ink capture.
In this example, the beginPath and moveTo methods are used to set the location in screen coordinates at which to begin displaying the ink data. (Capturing ink and displaying it are two separate actions.) The MSPointerDown event is then processed through
inkManagerby passing the pointer data (currentPoint) of the event to ProcessPointerDown.The global variable,
penID, is used to store the pointerId of the input pointer associated with this event. We'll discuss the need for this later.Note This example filters the pointer input (using the pointerType property) so that ink capture is performed for pen/stylus input and mouse input only when the left button is pressed. Touch input is reserved for manipulating the UI of the app.
function getPointerDeviceType(pId) { var pointerDeviceType; var pointerPoint = Windows.UI.Input.PointerPoint.getCurrentPoint(pId); switch (pointerPoint.pointerDevice.pointerDeviceType) { case Windows.Devices.Input.PointerDeviceType.touch: pointerDeviceType = "Touch"; break; case Windows.Devices.Input.PointerDeviceType.pen: pointerDeviceType = "Pen"; break; case Windows.Devices.Input.PointerDeviceType.mouse: pointerDeviceType = "Mouse"; break; default: pointerDeviceType = "Undefined"; } deviceMessage.innerText = pointerDeviceType; return pointerDeviceType; }// Occurs when the pointer (touch, pen, mouse) is detected by the canvas. // Each stroke begins with onPointerDown. function onPointerDown(evt) { // Get the device type for the pointer input. pointerDeviceType = getPointerDeviceType(evt.pointerId); // Process pen and mouse (with left button) only. Reserve touch for manipulations. if ((pointerDeviceType === "Pen") || ((pointerDeviceType === "Mouse") && (evt.button === 0))) { statusMessage.innerText = pointerDeviceType + " pointer down: Start stroke. " // Process one pointer at a time. if (pointerId === -1) { var current = evt.currentPoint; // Start drawing the stroke. inkContext.beginPath(); inkContext.lineWidth = strokeWidth; inkContext.strokeStyle = strokeColor; inkContext.moveTo(current.position.x, current.position.y); // Add current pointer to the ink manager (begin stroke). inkManager.processPointerDown(current); // The pointer id is used to restrict input processing to the current stroke. pointerId = evt.pointerId; } } else { // Process touch input. } } -
Ink data is captured when an MSPointerMove event occurs.
In the following example, the global variable,
penId, is used to ensure that the pointerId for this event is identical to that of the associated MSPointerDown event. If it's not, the input is ignored and no ink data is captured. This is useful, for example, to filter input from a mouse that is moved accidentally during a pen stroke.The lineTo (using the RawPosition of the pointer as reported by the digitizer) and stroke methods are called to draw and display the ink data immediately as discrete line segments. (Capturing ink and displaying it are two separate actions.) The MSPointerMove event is then processed through
inkManagerby passing the pointer data (currentPoint) of the event to ProcessPointerUpdate.// Mouse: Occurs when the pointer moves. // Pen/Touch: Occurs at a steady rate (approx. 100 messages/second) whether the pointer moves or not. function onPointerMove(evt) { // Process pen and mouse (with left button) only. Reserve touch for manipulations. if ((pointerDeviceType === "Pen") || ((pointerDeviceType === "Mouse") && (evt.button === 0))) { statusMessage.innerText = pointerDeviceType + " pointer move: Draw stroke as lines. " // The pointer Id is used to restrict input processing to the current stroke. // pointerId is updated in onPointerDown(). if (evt.pointerId === pointerId) { var current = evt.currentPoint; // Draw stroke in real time. inkContext.lineTo(current.rawPosition.x, current.rawPosition.y); inkContext.stroke(); // Add current pointer to the ink manager (update stroke). inkManager.processPointerUpdate(current); } } else { // Process touch input. } } -
Ink data capture is complete when an MSPointerUp event occurs.
As in the previous example, this function uses the global variable,
penId, to ensure that the pointerId for this event is identical to that of the associated MSPointerDown and MSPointerMove events. If it's not, the input is ignored and no ink data is captured.The lineTo, stroke, and closePath methods are called to complete and close the path created in the
handlePointerDownfunction. The MSPointerUp event is then processed throughinkManagerby passing the pointer data (currentPoint) of the event to ProcessPointerUp.The
renderAllStrokesfunction in this example is optional and is called to process the ink data and render the raw stroke segments on the canvas element as smooth curves (See How to How to render ink data).// Occurs when the pointer (touch, pen, mouse) is lifted from the canvas. // Each stroke ends with onPointerUp. function onPointerUp(evt) { // Process pen and mouse (with left button) only. Reserve touch for manipulations. if ((pointerDeviceType === "Pen") || ((pointerDeviceType === "Mouse") && (evt.button === 0))) { statusMessage.innerText = pointerDeviceType + " pointer up: Finish stroke. " if (evt.pointerId === pointerId) { // Add current pointer to the ink manager (end stroke). inkManager.processPointerUp(evt.currentPoint); // End live drawing. inkContext.closePath(); // Render strokes using bezier curves. renderAllStrokes(); // Reset pointer Id. pointerId = -1; } } else { // Process touch input. } }
See Related topics at the bottom of this page for links to more complex samples.
6. Complete example
See Capturing ink data complete code.
Summary
You now have a basic idea of how to capture ink data with your Windows Store app.
To see this code in action, build and run the following ink samples at the Windows Store app sample home page:
- Input: simplified ink sample - this sample demonstrates ink functionality such as saving and loading ink, selecting and deleting ink, and converting ink strokes to text through handwriting recognition.
- Input: ink sample - in addition to the functionality demonstrated in Input: simplified ink sample, this sample provides a richer UI and demonstrates how to search within recognition results.
Related topics
- Conceptual
- Responding to pen and stylus input
- Reference
- Windows.Devices.Input
- Windows.UI.Core
- Windows.UI.Input
- Windows.UI.Input.Inking
- Samples (DOM)
- Input: DOM pointer event handling sample
- Samples (Windows Store app APIs)
- Input: Device capabilities sample
- Input: Ink sample
- Input: Simplified ink sample
Build date: 11/29/2012