Inked

Create Ink-enabled Web Sites

LANGUAGES: VB.NET

ASP.NET VERSIONS: 2.0

This article provides an introduction to the Ink APIs for Web developers targeted at Windows XP Tablet PC users. Follow along and you ll learn to build a simple Windows Forms control that is Ink-enabled, embed it into a Web page, then interact with it.

Although Tablet PCs have a lot of great built-in functionality, such as handwriting recognition, the Tablet PC SDK enables developers to tap into the power of Ink to write a lot of interesting applications. Over the years I ve tried to look at applications that think out of the box of typical data entry to see where Ink can really shine. In addition to some of the awesome illustration software, some eye-opening examples of these are XThink s MathJournal and Physics Illustrator, which came out of the Microsoft Research Labs. Although handwriting and recognition are the first things that most people think of, it s the true mobility of these computers that make them stand out. Consider any scenario where a worker uses a clipboard to fill out a form, then hands that to someone else to enter into a computer. This is the perfect target for an Ink-enabled business application. But there are many other, more interesting things that can be done, such as marking up images (consider an architect, or perhaps an insurance adjuster inspecting a damaged car). The real estate and medical industries have also embraced the technology in a very big way.

One thing that many of these applications have in common is that they are all being built as client-side Windows applications. The reason for this is that the Tablet PC is dependent on a digitizer that covers the computer s screen. The digitizer receives the magnetized signals from the stylus and sends those to the operating system, which identifies the strokes and passes them on to the software (internal or customized). The software then uses the Tablet PC API to interpret and work with the resulting data. With Windows XP, a special version of the O/S, Windows XP Tablet PC Edition, was required. However, with Windows Vista, the Tablet PC functionality is wrapped into the base O/S. This article will focus on Windows XP Tablet PC Edition.

Because all of this work is done on the client side, embedding Ink into Web sites has not been an obvious target for developers. Additionally, the challenges of working with ActiveX or other embedded controls in a Web page have been daunting.

Basic Requirements

