Mobile Ink Library Custom Controls

August 11, 2007 — Leave a comment

In the previous posts we went through a technical overview of the Mobile Ink Library and the samples that are included.  In this post we will go through the functionality of the InkCanvas, InkPicture, InkRecognizer, InkSignature and InkControlBase classes.


The Mobile Ink Library consists of four controls to make it easier for the developer to ink enable a .NET Compact Framework application.  Using the IInkOverlay is pretty straight forward, but to simplify the life of the developer various controls were created to ink enable .NET Compact Framework applications using Windows Mobile 6.0.


InkControlBase is the abstract base class in which the InkRecognizer, InkPicture and InkSignature inherit from.  The following is the class diagram of the control:

As you can see from the diagram InkControlBase inherits from System.Windows.Forms.Control.  ‘Inking’ the control is enabled by the InkOverlay internal property which wraps the IInkOverlay interface (for more information on IInkOverlay see the technical overview ).

Since IInkOverlay requires a handle to the window (or control) to attach to, we override the OnHandleCreated() in the InkControlBase class to attach the control.  The following code is used to accomplish this:

You will notice the following line:

m_inkOverlay.IInkOverlay.hWnd = this.HandleInternal;

HandleInternal is an internal virtual property and returns the Handle of the InkControlBase control used to attach to the IInkOverlay. 

Classes inheriting from InkControlBase have the option to override this property to return a different handle.  We will visit this again when we discuss the remaining controls.

InkControlBase provides all the basic functionality such as Clear(), Open() and Save() methods.  These methods internally use the InkOverlay property to make the required calls to IInkOverlay. 


InkRecognizer class was created to allow the developer to recognize ink inputted by a user into plain text and inherits from InkControlBase. 

From the class diagram, you will see that InkRecognizer does not do much except override the ToString() method.  The ToString() method will return the text string that is recognized by the IInkOverlay object using the following code:

From the code above you will notice that InkOverlay internal property is used to access the the IInkDisp, IInkStrokes and IInkRecognitionResults to return the recognized text.  (For more information on text recognition see the technical overview ).  The BasicRecognitionCF sample demonstrates the use of the InkRecognizer control.


InkPicture control allows the developer to add ink to a picture using the standard System.Windows.Forms.PictureBox control.


The InkPicture control is not as straight forward as the InkRecognizer. 

The first difference is InkPicture overrides HandleInternal.  If you recall, HandleInternal provides the handle to which the IInkOverlay object will be attached to.  InkPicture internally has a m_pictureBox field which is the standard PictureBox control used to display an image and we use this the m_pictureBox.Handle to attach to the IInkOverlay object.

The InkPicture control exposes the internal PictureBox control as a property to allow the developer to modify any properties for the picture box.  It also exposes an Image property to get or set the image that is displayed in the PictureBox.


Capturing signatures is a very common requirement for Windows Mobile line of business applications and using and using the Windows Mobile Ink API (or WISP Lite) is a perfect solution.  Since the InkPicture control has the main requirements for capturing signatures (which is really just capturing ink data) it can be used as the base class for InkSignature.


Since this is a signature control, we may want to give some sort of indication to the user to sign.  To do this we can add an image to the control using the Image property.  Below is an example of what that could possibly look like:

The InkSignature control also exposes a FirstName, LastName and DateSigned property.  These class properties are saved as ExtendedProperties within the Ink Serialized Format (ISF) file (for more information on extended properties see technical overview) when the signature data is saved. Be aware that these properties are only saved when the ink data is saved using ISF and won’t be saved if saved to a GIF file.  The InkSerializationCF Sample demonstrates the use of the InkSignature control.

InkControlBase Workarounds 

During the development of these control, it was found that IInkOverlay behaved differently in managed code than it did in native code.  Whenever a user started inking on the signature control, the InkSignature control could never lose focus by tapping on any part of the screen (for example the Textbox).  Specifically, the Capture property of the control was set to True whenever a user started inking which caused other controls to not receive any Click events.  It was also noticed that the InkControlBase control would never receive focus when clicked on because of IInkOverlay.

To work around this we implemented some code in the OnMouseDown and OnMouseUp of the InkControlBase. 

Focus Issue

First we’ll look at OnMouseDown which resolves the ‘focus’ issue:

protected override void OnMouseDown(MouseEventArgs e)
    if (this.ClientRectangle.Contains(e.X, e.Y))

From the code above you can see that on mouse down we check to see if we are in the bounds of the control, if we are we call OnMouseDownInternal().

OnMouseDownInternal() will call the Foucs() method on the BoundingControl.  In the case of InkRecognizer it calls the InkControlBase implementation which returns this.

In the case if InkPicture and InkSignature, we override the BoundingControl property and return m_pictureBox.

This allows us to set focus to the underlying control and still have the control fire off events like GotFocus.

Capture Issue

The next issue faced was the Capture issue which seemed IInkOverlay always set Capture = true for the bounded control.  To work around this issue we had to override OnMouseUp as follows:

Again from the above code you can see that we call OnMouseUpInternal() where we set the Capture property to false and then send a ‘manual tap’ so the user does not have to tap the screen twice.

The SendTap() method makes a native call to mouse_event to manually send another tap to the screen since the first tap (or click) was consumed by the InkBaseControl.


The InkCanvas control was discussed briefly in the technical overview but we will go through it again since it’s a custom control part of the Mobile Ink Library.  The InkCanvas control is a managed wrapper to the native InkCanvas control available on Windows Mobile 6.  The InkCanvas control gives you the ability to add inking capabilities to your Compact Framework application on the Windows Mobile 6 platform without the need to use any of the COM interfaces. 

Here is the class diagram of InkCanvas:

From the above class diagram you can see there are three different modes that the InkCanvas can be set to. 

  1. INK – Sets the InkCanvas to inking mode and allows the collection of ink data
  2. SELECT – Sets the InkCanvas control select ink strokes collected
  3. DELETE – Sets the InkCanvas to delete ink strokes as the user taps on the stroke

There is also a PenStyle property which allows you to change the size, color, width and pen type of the stroke being collected.  If you need to interact with the IInkDisp interface, you can also use the Ink property and use the COM interfaces available.  The main method of communication with the native InkCanvas is via windows messages.  Since the InkCanvas control inherits from the OpenNETCF.Windows.Forms.Control2 class, Control2 helps simplify the creation of native control and capture any messages such as StrokeAdded. This allows us to raise relevant events such as StrokeAdded, StrokeDeleted and CharacterAdded. For more information on using Control2 see here.  The InkNotesCF Sample demonstrates the use of InkCanvas control.

Next up we will be looking at Sharing Ink on the Desktop and Windows Mobile.

No Comments

Be the first to start the conversation.

Leave a Reply