Share via


Persisting Ink with Attached Recognition Data

 

Jonathan Fingold
Microsoft Corporation

April 2003

Applies to:
    Microsoft® Tablet PC Platform SDK

Summary: Learn how to store and persist recognition data with ink by using the Microsoft Tablet PC Platform SDK version 1.5. Readers should be familiar with the Tablet PC Platform SDK and managed code. (6 printed pages)

Download the sample C# application for this article.

Contents

Introduction
Why Persist Recognition Results?
The ExtendedProperties and CustomStrokes Collections
How to Persist Recognition Results with the Ink Object

Introduction

This article discusses two ways of saving recognition data with your Ink object. Both of these methods are supported by the Microsoft® Tablet PC Platform API. Both of these methods preserve the data when you copy the Ink object to the Clipboard or when you save the Ink object. The first method uses the Ink object's CustomStrokes property. The second method uses the Ink object's ExtendedProperties property.

This article does not discuss how to perform handwriting recognition. For information about handwriting recognition, see the Multiple Recognizers Sample topic. Also, this article does not discuss how to keep the saved recognition data synchronized with the Ink object.

To compile and run the sample associated with this article on Windows XP Professional, you must have the Tablet PC Platform SDK installed. For more information about the Tablet PC Platform, see the Windows XP Tablet PC Platform SDK documentation.

Why Persist Recognition Results?

Reasons to persist recognition information with the Ink object include:

  • Text recognition may place intense demands on processors. It is more efficient for you to perform recognition once and save the recognition data than it is to recognize ink multiple times if the Ink object has not changed.
  • If you modify the recognition result and persist the Ink object, then the modified recognition result is lost unless you also persist the recognition data. One example of this is if you provide a user interface for correcting the recognition results, and then use that information to modify one or more of the recognition alternates, such as the top alternate, or the top alternate string.

Some of the considerations when you are designing an application that persists recognition information include:

  • Persisting recognition information increases your application's complexity. Your application has to determine when existing results are available and if the underlying ink has changed and new results are required.
  • The recognition information increases the size of the persisted Ink object.
  • The recognition information your application persists may not be recognized by or applicable to other applications. For each persistence format, decide what information should be kept and what should be removed when the Ink object is persisted.

The ExtendedProperties and CustomStrokes Collections

In the CustomStrokes collection each element in the collection is a Strokes collection that is identified by a string. In the ExtendedProperties collection each element in the collection is an object that is identified by a globally unique identifier (GUID).

You use the Ink object's ExtendedProperties property to persist the top alternate string. Each ExtendedProperty object consists of an application-defined GUID and associated application-defined data, such as the top alternate. The ExtendedProperties property of an Ink object is persisted with the Ink object. For more information about the ExtendedProperties collection, see ExtendedProperties Collection in the Tablet PC Platform SDK. For more information about the objects supported by the ExtendedProperties collection, see ExtendedProperties.Add in the Tablet PC Platform SDK.

You can use the CustomStrokes collection to save a Strokes collection to which you have assigned a recognition result. The CustomStrokes collection contains named Strokes collections. The CustomStrokes property of an Ink object is persisted with the Ink object. For more information about the CustomStrokes collection, see CustomStrokes Collection in the Tablet PC Platform SDK.

How to Persist Recognition Results with the Ink Object

Two common ways of persisting an Ink object are copying the Ink object to the Clipboard and saving the Ink object to a file. Both the Ink object's CustomStrokes and ExtendedProperties properties are persisted as part of the Ink object.

For more information about copying ink to and pasting ink from the Clipboard, see Ink.ClipboardCopy and Ink.ClipboardPaste in the Tablet PC Platform SDK. For more information about saving ink to and loading ink from a format that can be persisted, see Ink.Save and Ink.Load in the Tablet PC Platform SDK.

The following C# examples are taken from the sample application for this article.

Obtaining a RecognitionResult Object

Before recognition data can be added to the Ink object, you need to obtain a recognition result for the ink. First, you need to create a recognizer context for your application. Then, you obtain a recognition result for the ink.

To Obtain a Recognition Result for the Ink Object

  1. See if there are strokes in the Ink object to recognize. The RecognizerContext.Recognize method throws an exception if the recognizer context has an empty Strokes collection.
  2. Assign the Strokes collection from the Ink object to the recognizer context
  3. Use the Recognize method of the recognizer context to generate a RecognitionResult object.
  4. See if any errors occurred during recognition. If errors occurred, the recognition result may not contain accurate data.

