RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Capture Signatures Remotely from Your Pocket PC

You don't have to work for Federal Express to outfit your delivery or salesforce with a remote signature capture and transmission feature. With just a Pocket PC and the simple instructions herein, you'll soon be sending John Hancocks to and from your server with accuracy and grace.

f you have ever received a package from one of the main courier companies (such as UPS, DHL, or FedEx), you have no doubt been asked to sign for the package on a mobile computer that the courier carries with him. But what happens after you sign for the package? The signature and the delivery information are transmitted back to the central server so that the whereabouts of each package can be tracked in real-time.

You don't have to be the IT manager at Federal Express to figure out similar ways of using such an efficient technology. In this article, I will show you how to build a Pocket PC application that captures users' signatures and transmits them back to a server in real-time using sockets communications. There are two components you will build in this article:

  1. A Pocket PC application that captures users' signatures. You will learn how you can build a control that allows user to write on it. You will use GDI+ to draw lines that make up a user's signature and then save them as a series of coordinates.
  2. A server that receives delivery information from clients and displays the signature captured for each delivery. For efficient transmission of data from client to server, you will use sockets programming to accomplish this.
Figure 1 shows what the client and the server will look like.

Figure 1. The client and the server you will build in this article are shown.
Figure 2. A series of events are fired when you write the letter "C" on the control.

Building the Signature Control
The first component to build in this article is the Signature control. Using Visual Studio 2005, create a new Windows Mobile 5.0 Pocket PC application project and name it RemoteTracking.

Add a new Class file to the project (right-click on project name in Solution Explorer and select Add | New Item…). Name the class file Signature.vb.

Inherit the Signature class from Control and declare its member variables as follows:

Public Class Signature
    Inherits Control

    Private _bmp As Bitmap
    Private _previouspoint As New Point
    Private _points As ArrayList
    Private _lines As New ArrayList
    Private _g As Graphics
    Private _pen = New Pen(Color.Black, 2)
    Private _Enable As Boolean = False

End Class
As the user writes on the control using the stylus, the series of points it makes on the control are saved. There are three events of concern to us:
  • OnMouseDown—this event is fired when the stylus touches on the control
  • OnMouseMove—this event is fired when the stylus is dragged on the control
  • OnMouseUp—this event is fired when the stylus is lifted from the control
Figure 2 shows what happens when you write the character "C." The OnMouseDown event is first fired, followed by a series of OnMouseMove events as the stylus is dragged counter-clockwise, and then finally the OnMouseUp event is fired when the stylus is lifted.

The points touched by the stylus between the OnMouseDown and OnMouseUp events are saved as a series of continuous points (called a line). For example, the character "C" is made up of one line (assuming you did not lift up the stylus whiling drawing it) while the character "t" (see Figure 3) is made up of two lines—one horizontal and one vertical.

Figure 3. You need two lines to make the character "t".
Figure 4. An ArrayList object is used to store the data that represents each drawing.

The lines and the points composing a character are saved in an ArrayList object (see Figure 4).

Continuing with the coding of the Signature class, I'll now add the definition for the OnMouseDown event handler:

    '---when the user tabs on the screen---
    Protected Overrides Sub OnMouseDown( _
       ByVal e As System.Windows.Forms.MouseEventArgs)

        If Not _Enable Then Exit Sub

        '---save the current point for later use---
        _previouspoint.X = e.X
        _previouspoint.Y = e.Y

        _points = New ArrayList
        '---add the point---
    End Sub
In this event, when the user uses the stylus to tap on the control, you will save its coordinates to an ArrayList object called _points.

The next event to define is the OnMouseMove event handler:

    '---when the user drags his stylus---
    Protected Overrides Sub OnMouseMove( _
       ByVal e As System.Windows.Forms.MouseEventArgs)

        If Not _Enable Then Exit Sub

        '---add the current point---
        _points.Add(New Point(e.X, e.Y))

        '---draws a line connecting the previous
        ' point and the current point---
        _g.DrawLine(_pen, _previouspoint.X, _
           _previouspoint.Y, e.X, e.Y)

        '---saves the current point for later use---
        _previouspoint.X = e.X
        _previouspoint.Y = e.Y

        '---update the display---
    End Sub
