//-------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// File: InkCollection.cs
// Simple Ink Collection Sample Application
//
// This sample program demonstrates how to use a real time stylus
// to collect and render pen input.
//
// The features used are: RealTimeStylus, DynamicRenderer,
// and IStylusAsyncPlugin.
//
//--------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
// The Microsoft Tablet PC namespaces
using Microsoft.Ink;
using Microsoft.StylusInput;
using Microsoft.StylusInput.PluginData;
namespace InkCollection
{
///
/// The InkCollection Sample Application form class
///
public class InkCollection : Form, IStylusAsyncPlugin
{
// Declare constants for the pen widths used by this application.
// Note that these constants are in himetric units (1 unit = .01mm)
private const float ThinInkWidth = 10;
private const float MediumInkWidth = 100;
private const float ThickInkWidth = 200;
// Declare the real time stylus
private RealTimeStylus myRealTimeStylus;
// Declare the renderers. The dynamic renderer is used to render the ink
// stroke that is currently being collected, whereas the static renderer
// is used to render strokes that have already been collected.
private DynamicRenderer myDynamicRenderer;
private Renderer myRenderer;
// Declare the hashtable used to store packet data that is being collected by one
// or more cursors. StylusId's are used as the hashtable key to uniquely
// identify the packet data collected for a given cursor.
private Hashtable myPackets;
// Declare the ink object used to store strokes collected by the real time stylus.
private Ink myInk;
#region Standard Template Code
private System.Windows.Forms.MenuItem miMainFile;
private System.Windows.Forms.MenuItem miExit;
private System.Windows.Forms.MenuItem miMainInk;
private System.Windows.Forms.MenuItem miEnabled;
private System.Windows.Forms.MenuItem miColor;
private System.Windows.Forms.MenuItem miRed;
private System.Windows.Forms.MenuItem miGreen;
private System.Windows.Forms.MenuItem miBlue;
private System.Windows.Forms.MenuItem miBlack;
private System.Windows.Forms.MenuItem miWidth;
private System.Windows.Forms.MenuItem miThin;
private System.Windows.Forms.MenuItem miMedium;
private System.Windows.Forms.MenuItem miThick;
private System.Windows.Forms.MainMenu miMain;
private System.ComponentModel.Container components = null;
#endregion
public InkCollection()
{
#region Standard Template Code
// Required for Windows Form Designer support
InitializeComponent();
#endregion
}
#region Standard Template Code
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Windows Form Designer generated code
///
/// ----- Standard Template Code -----
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.miMain = new System.Windows.Forms.MainMenu();
this.miMainFile = new System.Windows.Forms.MenuItem();
this.miExit = new System.Windows.Forms.MenuItem();
this.miMainInk = new System.Windows.Forms.MenuItem();
this.miEnabled = new System.Windows.Forms.MenuItem();
this.miColor = new System.Windows.Forms.MenuItem();
this.miRed = new System.Windows.Forms.MenuItem();
this.miGreen = new System.Windows.Forms.MenuItem();
this.miBlue = new System.Windows.Forms.MenuItem();
this.miBlack = new System.Windows.Forms.MenuItem();
this.miWidth = new System.Windows.Forms.MenuItem();
this.miThin = new System.Windows.Forms.MenuItem();
this.miMedium = new System.Windows.Forms.MenuItem();
this.miThick = new System.Windows.Forms.MenuItem();
//
// miMain
//
this.miMain.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.miMainFile,
this.miMainInk});
//
// miMainFile
//
this.miMainFile.Index = 0;
this.miMainFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.miExit});
this.miMainFile.Text = "File";
//
// miExit
//
this.miExit.Index = 0;
this.miExit.Text = "Exit";
this.miExit.Click += new System.EventHandler(this.miExit_Click);
//
// miMainInk
//
this.miMainInk.Index = 1;
this.miMainInk.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.miEnabled,
this.miColor,
this.miWidth});
this.miMainInk.Text = "Ink";
//
// miEnabled
//
this.miEnabled.Checked = true;
this.miEnabled.Index = 0;
this.miEnabled.Text = "Enabled";
this.miEnabled.Click += new System.EventHandler(this.miEnabled_Click);
//
// miColor
//
this.miColor.Index = 1;
this.miColor.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.miRed,
this.miGreen,
this.miBlue,
this.miBlack});
this.miColor.Text = "Color";
//
// miRed
//
this.miRed.Index = 0;
this.miRed.Text = "Red";
this.miRed.Click += new System.EventHandler(this.miRed_Click);
//
// miGreen
//
this.miGreen.Index = 1;
this.miGreen.Text = "Green";
this.miGreen.Click += new System.EventHandler(this.miGreen_Click);
//
// miBlue
//
this.miBlue.Index = 2;
this.miBlue.Text = "Blue";
this.miBlue.Click += new System.EventHandler(this.miBlue_Click);
//
// miBlack
//
this.miBlack.Index = 3;
this.miBlack.Text = "Black";
this.miBlack.Click += new System.EventHandler(this.miBlack_Click);
//
// miWidth
//
this.miWidth.Index = 2;
this.miWidth.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.miThin,
this.miMedium,
this.miThick});
this.miWidth.Text = "Width";
//
// miThin
//
this.miThin.Index = 0;
this.miThin.Text = "Thin";
this.miThin.Click += new System.EventHandler(this.miThin_Click);
//
// miMedium
//
this.miMedium.Index = 1;
this.miMedium.Text = "Medium";
this.miMedium.Click += new System.EventHandler(this.miMedium_Click);
//
// miThick
//
this.miThick.Index = 2;
this.miThick.Text = "Thick";
this.miThick.Click += new System.EventHandler(this.miThick_Click);
//
// InkCollection
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 245);
this.Menu = this.miMain;
this.Name = "InkCollection";
this.Text = "RTS Ink Collection Sample";
this.Load += new System.EventHandler(this.InkCollection_Load);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.InkCollection_Paint);
}
#endregion
#region Standard Template Code
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.Run(new InkCollection());
}
#endregion
///
/// Event Handler from Form Load Event
/// Set up the real time stylus for collection
///
/// The control that raised the event.
/// The event arguments.
private void InkCollection_Load(object sender, System.EventArgs e)
{
// Create the renderers. The dynamic renderer is used to render the ink
// stroke that is currently being collected, whereas the static renderer
// is used to render strokes that have already been collected.
myDynamicRenderer = new DynamicRenderer(this);
myRenderer = new Renderer();
//
// If you do not modify the default drawing attributes, the default
// drawing attributes will use the following properties and values:
//
// AntiAliased = true
// Color = black
// FitToCurve = false
// Height = 1
// IgnorePressure = false
// PenTip = ball
// RasterOperation = copy pen
// Transparency = 0
// Width = 53 (2 pixels on a 96 dpi screen)
//
// For an example of how to modify other drawing attributes, uncomment
// the following lines of code:
// myDynamicRenderer.DrawingAttributes.PenTip = PenTip.Rectangle;
// myDynamicRenderer.DrawingAttributes.Height = (.5F)*MediumInkWidth;
// myDynamicRenderer.DrawingAttributes.Transparency = 128;
//
// Create the real time stylus used to receive stylus notifications
myRealTimeStylus = new RealTimeStylus(this, true);
// Add the dynamic renderer to the synchronous plugin notification chain.
// Synchronous notifications occur on the pen thread.
myRealTimeStylus.SyncPluginCollection.Add(myDynamicRenderer);
// Add the form to the asynchronous plugin notification chain. This plugin
// will be used to collect stylus data into an ink object. Asynchronous
// notifications occur on the UI thread.
myRealTimeStylus.AsyncPluginCollection.Add(this);
// Enable the real time stylus and the dynamic renderer
myRealTimeStylus.Enabled = true;
myDynamicRenderer.Enabled = true;
// Create the ink object used to store ink collected from the real time stylus
myPackets = new Hashtable();
myInk = new Ink();
}
///
/// Event Handler from the form Paint event.
///
/// The control that raised the event.
/// The event arguments.
private void InkCollection_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// Refresh the dynamic renderer, since it's possible that a stroke is being
// collected at the time Paint occurs. In this case, the portion of the stroke
// that has already been collected will need to be redrawn.
myDynamicRenderer.Refresh();
// Use the static renderer to redraw strokes that have already been collected.
myRenderer.Draw(e.Graphics, myInk.Strokes);
}
#region Menu Event Handlers
///
/// Event Handler from Ink->Color->Red Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miRed_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Color = Color.Red;
}
///
/// Event Handler from Ink->Color->Green Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miGreen_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Color = Color.Green;
}
///
/// Event Handler from Ink->Color->Blue Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miBlue_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Color = Color.Blue;
}
///
/// Event Handler from Ink->Color->Black Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miBlack_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Color = Color.Black;
}
///
/// Event Handler from Ink->Width->Thin Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miThin_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Width = ThinInkWidth;
}
///
/// Event Handler from Ink->Width->Medium Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miMedium_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Width = MediumInkWidth;
}
///
/// Event Handler from Ink->Width->Thick Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miThick_Click(object sender, System.EventArgs e)
{
myDynamicRenderer.DrawingAttributes.Width = ThickInkWidth;
}
///
/// Event Handler from File->Exit Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miExit_Click(object sender, System.EventArgs e)
{
myRealTimeStylus.Enabled = false;
Application.Exit();
}
///
/// Event Handler from Ink->Enabled Menu Item
///
/// The control that raised the event.
/// The event arguments.
private void miEnabled_Click(object sender, System.EventArgs e)
{
// Toggle the enabled state of the real time stylus
myRealTimeStylus.Enabled = !myRealTimeStylus.Enabled;
miEnabled.Checked = myRealTimeStylus.Enabled;
}
#endregion
#region IStylusAsyncPlugin interface implementation
///
/// Occurs when the stylus touches the digitizer surface.
/// Allocate a new array to store the packet data for this stylus.
///
/// The real time stylus associated with the notification
/// The notification data
public void StylusDown(RealTimeStylus sender, StylusDownData data)
{
// Allocate an empty array to store the packet data that will be
// collected for this stylus.
ArrayList collectedPackets = new ArrayList();
// Add the packet data from StylusDown to the array
collectedPackets.AddRange(data.GetData());
// Insert the array into a hashtable using the stylus id as a key.
myPackets.Add(data.Stylus.Id, collectedPackets);
}
///
/// Occurs when the stylus moves on the digitizer surface.
/// Add new packet data into the packet array for this stylus.
///
/// The real time stylus associated with the notification
/// The notification data
public void Packets(RealTimeStylus sender, PacketsData data)
{
// Use the stylus id as a key to retrieve the packet array for the
// stylus. Insert the new packet data into this array.
((ArrayList)(myPackets[data.Stylus.Id])).AddRange(data.GetData());
}
///
/// Occurs when the stylus leaves the digitizer surface.
/// Retrieve the packet array for this stylus and use it to create
/// a new stoke.
///
/// The real time stylus associated with the notification
/// The notification data
public void StylusUp(RealTimeStylus sender, StylusUpData data)
{
// Retrieve the packet array from the hashtable using the cursor id
// as a key. Then, clean this entry from the hash since it is no
// longer needed.
ArrayList collectedPackets = (ArrayList)myPackets[data.Stylus.Id];
myPackets.Remove(data.Stylus.Id);
// Add the packet data from StylusUp to the array
collectedPackets.AddRange(data.GetData());
// Create the stroke using the specified drawing attributes.
int[] packets = (int[])(collectedPackets.ToArray(typeof(int)));
TabletPropertyDescriptionCollection tabletProperties = myRealTimeStylus.GetTabletPropertyDescriptionCollection(data.Stylus.TabletContextId);
Stroke stroke = myInk.CreateStroke(packets, tabletProperties);
if (stroke != null)
{
stroke.DrawingAttributes.Color = myDynamicRenderer.DrawingAttributes.Color;
stroke.DrawingAttributes.Width = myDynamicRenderer.DrawingAttributes.Width;
}
}
///
/// Called when the current plugin or the ones previous in the list
/// threw an exception.
///
/// The real time stylus
/// Error data
public void Error(RealTimeStylus sender, ErrorData data)
{
Debug.Assert(false, null, "An error occurred. DataId=" + data.DataId + ", " + "Exception=" + data.InnerException);
}
///
/// Defines the types of notifications the plugin is interested in.
///
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown |
DataInterestMask.Packets |
DataInterestMask.StylusUp |
DataInterestMask.Error;
}
}
// The remaining interface methods are not used in this sample application.
public void RealTimeStylusDisabled(RealTimeStylus sender, RealTimeStylusDisabledData data) {}
public void RealTimeStylusEnabled(RealTimeStylus sender, RealTimeStylusEnabledData data){}
public void StylusOutOfRange(RealTimeStylus sender, StylusOutOfRangeData data) {}
public void StylusInRange(RealTimeStylus sender, StylusInRangeData data) {}
public void StylusButtonDown(RealTimeStylus sender, StylusButtonDownData data) {}
public void StylusButtonUp(RealTimeStylus sender, StylusButtonUpData data) {}
public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data){}
public void SystemGesture(RealTimeStylus sender, SystemGestureData data){}
public void InAirPackets(RealTimeStylus sender, InAirPacketsData data){}
public void TabletAdded(RealTimeStylus sender, TabletAddedData data){}
public void TabletRemoved(RealTimeStylus sender, TabletRemovedData data) {}
#endregion
}
}