Example

In the following example, the default recognizer context is assigned to the RecognizerContext object, _recognizerContext, which is then used to perform handwriting recognition on the strokes in the Ink object, _theInk.

// Create the default recognizer context.
_recognizerContext = new RecognizerContext(); 

// ...

// If there are strokes to recognize,
if (0 < _theInk.Strokes.Count)
{
    // Assign the strokes to the recognizer context.
    _recognizerContext.Strokes = _theInk.Strokes;

    // Perform the recognition on the strokes.
    RecognitionStatus theStatus;
    _recognitionResult =
        _recognizerContext.Recognize(out theStatus);

    // If there was an error in recognition,
    if (RecognitionStatus.NoError != theStatus)
    {
        // Discard the recognition result.
        _recognitionResult = null;
    }
}
else
{
    // Otherwise, clear the recognition result.
    _recognitionResult = null;
}

Using the CustomStrokes Collection

To add a recognition result to the CustomStrokes collection of an Ink object, you need to attach the recognition result to the Strokes collection on which the recognition was performed. Then, remove the previous recognition result from the Ink object's CustomStrokes collection and add the current result to the CustomStrokes collection.

To Add Recognition Data by Using the CustomStrokes Collection

  1. Use the RecognitionResult object's SetResultOnStrokes method to attach the recognition result to the Strokes collection that generated the recognition result.

  2. Add this Strokes collection to the Ink object's CustomStrokes property by using the CustomStrokes collection's Add method.

    The Add method takes two arguments: a string to identify the Strokes collection and the Strokes collection. Be sure to use the Strokes collection from the recognizer context, as this is the collection to which the RecognitionResult object is attached.

The Ink object's CustomStrokes property is persisted any time that the Ink object is persisted.

To Remove a Strokes Collection from the CustomStrokes Collection

Use the CustomStrokes collection's Remove or Clear methods. The Remove method removes a single, named Strokes collection. The Clear method removes all Strokes collections from the CustomStrokes collection.

Example

In the following example, the string, "FullResult", is used to identify the Strokes collection to which the recognition result is attached.

// Attach the recognition result to the Strokes collection
// that generated the result.
_recognitionResult.SetResultOnStrokes();

// Remove the recognition result element from the 
// CustomStrokes collection.
try
{
    _theInk.CustomStrokes.Remove("FullResult");
}
catch (ArgumentException)
{
    // The indexer throws an argument exception if the element
    // does not exist.
}

// Add the recognition result to the CustomStrokes collection.
_theInk.CustomStrokes.Add(
     "FullResult",
    _recognitionResult.Strokes);

Using the ExtendedProperties Collection

To add the top alternate string to the ExtendedProperties collection of an Ink object, you need a GUID to identify the extended property for the top alternate string. Then, you need to remove the previous extended property for the top alternate string and add a new extended property with the current top alternate string.

To Add Recognition Data by Using the ExtendedProperties Collection

Use the ExtendedProperties collection's Add method to store the top alternate string for the Ink object in the Ink object's ExtendedProperties property. Generate a GUID for your application or set of applications that need to access the ExtendedProperty object you are creating.

The Ink object's ExtendedProperties property is persisted any time that the Ink object is persisted.

To Remove an ExtendedProperty Object from the ExtendedProperties Collection

Use the ExtendedProperties collection's Remove or Clear methods. The Remove method removes a single property identified by a GUID. The Clear method removes all ExtendedProperty objects from the ExtendedProperties collection.

Example

The following example shows how to replace an extended property that contains the top alternate string.

Note   Generate a unique GUID for your application. If your application shares data with another application by using the ExtendedProperties collection, the two applications must use the same GUID to identify the ExtendedProperty object containing the data.

// Create the GUID for the extended property that will hold
// the top alternate string.
private static readonly Guid _topAlternateGuid =
   new Guid("ffe934ef-99ad-4e14-b71a-ee29eecf990d");

// ...
 
// If the ExtendedProperties collection is not empty, then
// remove the element from the collection.
if (_theInk.ExtendedProperties.Contains(_topAlternateGuid))
{
   _theInk.ExtendedProperties.Remove(_topAlternateGuid);
}

// Add the top alternate string to the ExtendedProperties
// collection.
_theInk.ExtendedProperties.Add(
   _topAlternateGuid,
   _recognitionResult.TopString);