Get Control and Performance with the Real Time Stylus API Standard Ink collection is incredibly easy using the Tablet PC SDK. For scenarios that require more control or non-default behavior, default Ink collection may not be the best choice. The Real Time Stylus API provides lower-level, higher performance access to stylus input, making this the API of choice for power-developers. Many Tablet PC applications can do everything they need to do using Tablet PC SDK controls and classes such as the InkCollector and InkOverlay. These objects fully automate the collection of Ink information received from the stylus (pen), rendering that Ink on the screen, and even collecting that Ink into memory using Ink objects, stroke collections, and data points. These objects are great for the most fundamental thing Tablet PCs can do: collecting digital Ink. | " | The Real Time Stylus API is all about control and performance.
| " |
There are many scenarios where a developer might want to have more control over this process, or perhaps apply a different behavior and use the stylus for things other than collecting Ink, or maybe to collect and draw Ink in a non-standard fashion. There also are many scenarios where the performance of standard Ink collectors is not sufficient. Examples include games, 3D applications where the stylus is used to move objects around, and other real-time applications. For all these needs, the Tablet PC SDK version 1.7 introduced a new way of getting to pen data: the Real Time Stylus. The Real Time Stylus API is very simple in concept. The digitizer collects data from the hardware and passes the information on to a collection of registered objects. These objects are known as stylus plug-in objects. There are two kinds of those plug-in objects: those that implement the IStylusSyncPlugin interface, and those that implement IStylusAsyncPlugin. These two object types are very similar in functionality. For the first examples, I will focus on IStylusSyncPlugin. The Basic Implementation To create a project implementing an object that reacts to real-time stylus events, create a standard VB.NET or C# project, and include the Microsoft.Ink (also known as Tablet PC SDK) assembly/namespace in your references. The next step is the creation of an object that can be registered with the digitizer so it can be called whenever the pen triggers some action you are interested in. This object needs to implement the IStylusSyncPlugin interface, which is very simple in concept. It has a number of methods that get called whenever a certain action happens. These methods can conceptually be seen as event handlers. Keep in mind that the Real Time Stylus API is all about performance. For this reason, not all the available methods are called all the time. Instead, each plug-in object must implement a property that indicates which events you are interested in. For instance, if you are interested in all packets (data generated when the pen is used to write or draw) as well as pen up/down events, you can indicate this using the DataInterest property as shown in the following VB.Net example: Public ReadOnly Property DataInterest() _ As DataInterestMask _ Implements IStylusSyncPlugin.DataInterest Get Return DataInterestMask.Packets _ Or DataInterestMask.StylusDown _ Or DataInterestMask.StylusUp End Get End Property
Here is the C# version: public DataInterestMask DataInterest { get { return DataInterestMask.Packets | DataInterestMask.StylusDown | DataInterestMask.StylusUp; } }
A plug-in object configured in this fashion has its Packets(), StylusDown(), and StylusUp() methods called whenever those events occur. They can be used in the following fashion: Public Sub Packets(ByVal s As RealTimeStylus, _ ByVal data As PluginData.PacketsData) _ Implements IStylusSyncPlugin.Packets Console.WriteLine("Packet: X " _ + data(0).ToString() + _ "/ Y " + data(1).ToString()) End Sub
Public Sub StylusDown(ByVal s As RealTimeStylus, _ ByVal data As PluginData.StylusDownData) _ Implements IStylusSyncPlugin.StylusDown Console.WriteLine("Stylus Down") End Sub
Public Sub StylusUp(ByVal s As RealTimeStylus, _ ByVal data As PluginData.StylusUpData) _ Implements IStylusSyncPlugin.StylusUp Console.WriteLine("Stylus Up") End Sub
The C# version is very similar: public void Packets(RealTimeStylus sender, PacketsData data) { Console.WriteLine("Packet: X " + data[0].ToString() + "/ Y " + data[1].ToString()); }
public void StylusDown(RealTimeStylus sender, StylusDownData data) { Console.WriteLine("Stylus Down"); }
public void StylusUp(RealTimeStylus sender, StylusUpData data) { Console.WriteLine("Stylus Up"); }
Listings 1 and 2 show the complete implementation of this simple Real Time Stylus plug-in. | & | | 
By: Markus Egger
Markus is an international speaker, having presented sessions at numerous conferences in North & South America and Europe. Markus has written many articles for publications including CoDe Magazine, Visual Studio Magazine, MSDN Brazil, asp.net Pro, FoxPro Advisor, Fuchs, FoxTalk and Microsoft Office & Database Journal. Markus is the publisher of CoDe Magazine.
Markus is also the President and Chief Software Architect of EPS Software Corp., a custom software development and consulting firm located Houston, Texas. He specializes in consulting for object-oriented development, Internet development, B2B, and Web Services. EPS does most of development using Microsoft Visual Studio (.NET). EPS has worked on software projects for Fortune 500 companies including Philip Morris, Qualcomm, Shell, and Microsoft. Markus has also worked as a contractor on the Microsoft Visual Studio team, where he was mostly responsible for object modeling and other object- and component-related technologies.
Markus received the Microsoft MVP Award (1996-2006) for his contributions to the developer community. Visual LandPro, one of the applications Markus was responsible for, was nominated three times in the Microsoft Excellence Awards.
megger@eps-software.com
megger@eps-software.com | Fast Facts | | The Real Time Stylus API provides an alternate way to receive input from a pen. It is a high performance API that provides a great level of control to developers for a small penalty in added effort. | |
|
| Listing 1: The VB.NET version of a simple Real Time Stylus plug-in | Imports Microsoft.StylusInput
Public Class SimpleStylus Implements IStylusSyncPlugin
Public ReadOnly Property DataInterest() _ As DataInterestMask _ Implements IStylusSyncPlugin.DataInterest Get Return DataInterestMask.Packets _ Or DataInterestMask.StylusDown _ Or DataInterestMask.StylusUp End Get End Property
Public Sub Packets(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.PacketsData) _ Implements IStylusSyncPlugin.Packets Console.WriteLine("Packet: X " _ + data(0).ToString() + _ "/ Y " + data(1).ToString()) End Sub
Public Sub StylusDown(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.StylusDownData) _ Implements IStylusSyncPlugin.StylusDown Console.WriteLine("Stylus Down") End Sub
Public Sub StylusUp(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.StylusUpData) _ Implements IStylusSyncPlugin.StylusUp Console.WriteLine("Stylus Up") End Sub
Public Sub CustomStylusDataAdded( _ ByVal sender As RealTimeStylus, _ ByVal data As PluginData.CustomStylusData) _ Implements IStylusSyncPlugin.CustomStylusDataAdded End Sub Public Sub [Error](ByVal sender As RealTimeStylus, _ ByVal data As PluginData.ErrorData) _ Implements IStylusSyncPlugin.Error End Sub Public Sub InAirPackets(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.InAirPacketsData) _ Implements IStylusSyncPlugin.InAirPackets End Sub Public Sub RealTimeStylusDisabled( _ ByVal sender As RealTimeStylus, _ ByVal data As PluginData.RealTimeStylusDisabledData) _ Implements IStylusSyncPlugin.RealTimeStylusDisabled End Sub Public Sub RealTimeStylusEnabled( _ ByVal sender As RealTimeStylus, _ ByVal data As PluginData.RealTimeStylusEnabledData) _ Implements IStylusSyncPlugin.RealTimeStylusEnabled End Sub Public Sub StylusButtonDown( _ ByVal sender As RealTimeStylus, _ ByVal data As PluginData.StylusButtonDownData) _ Implements IStylusSyncPlugin.StylusButtonDown End Sub Public Sub StylusButtonUp(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.StylusButtonUpData) _ Implements IStylusSyncPlugin.StylusButtonUp End Sub Public Sub StylusInRange(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.StylusInRangeData) _ Implements IStylusSyncPlugin.StylusInRange End Sub Public Sub StylusOutOfRange(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.StylusOutOfRangeData) _ Implements IStylusSyncPlugin.StylusOutOfRange End Sub Public Sub SystemGesture(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.SystemGestureData) _ Implements IStylusSyncPlugin.SystemGesture End Sub Public Sub TabletAdded(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.TabletAddedData) _ Implements IStylusSyncPlugin.TabletAdded End Sub Public Sub TabletRemoved(ByVal sender As RealTimeStylus, _ ByVal data As PluginData.TabletRemovedData) _ Implements IStylusSyncPlugin.TabletRemoved End Sub End Class
|
| Listing 2: The C# version of a simple Real Time Stylus plug-in | using System; using System.Drawing; using System.Windows.Forms; using Microsoft.StylusInput; using Microsoft.StylusInput.PluginData;
namespace RTSCS { public class SimpleStylus : IStylusSyncPlugin { public DataInterestMask DataInterest { get { return DataInterestMask.Packets | DataInterestMask.StylusDown | DataInterestMask.StylusUp; } }
public void Packets(RealTimeStylus sender, PacketsData data) { Console.WriteLine("Packet: X " + data[0].ToString() + "/ Y " + data[1].ToString()); }
public void StylusDown(RealTimeStylus s, StylusDownData data) { Console.WriteLine("Stylus Down"); }
public void StylusUp(RealTimeStylus s, StylusUpData data) { Console.WriteLine("Stylus Up"); }
public void TabletRemoved(RealTimeStylus sender, TabletRemovedData data) {} public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data) {} public void RealTimeStylusDisabled(RealTimeStylus sender, RealTimeStylusDisabledData data) {} public void StylusOutOfRange(RealTimeStylus sender, StylusOutOfRangeData data) {} public void StylusButtonUp(RealTimeStylus sender, StylusButtonUpData data) {} public void StylusInRange(RealTimeStylus sender, StylusInRangeData data) {} public void RealTimeStylusEnabled(RealTimeStylus sender, RealTimeStylusEnabledData data) {} public void SystemGesture(RealTimeStylus sender, SystemGestureData data) {} public void TabletAdded(RealTimeStylus sender, TabletAddedData data) {} public void Error(RealTimeStylus sender, ErrorData data) {} public void InAirPackets(RealTimeStylus sender, InAirPacketsData data) {} public void StylusButtonDown(RealTimeStylus sender, StylusButtonDownData data) {} } }
|
|