You don t need a Tablet PC to do Tablet PC development. Installing the Tablet PC SDK will give your computer most of what you need to develop and test your applications. MSDN has articles on setting up for development, as well as developing off-tablet (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tpcsdk10/lonestar/devcenter/tbidxindex.asp). If you want to test the inking abilities with something finer than what a mouse will render, you can plug into your system an inexpensive digitizer, such as one made by Wacom. Whether you have a Tablet PC or not, you ll need to download and install the Tablet PC SDK 1.7, as well as the updates to integrate with .NET 2.0 (http://www.microsoft.com/downloads/details.aspx?FamilyId=B46D4B83-A821-40BC-AA85-C9EE3D6E9699&displaylang=en; http://www.microsoft.com/downloads/details.aspx?FamilyID=69640b5c-0ee9-421e-8d5c-d40debee36c2&displaylang=en). The MSDN articles will assist you with this. Users must have a Tablet PC to interact with your Ink-enabled controls.

Your First Ink-enabled Web Application

Now to the code! The remainder of this article will walk you through building a simple Ink-enabled Windows Forms control, as well as embedding it into a Web page.

This control will allow users to draw or write into it using a few colors and a few pen widths, erase strokes, and clear the control completely. It will also have the ability to expose the contents of the control so you can get the data to the server side for saving into a database or whatever you choose to do with the data.

It is important to note that you should build as much logic into the control as possible, thereby minimizing the necessary interaction between the Web page and the control. For example, place controls for changing the pen color within the user control. That way it won t be necessary to write JavaScript code to tell the user control to change a color.

In Visual Studio, create a Windows Control Library project and add to the project a reference to the Microsoft Tablet PC API. A user control is automatically created. We ll work with that one. The first thing to do to this control is give it a border using the control s BorderStyle property. Without a border, it s impossible to determine where to ink when the control is embedded in the Web page.

A ToolStrip control is a great place to organize all the buttons for interacting with Ink. With the buttons, we can tell the control to select a new color for the pen or change other characteristics of how the ink will be drawn into the control. Add eight ToolStripButtons to the ToolStrip. Using the properties for each button, change the first four buttons. Each button should have DisplayStyle set to None and the BackGroundColor set to a color of your choice. The fifth and sixth buttons will be used to set the ink weight to Thick and Thin . The next button will be used to allow the user to erase strokes. Change the DisplayStyle of these buttons to Text and their Text properties accordingly. Of course, you can use an eraser image instead of text, if you d like. The last ToolTipButton should be for clearing the entire control. Figure 1 shows what the control should look like so far.


Figure 1: The control as it should look so far.

Ink-enabling the User Control

It s time to get Ink capabilities into the control. This is done using the Microsoft.Ink.InkOverlay object, which is a component, not a control. InkOverlay is instantiated and attached to whichever control you would like to be Ink-enabled. If this were a Windows Form, you may want to Ink-enable a TextBox control. In some cases, we ll want the entire user control Ink-enabled. However, because the ToolStrip control is there, we ll create a panel to fill the balance of the user control and Ink-enable this panel.

The basic structure of the object model is that InkOverlay contains an Ink object, which is made up of a collection of strokes. A stroke is defined by the starting point when a user touches the stylus to the screen, to the ending point when the stylus is lifted from the screen. You can drill down further to work with all the points that make up a stroke.

Drop a panel onto the control and set its docking property to Fill. In the code, create a variable for the InkOverlay object, and in the Load method instantiate the object, attach it to the panel, and enable it:

Imports Microsoft.Ink

Public Class UserControl1

 Dim inkO As InkOverlay

 Private Sub UserControl1_Load(ByVal sender As Object, _

  ByVal e As System.EventArgs) Handles Me.Load

     inkO = New InkOverlay(Panel1)

     inkO.Enabled = True

  End Sub

End Class

 

Thanks to Visual Studio 2005 s UserControl TestContainer, you can run the project and test the drawing ability of the control. If you are not on a Tablet PC, you ll be able to draw with your mouse although it will be a bit ragged as the resolution of the mouse is not nearly as fine as that of a stylus and digitizer.

Formatting the Ink

The Tablet PC API has a surprising amount of functionality. We ll barely scratch the surface in this example, but it s a great place to start.

The InkOverlay.DefaultDrawingAttributes property contains properties to control the color and other attributes of the ink. This affects ink to be drawn, not ink that already exists in the control. The ChangeInkColor method below can be used to change the ink color. Wire up the method to the Click events of the four color buttons:

Private Sub ChangeInkColor(ByVal sender As System.Object, _

 ByVal e As System.EventArgs)

 Dim button As ToolStripButton = sender

 inkO.DefaultDrawingAttributes.Color = button.BackColor

End Sub

 

The thinInk and thickInk Click events change the Width of the DefaultDrawingAttributes:

 

Private Sub thinInk_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles thinInk.Click

    inkO.DefaultDrawingAttributes.Width = 50

 End Sub

 Private Sub thickInk_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles thickInk.Click

   inkO.DefaultDrawingAttributes.Width = 150

End Sub

 

The InkOverlay.EditingMode options are Ink, Delete, and Select. In the Click event of the Eraser button, we ll toggle the mode from ink to eraser. At the same time, the text of the button will change so that when the InkOverlay is in eraser mode, it will be obvious that clicking the button will set the user back to ink mode. Note that there are two ways to erase, controlled by the InkOverlay.EraserMode property. The default mode is StrokeErase, which will remove an entire stroke by touching any point on the stroke. The alternate mode is PointErase, which behaves more like a typical erase action, removing ink only at the positions the eraser touches:

 

Private Sub Eraser_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Eraser.Click

  If inkO.EditingMode = InkOverlayEditingMode.Delete Then

   inkO.EditingMode = InkOverlayEditingMode.Ink

   Eraser.Text = "Erase"

  Else

   inkO.EditingMode = InkOverlayEditingMode.Delete

   Eraser.Text = "Ink"

  End If

 End Sub

 

The last button on the ToolStrip is used to clear all the ink from the control, using the InkOverlay.Ink.DeleteStrokes method. You also need to invalidate the control that is attached to the InkOverlay to force it to redraw itself. Otherwise, even though the strokes no longer exist in the Ink control, they remain displayed on the drawing surface:

 

Private Sub ClearControl_Click(ByVal sender _

 As System.Object, ByVal e As System.EventArgs) _

 Handles ClearControl.Click

   inkO.Ink.DeleteStrokes()

    Panel1.Invalidate()

 End Sub

 

Run the project and check out all the functionality of the control in the UserControl TestContainer (see Figure 2).


Figure 2: Test the control s functionality.

Adding Functions to Interact with the Web Page

At this point you could easily embed the control in a Web page and let the user have some fun drawing. All the functionality built in to the control will work on the Web page with no additional coding required. However, the user won t be able to do anything more than draw on the page; there would be no way to save images or send them anywhere, either by e-mail or to server applications, such as a Web service or a database.

Let s rectify this situation; let s add functionality that the Web page can call. For this article, we ll enable the application to extract the Ink data from the Ink control so you can save it as a .bmp file on the server. Although it is certainly possible to store the Ink data so that it may be retrieved and pulled back into an Ink-enabled control and edited further, that is beyond the scope of this article.

We ll be adding a public function named GetInkData that can be called by the host (the Web page); it will return a string to the page.

The Ink class has a Save function that outputs a byte array in several formats. One format, InkSerializedFormat (or ISF) persists all the metadata about the Ink object. This is convenient for placing the data into an Ink control at a later date. Another format, GIF, saves the data as a GIF file and adds the ISF metadata, as well. That means if you want to have a true image file and the ISF data, you need only save once. The resulting byte array can then be written out to a GIF file or pulled back into an Ink-enabled control.

The GetInkData function will output the GIF-persisted data; however, for it to be transmitted from the client-side script to the server-side code it first must be converted to a Base64 string format. Although the Ink.Save function has alternative persistence formats for Base64, they require additional manipulation. Therefore, this code will persist to GIF and then use the .NET conversion method to get the Base64 string. Add the following function to the Ink control:

 

Public Funtion GetInkData() As String

 If inkO.Ink.Strokes.Count = 0 Then

 Return  ("empty")

 Else

 Dim inkBytes As Byte() = inkO.Ink.Save(PersistenceFormat.Gif)

 Return Convert.ToBase64String(inkBytes)

 End If

End Function

 

Now the control is complete. But before building the project, there s one more very important step! The assembly must be visible to COM. This can be done by opening the Application Tab of the project properties, then clicking the Assembly Information button and checking the Make Assembly COM-Visible checkbox.

Compile the project. The resulting DLL is what gets added to the Web site. Because it will be an embedded resource, you ll actually do this simply by copying and pasting the DLL file, just as you would an image file.

Creating the Host Web Site

Create a new ASP.NET Web site. I have successfully run this sample using an IIS (HTTP) Web site, a file-based server (File System) Web site, and a Web Application project. Note that if you do development in a File System server, it will be necessary to change the user control s class name any time you modify the user control and recompile the assembly.

Next, add the DLL to the project. If the Web site is in the same solution as the user control project, you can copy and paste from one project to the other. Otherwise, you can use the Add Existing Item method to add the DLL to the Web site.

Prior to Internet Explorer 7, it was enough to embed the control directly into the HTML of the Web page with the tags. However, now you must embed the Ink control using a separate JavaScript file or else the user will have to click on the control to activate it. Clicking with the stylus will leave unwanted marks on the drawing surface. Add a new JavaScript file to the Web site using the Add New Item option; name the file EmbedInkControl.js.

The object will be embedded using the assembly name and the strongly typed name of the user control s class. My user control project was named aspnetPROInkControl; by default this is the name of the DLL assembly. The class has the default name of the user control (UserControl1). The code for the JavaScript file looks like this:

 

document.write('

 "aspnetPROInkControl.dll#aspnetPROInkControl.UserControl1"

 height="400" width="400">

');

 

Because the control is being embedded when the page is rendered, you won t see it on the Web page at design time. You ll most likely want to adjust the height and width and determine the placement of the control. I get around this by embedding the control directly at design time using the following snippet in the HTML of my page:

 

 width="400">

 

When I am satisfied with this, I modify the JavaScript file accordingly, then replace the tags with the call to the JavaScript file:

 

 

This will render the Ink control in the position where the script tags are placed. The last steps are to call the GetInkData function from the client side and send the data to the server.

Place an control on the Web page. Also, place an HTML Hidden input control somewhere on the page. Be sure to make the Hidden input control available to the server by setting its runat property to server. The following code assumes that the form and these controls have their default names of form1, Button1, and Hidden1.

Two things need to happen when the button is clicked. The first is a client-side call to the GetInkData function in the embedded Ink control. This call will also place the resulting Ink in a hidden HTML control. Then the button s Click event will read the data from the hidden HTML control and save it to a GIF file on the server.

Thanks to a new property in the ASP.NET Button control, named OnClientClick, it is possible to fire off both the client-side and server-side events with just one click of the button. Change the OnClientClick property to SaveInk. Then add the SaveInk JavaScript function to the source of the Web page. Place it inside the opening tag:

 

 

Fortunately, the client-side event is hit first. Therefore, in the server-side Click event function for the button you ll be able to read the value of the Hidden1 control, which will already have the Ink data. Because the data is in Base64String format, it will be necessary to convert it back to bytes to create the GIF image file from it. Note that in the control there was a test to ensure that there was data in the Ink control. If there was no data, the control returns empty . The Button1_Click event tests for the return value of empty before proceeding with the file creation:

 

Protected Sub Button1_Click(ByVal sender as Object, _

 ByVal e as System.EventArgs) Handles Button1.Click

Dim inkString as String

   inkString=Hidden1.Value

 If InkString<>"empty" Then

   Dim bytes() as Byte=Convert.FromBase64String(InkString)

   System.IO.File.WriteAllBytes(Server.MapPath("") & _

    "\myInkImage.gif",bytes)

End Sub

 

Now you should be able to run the Web page, draw in it, and save your drawing. One thing to point out is that once you get to the button s Click event and have the string that is returned by Hidden1.Value, you can do whatever you want with the data. Though the example merely saves it to an image file, you could save the data into a database or an XML file, store it in Session for use elsewhere on the site, send it to a Web service, or take some other action on it. At this point it s simply a string. Figure 3 shows the Web page with the Ink control embedded in it.


Figure 3: The Web page with the Ink control embedded in it.

 

Conclusion

Ink-enabled Web sites can be used for fun or as part of business applications. For example, rather than a drawing palette, consider allowing users to mark-up online documents or to actually use their signature to sign a document. Be aware that hidden controls are not secure, so anything that requires security should be encrypted prior to storing it in the hidden control. The biggest challenge, of course, is to find end users with more artistic talent than the typical developer, as evidenced by the drawings in this article.

The source code accompanying this article is available for download.

Julia Lerman is an independent consultant and .NET Mentor who has been designing and writing software applications for more than 20 years. She lives in Vermont, where she runs the Vermont.NET User Group. Julia is well known in the .NET community as an INETA Speaker, .NET MVP, ASPInsider, conference speaker, and prolific blogger. You can read Julia s blog at http://thedatafarm.com/blog.

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish