Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / WPF
Article

Adventures into Ink API using WPF

Rate me:
Please Sign up or sign in to vote.
4.93/5 (59 votes)
7 Jun 200710 min read 253.2K   6.5K   102   62
Adventures into Ink API using WPF

Contents

Introduction

I don't know a lot about you but I am becoming more and more interested in .NET 3.0 and in particular I am drawn to WPF. Up until now I have been mainly crafting my WPF apps such as this or this or this using a combination of Visual Studio 2005 with The Visual Studio Designer for WPF addon, or have been borrowing snippets of code from here and there (Mainly from Josh Smith actually, so thanks Josh if you're reading this), and piecing together a workable solution. Anyway for this article I decided to use Expression BLEND to see what I could create and just how easy it was.

But just what is it that I decided to do this time? Well I recently started to develop a fascination for the Ink API, for which there is a nice Tablet PC SDK available. In Windows Vista (which I am using) the associated APIs are pre-installed, but if you are an XP user you may need to download the SDK which is available here.

That said for this article if you have the .NET 3.0 framework installed, I would think that, that may be sufficient.

Anyway, as I say I have found myself playing with the Ink API and messing about with it a bit. I have been looking at it in MSDN for while, then I checked (out of curiosity) in my Applications=Code+Markup book, by Charles Petzold, and it turns out I was trying to do something very similar to him, so this app kind of represents a combination of both mine and his books example. I decided to produce the simplest version of paint that one could hope to see, no layers, nothing fancy like that, just Ink.

So this app will demonstrate the following aspects of using Ink

  • Save Ink
  • Save Ink as a bitmap
  • Load Ink
  • Cut Ink
  • Copy Ink
  • Paste Ink
  • Delete Ink
  • Select Ink
  • Format Ink
  • Stylus Color
  • Change stylus type
  • Change pen

Oh it will also demonstrate, but shall not describe the usage of following WPF controls (if you want to see how they work dive into the XAML)

  • Buttons
  • Grids
  • InkCanvas
  • GroupBox
  • RadioBtton
  • Expander
  • Popup

It obviously uses Styles and Templates to achieve its handsome good looks, but these WPF concepts are described in various other places, you could try here or Josh Smith who talks about it in his lovely series on WPF.

What this article will talk about is the use of Ink, and if it is deemed important will explain the UI elements associated with a particular Ink operation.

A Note About The Demo App

Before I start bombarding people with the inner mechanisms of the attached WPF application, shall we have a quick look at the finished product.

Image 1

Pretty isn't he.

The application is based on using Visual Studio 2005 with The Visual Studio Designer for WPF installed, and using Expression BLEND and Visual Studio 2005 combination. I would just like to point out that I do not think that using Expression BLEND by itself makes you good at WPF, you still need to be able to hand craft code if you want to get neat code. But as I say I just wanted to give it a try, for this article. And I have to say I do actually think the Expression BLEND team have done an excellent job, it is just as easy to use as Adobe Flash, which I also liked very much.

Prerequisites

  1. Obviously as it is WPF you will also need the .NET 3.0 framework
  2. And if you really want to edit things in Visual Studio The Visual Studio Designer for WPF may not go amiss

So What Does It Actually Do

As I stated above the application does the following, so we'll investigate these items one by one.

  • Save Ink
  • Save Ink as a bitmap
  • Load Ink
  • Cut Ink
  • Copy Ink
  • Paste Ink
  • Delete Ink
  • Select Ink
  • Format Ink
  • Stylus Color
  • Change stylus type
  • Change pen

But before we go into all of that, we need to understand one thing, and that is, what are we actually applying all these related functions to.

Well in this example I will actually be using the Microsoft.Ink Namespace and more specifically I will be demonstrating things using the WPF <a title="InkCanvas" target="_blank" hef="http://msdn2.microsoft.com/en-us/library/system.windows.controls.inkcanvas.aspx">InkCanvas</a> control, which is of course a WPF control, but there is an equivalent in the Tablet PC SDK, but as I say I'm using the <a title="InkCanvas" target="_blank" hef="http://msdn2.microsoft.com/en-us/library/system.windows.controls.inkcanvas.aspx">InkCanvas</a> control.