Here, you add the coordinates of the point to the _points object and then draw a line connecting the previous point to the current point. You then call the Invalidate() method to force the control surface to be repainted so that the line drawn will now become visible.

The final event handler to define is the OnMouseUp event:

    '---when the user lifts his stylus---
    Protected Overrides Sub OnMouseUp( _
       ByVal e As System.Windows.Forms.MouseEventArgs)

        If Not _Enable Then Exit Sub

        '---convert all the arraylist items into a Point array---
        Dim pts(_points.Count - 1) As Point
        For i As Integer = 0 To _points.Count - 1
            pts(i) = CType(_points(i), Point)
        '---add the list of points to the current line---
    End Sub
In this event handler, you convert all the objects saved in the _points ArrayList object into a Point array and then add it into the _lines ArrayList object.

The next step would be to create an image to be used as the background for the signature control. Using MS Paint, create an image of dimension 233x73 (see Figure 5). Name the image Signature.bmp.

Figure 5. The background image to use for the signature control is shown.
Add the image to the project by right-clicking on the project name in Solution Explorer and then selecting Add | Existing Item…. After the image is added to the project, select it in Solution Explorer and then change the value of its "Copy to Output Directory" property to "Copy if newer."

Back in the Signature class, add an InitSignature() subroutine to the class so that you can load the background image to use as the surface for the control:

    Public Sub InitSignature()
        '---load the background image for the control---
        Dim path As String = System.IO.Path.GetDirectoryName( _
           System.Reflection.Assembly. _
        _bmp = New Bitmap(path & "Signature.bmp")
        _g = Graphics.FromImage(_bmp)
    End Sub
You also need to override the OnPaint() event handler so that the control can be updated correctly:

    '--updates the display on the control---
    Protected Overrides Sub OnPaint( _
       ByVal e As System.Windows.Forms.PaintEventArgs)
        e.Graphics.DrawImage(_bmp, 0, 0)
    End Sub
To prevent the control from flickering when you are updating its display, override the OnPaintBackGround() subroutine:

    Protected Overrides Sub OnPaintBackground( _
       ByVal e As PaintEventArgs)
        '---do nothing-to prevent flickering---
    End Sub
Sometimes the user may only want to display the signature and not capture it. Therefore, add the Enable property definition so that users of this control can disable the signature control programmatically:

    Public Property Enable() As Boolean
            Return _Enable
        End Get
        Set(ByVal value As Boolean)
            _Enable = value
        End Set
    End Property
Lastly, define the Signature property so that users can either obtain the value (as a series of coordinates) of the signature (defined below) or set it to display a signature:

    '---gets and sets the signature---
    Public Property Signature() As String
            Dim sb As New System.Text.StringBuilder
            For i As Integer = 0 To _lines.Count - 1
                For Each pt As Point In _lines(i)
                    sb.Append(pt.X & "," & pt.Y & "|")
            Return sb.ToString
        End Get
        Set(ByVal value As String)

            '---split into individual lines---
            Dim lines As String() = value.Split(vbLf)

            '---for each individual line---
            For i As Integer = 0 To lines.Length - 2
                '---split into individual points---
                Dim ps As String() = lines(i).Split("|")

                Dim points(ps.Length - 2) As Point
                '---for each point---
                For j As Integer = 0 To ps.Length - 2
                    Dim xy As String() = ps(j).Split(",")
                    points(j) = New Point(xy(0), xy(1))
        End Set
    End Property
Note that the value of a signature is represented as a series of lines (separated by a LineFeed character), with each line containing a series of points. Using the example shown in Figure 4, the value of the signature is as follows:


Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date