The WPF <a title="InkCanvas" target="_blank" hef="http://msdn2.microsoft.com/en-us/library/system.windows.controls.inkcanvas.aspx">InkCanvas</a> control exposes an interesting object that we will be using over and over in this article. This object is a StrokeCollection which can be accessed via the InkCanvas class. It is by using these 2 classes that we are able to carry out all the associated tasks in creating this very simplistic paint application.

So let's get on with it, shall we.

Save Ink

Image 2

Saving some Ink is child's play, we simply use the Save() method of the InkCanvas.Strokes object. Which accepts any stream. In the attached app, I create a new file format called "Ink Serialized Format", but you can use whatever you like.

C#
this.inkCanv.Strokes.Save(file);

And that's enough to save all the information needed to restore the Ink at a later time

Save Ink as a bitmap

Image 3

Saving the Ink as a Bitmap is a little trickier, but not impossible. We simply use 3 nice objects RenderTargetBitmap,BmpBitmapEncoder and BitmapFrame in the manner shown below:

C#
int marg = int.Parse(this.inkCanv.Margin.Left.ToString());
RenderTargetBitmap rtb = 
        new RenderTargetBitmap((int)this.inkCanv.ActualWidth - marg,
                (int)this.inkCanv.ActualHeight - marg, 0, 0, 
            PixelFormats.Default);
rtb.Render(this.inkCanv);
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(file);
file.Close();

It should be noted that this is a one way trip, I did not find a way to retrieve Ink from an image. Though it is no problem to add images as nodes in the InkCanvas hierarchy. This will be discussed further in the 2nd part of this article series.

Load Ink file

Image 4

It should come as no surprise that to load some Ink from a file its just the opposite of saving a file. As before we simply use a stream. In the attached app, I create a new file format called "Ink Serialized Format", but you can use whatever you like.

C#
this.inkCanv.Strokes = new StrokeCollection(file);

Cut Ink

Image 5

In order to actually cut the Ink, you must Select some Ink to cut. This can be done in 2 ways, you may either use the Select button (this will be discussed here or the current stylus may be changed to be in select mode. This is also discussed in more detail here.

For now I'm going to assume that there is at least some Ink selected. You will be able to see the selected Ink as there will be a bounding rectangle with resize handles surrounding the Ink, as shown in the figure above. So once you've got some ink selected, you will be able to Cut it; it's very easy.

C#
if (this.inkCanv.GetSelectedStrokes().Count > 0)
    this.inkCanv.CutSelection();

Copy Ink

Copying Ink is almost the same as Cutting it (Assuming you have some Ink selected), we simply use the CopySelection method of the InkCanvas instead of the CutSelection

C#
if (this.inkCanv.GetSelectedStrokes().Count > 0)
    this.inkCanv.CopySelection();

Paste Ink

Pasting Ink is almost as easy (Assuming you have some Ink selected), let's have a look at that.

C#
if (this.inkCanv.CanPaste())
    this.inkCanv.Paste();

Delete Ink

Deleting Ink is also very simple (Assuming you have some Ink selected), just check that there are some Strokes to remove, and remove them.

C#
if (this.inkCanv.GetSelectedStrokes().Count > 0)
{
    foreach (Stroke strk in this.inkCanv.GetSelectedStrokes())
        this.inkCanv.Strokes.Remove(strk);
}

Select Ink

Recall earlier for the Select Cut, Copy, Paste And Delete operations, we had to actually have some Ink selected. Well how do we select some Ink. As I stated that this can be done in 2 ways, you may either use the Select button (this option) or the current stylus may be changed to be in select mode. So let's have a look at how to select all Ink. It's very easy:

C#
this.inkCanv.Select(this.inkCanv.Strokes);

Format Ink

Formatting Ink relies on you first having selected some Ink to format. So assuming you have some Ink (Strokes) selected when you use the Format Ink button, you will be shown the color picker window as shown below in the Stylus Color section, that window will enable you to change the Strokes attributes.

Note: When selecting strokes the strokes selected will look as follows:

Image 6

The code for the Format button is simply going to try and get the color of the 1st Stroke, and then show the dialog window where we can pick a new color for the selected Strokes.

C#
StylusSettings dlg = new StylusSettings();
dlg.Owner = this;

// Try getting the DrawingAttributes of the first selected stroke.
StrokeCollection strokes = this.inkCanv.GetSelectedStrokes();

if (strokes.Count > 0)
    dlg.DrawingAttributes = strokes[0].DrawingAttributes;
else
    dlg.DrawingAttributes = this.inkCanv.DefaultDrawingAttributes;

if ((bool)dlg.ShowDialog().GetValueOrDefault())
{
    // Set the DrawingAttributes of all the selected strokes.
    foreach (Stroke strk in strokes)
        strk.DrawingAttributes = dlg.DrawingAttributes;
}

Stylus color

In order for the user to control what color and how the Ink should be applied there is a second XAML window that is used, this is called "StylusSettings.xaml" and it contains a UniformGrid control with buttons which simply have their backgrounds set to a particular Brush color out of the collection of System.Brushes.

Image 7

The iteration of the System.Brushes is done using Reflection.

C#
private void createGridOfColor()
{
    PropertyInfo[] props = typeof(Brushes).GetProperties(BindingFlags.Public |
                                          BindingFlags.Static);
    // Create individual items
    foreach (PropertyInfo p in props)
    {
        Button b = new Button();
        b.Background = (SolidColorBrush)p.GetValue(null, null);
        b.Foreground = Brushes.Transparent;
        b.BorderBrush=Brushes.Transparent;
        b.Click += new RoutedEventHandler(b_Click);
        this.ugColors.Children.Add(b);
    }
}

Also this page is responsible for showing and setting the current Ink values that will be used for drawing with. This is achieved by the use of a nice class called DrawingAttributes which can be both retrieved and set on the InkCanvas

C#
public DrawingAttributes DrawingAttributes
{
    set
    {
        chkPressure.IsChecked = value.IgnorePressure;
        chkHighlight.IsChecked = value.IsHighlighter;
        penWidth = value.Width;
        penHeight = value.Height;
        currColor = value.Color;
    }
    get
    {
        DrawingAttributes drawattr = new DrawingAttributes();
        drawattr.IgnorePressure = (bool)chkPressure.IsChecked;
        drawattr.Width=penWidth;
        drawattr.Height = penHeight;
        drawattr.IsHighlighter = (bool)chkHighlight.IsChecked;
        drawattr.Color = currColor;
        return drawattr;
    }
}

Change stylus type

There is also the facility to change the stylus control, to any of the following:

  • Ink: Will draw Ink
  • Erase: Will erase Ink (that is Drawn over with the stylus)
  • Erase By Stroke: Will erase the Stroke that was selected
  • Select: Will allow the user to draw around the Ink to select

Image 8

Allows the user to draw Ink.

Image 9

Allows the user to erase Ink.

Image 10

Allows the user to erase Ink Strokes.

Image 11

Allows the user to select Ink Strokes.

Change pen size

There is also a facility to change the pen size.

Image 12

Some other cool s%*t

There are a number of areas which I quite like and hope that you may find interesting such as :

  • FishEyePanel.cs: Which is not my own, but I like it all the same, it comes from here and is by a fellow called Paul Tallett. Basically it works like those nice task bars that Apples have, where the icon nearest the mouse is biggest and those either side are slightly smaller and so on.

    Image 13

That's it

I hope this article shows just how easy it is to use Ink in your applications. That said, I have only touched a very small part of what can be done with the Tablet PC SDK. I did not want to put people off by diving straight into the immense inner workings of Ink without people actually seeing a fairly simple application of it first. I am planning another Ink related article that should tie it together a bit more, so you may have to wait till then.

So What Do You Think ?

I would just like to ask, if you liked the article please vote for it, and leave some comments, as it lets me know if the article was at the right level or not, and whether it contained what people need to know.

Conclusion

I have enjoyed writing this article and like I say, I will be writing one more article on Ink, that I'm afraid to say will be VISTA only. It will also use another .NET 3.0 technology. I'm hoping the next article may be quite interesting to you good folk, as it will use two .NET 3.0 technologies and Vista only APIs.

As I've said before....if you want to keep a work/life balance, I would suggest you stay as far away from WPF as possible, cos once its got you in its little tentacles, there really is no escape. "Resistance Is Futile. You Will Be Assimilated".

History

  • v1.0 06/06/07: Initial issue

Other Stuff

I would encourage people to get into WPF and read all that Josh Smith writes, and to also try Expression BLEND for themselves. As I say I think it's cool, but should also be used with some hand coding in places. And if you're serious about WPF, you should read around this subject so you know what the code that Expression BLEND produces actually does.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
QuestionInk for WEB Pin
souvikchat4u198128-Jun-17 6:54
souvikchat4u198128-Jun-17 6:54 
QuestionDisplay Ink Collecter Pin
Member 1036245426-Oct-13 16:26
Member 1036245426-Oct-13 16:26 
GeneralMy vote of 5 Pin
Farhan Ghumra13-Jun-12 0:08
professionalFarhan Ghumra13-Jun-12 0:08 
GeneralMy vote of 5 Pin
RCohn17-May-12 16:07
RCohn17-May-12 16:07 
GeneralMy vote of 5 Pin
Ravichandran O S17-Feb-12 0:44
Ravichandran O S17-Feb-12 0:44 
GeneralMy vote of 5 Pin
delibey14-Feb-12 14:33
delibey14-Feb-12 14:33 
GeneralMy vote of 5 Pin
John-ph11-Apr-11 1:30
John-ph11-Apr-11 1:30 
QuestionCan we replay and edit? Pin
samwiz16-Mar-11 22:26
samwiz16-Mar-11 22:26 
AnswerRe: Can we replay and edit? Pin
Sacha Barber16-Mar-11 22:56
Sacha Barber16-Mar-11 22:56 
AnswerRe: Can we replay and edit? Pin
Tom.Jia28-Oct-11 18:57
Tom.Jia28-Oct-11 18:57 
GeneralRe: Can we replay and edit? Pin
Sacha Barber29-Oct-11 0:39
Sacha Barber29-Oct-11 0:39 
GeneralRe: Can we replay and edit? Pin
Tom.Jia30-Oct-11 15:06
Tom.Jia30-Oct-11 15:06 
GeneralCool Pin
zhujinlong198409135-Dec-10 16:17
zhujinlong198409135-Dec-10 16:17 
GeneralRe: Cool Pin
Sacha Barber5-Dec-10 18:51
Sacha Barber5-Dec-10 18:51 
Ta
Sacha Barber
  • Microsoft Visual C# MVP 2008-2010
  • Codeproject MVP 2008-2010
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue

My Blog : sachabarber.net

GeneralMy vote of 5 Pin
Amol Patki24-Oct-10 20:31
Amol Patki24-Oct-10 20:31 
GeneralMy vote of 5 Pin
suvb13-Jul-10 23:33
suvb13-Jul-10 23:33 
QuestionHow to draw shapes and save them as isf Pin
bspro2-Jul-10 23:37
bspro2-Jul-10 23:37 
GeneralGreat apps Pin
cyrax16051-Nov-09 19:48
cyrax16051-Nov-09 19:48 
QuestionGreat one! Any lights on text controls. Pin
subho1006-Oct-09 23:25
subho1006-Oct-09 23:25 
GeneralGreat code Pin
JoshMachin22-Jul-09 19:10
JoshMachin22-Jul-09 19:10 
GeneralRe: Great code Pin
Sacha Barber22-Jul-09 21:48
Sacha Barber22-Jul-09 21:48 
GeneralHello got a question for you. Pin
uniphix8-Jul-09 21:37
uniphix8-Jul-09 21:37 
GeneralRe: Hello got a question for you. Pin
Sacha Barber8-Jul-09 21:52
Sacha Barber8-Jul-09 21:52 
GeneralRe: Hello got a question for you. Pin
uniphix9-Jul-09 11:43
uniphix9-Jul-09 11:43 
QuestionDoes ink API provide information about Pen Tilt ? Both APOGEE AND AZIMUTH angles ? Pin
cadieuh8-Jun-09 0:47
cadieuh8-Jun-09 0:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.