devxlogo

Capture Signatures Remotely from Your Pocket PC

Capture Signatures Remotely from Your Pocket PC

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 = FalseEnd 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---        _points.Add(_previouspoint)    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---        Invalidate()    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)        Next        '---add the list of points to the current line---        _lines.Add(pts)    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 233×73 (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. _           GetExecutingAssembly().GetName().CodeBase)        _bmp = New Bitmap(path & "Signature.bmp")        _g = Graphics.FromImage(_bmp)        _lines.Clear()        Invalidate()    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        Get            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        Get            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 & "|")                Next                sb.Append(vbLf)            Next            Return sb.ToString        End Get        Set(ByVal value As String)            _lines.Clear()            '---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))                Next                _lines.Add(points)            Next            DrawSignature()        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:

119,29|119,25|114,22|109,22|104,22|?132,30|138,29|143,28|147,28|152,28|?151,9|150,13|150,17|150,21|150,25|150,29|?

Testing the Signature Control
You can now test the signature control. Back in Form1, double-click on it to reveal the code-behind. Code the following:

Public Class Form1    Private sig As New Signature    Private Sub Form1_Load( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles MyBase.Load        With sig            .Location = New Point(3, 180)            .Size = New Size(233, 73)            .Enable = True            .InitSignature()        End With        Me.Controls.Add(sig)        Me.Refresh()    End SubEnd Class

Essentially, you are programmatically adding the signature control to the form. Press F5 to deploy it to an emulator (or a real device) and you should now be able to write on the signature control (see Figure 6).


Figure 6. Testing the signature control on an emulator or a real device is now possible.
?
Figure 7. Populate Form1 with the various controls as shown here.

Sending Signatures to Backend Server
Now that you have the signature control ready, it is time to code the logic to send the signature to a backend server. For this, you will use sockets communication.

Add a new class to the current project and name it Sync.vb. Populate it as follows:

Imports System.NetImports System.Net.SocketsPublic Class Sync    Const portNo As Integer = 3456    Private client As Socket    Public Sub PerformSync( _       ByVal HostIP As String, _       ByVal txtData As String)        Try            Dim RemoteAdd As System.Net.IPAddress = _               System.Net.IPAddress.Parse(HostIP)            Dim endPoint As New IPEndPoint(RemoteAdd, portNo)            client = New Socket(endPoint.AddressFamily, _                     SocketType.Stream, ProtocolType.Tcp)            client.Connect(endPoint)            '---send a message to the server            Dim data As Byte() = _            System.Text.Encoding.ASCII.GetBytes(txtData & "*")            '---send the text---            client.Send(data)            MsgBox("Data sent!")            client.Close()        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End SubEnd Class
Author’s Note: Most of the code for socket communication is similar to that used in my previous article, “Take Your Apps Far and Wide with a GPS Tracking System.”

Back in the code-behind for Form1, add the following member variables:

Public Class Form1    Private sig As New Signature    '---use for synchronization---    Private sync As New Sync    '---IP address of the server---    Private ServerIP As String = "10.0.1.2"    '---the ID of the user---    Private ID As String = "1"
Author’s Note: Substitute “10.0.1.2” with the IP address of your own server. More on this in the next section.

Using the data-binding feature of Visual Studio 2005, bind the SQL Mobile database Northwind.sdf to a DataGrid control (see Figure 7) and add a Send menu item.

Author’s note: You can refer to this screen cast to understand how to bind a table in a database to a DataGrid control.

Code the Send menu button as follows:

    Private Sub MenuItem1_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles MenuItem1.Click        '---send to the server---        Dim OrderID As String = _           OrdersDataGrid.Item( _           OrdersDataGrid.CurrentCell.RowNumber, 0). _           ToString()        sync.PerformSync(ServerIP, ID & "#" & OrderID & _           "#" & Now & "#" & sig.Signature)        '---clear the signature---        sig.InitSignature()    End Sub

Essentially, you are sending the following information to the server:

  • ID of the person making the delivery
  • Order ID
  • Date and time of delivery
  • Signature of the recipient

Building a Server
You will now build a Windows application that acts as the server and receives delivery information from clients. Using Visual Studio 2005, create a new Windows application project and name it SyncServer.

Your server will display the signature of the recipient for each delivery, thus you will reuse the code for the signature control developed earlier.

Add the Signature.bmp 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 the “Copy to Output Directory” property to “Copy if newer.”

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. This is the signature control that you will use on the server side. Populate it as shown in Listing 1.

Note that because the signature control used on the server side is used for displaying signatures (and not capturing them), you can omit the three main events?OnMouseDown, OnMouseMove, and OnMouseUp.

Next add a new Class file to the project (right-click on project name in Solution Explorer and select Add | New Item?) for receiving connections from clients. Name the class file as WMClient.vb. Populate it as shown in Listing 2.

Author’s Note: Most of the code in Listing 2 is adapted from my previous article, “Take Your Apps Far and Wide with a GPS Tracking System.”

Back in Form1, populate it with the following controls (see also Figure 8):

  • Label
  • ListBox


Figure 8. Populate Form1 (server) with the Label and ListBox controls as shown.
?
Figure 9. Testing the application.

For simplicity, all the delivery information sent by the clients will be added to the ListBox control. In the real world, you should persist all delivery information to a database.

Switch to the code-behind of Form1 and import the following namespaces:

Imports System.Net.SocketsImports System.Threading

Declare the following member variables:

Public Class Form1    Dim WithEvents user As WMClient    Dim sig As New Signature    '---storing signature for each user---    Private Signatures As New ArrayList

Define the ListenForConnections() subroutine to listen for incoming connections from clients:

    Private Sub ListenForConnections()        Const portNo As Integer = 3456        Dim localAdd As System.Net.IPAddress = _           System.Net.IPAddress.Parse("10.0.1.2")        Dim listener As New TcpListener(localAdd, portNo)        listener.Start()        While True            user = New WMClient(listener.AcceptTcpClient)        End While    End Sub
Author’s Note: Substitute “10.0.1.2” with the IP address of your own server.

In the Form1_Load event, spin off a thread to listen for incoming connections and add a new signature control to the form:

    Private Sub Form1_Load( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles MyBase.Load        '---listen for incoming connections---        Dim t1 As New Thread(AddressOf ListenForConnections)        t1.Start()        '---add a signature control---        With sig            .Location = New Point(294, 25)            .Size = New Size(233, 73)            .InitSignature()        End With        Me.Controls.Add(sig)        Me.Refresh()    End Sub

Define the InformationReceived() subroutine to handle the DataReceived event defined in the WMClient class. The DataReceived event is fired whenever the server receives the data sent by the client. Here, you will update the information on the ListBox control as well as display the signature on the signature control. All of these tasks are done via a delegate:

    Private Sub InformationReceived( _       ByVal ID As Integer, _       ByVal OrderID As String, _       ByVal DateTime As String, _       ByVal signature As String) Handles user.DataReceived        '---display the received information---        Me.BeginInvoke(New _            mydelegate(AddressOf DisplayInformation), _            New Object() {ID, OrderID, DateTime, signature})    End Sub    Private Delegate Sub mydelegate( _       ByVal ID As Integer, _       ByVal OrderID As String, _       ByVal DateTime As String, _       ByVal signature As String)

The DisplayInformation() subroutine adds the delivery information to the ListBox control and then displays the signature received. Note that the signature for each item in the ListBox control is saved in an ArrayList object.

    Private Sub DisplayInformation( _       ByVal ID As Integer, _       ByVal OrderID As String, _       ByVal DateTime As String, _       ByVal signature As String)        Dim str As String = ID & vbTab & _                            OrderID & vbTab & _                            DateTime        ListBox1.Items.Add(str)        Signatures.Add(signature)        With sig            .InitSignature()            .Signature = signature        End With    End Sub

Finally, service the SelectedIndexChanged event for the ListBox control so that when each item in the ListBox control is clicked, the signature for each delivery will be shown:

    Private Sub ListBox1_SelectedIndexChanged( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles ListBox1.SelectedIndexChanged        If ListBox1.SelectedIndex < 0 Then Exit Sub        sig.InitSignature()        sig.Signature = Signatures.Item(ListBox1.SelectedIndex)    End Sub

That's it! You can now press F5 to test the server. On the Pocket PC, select an order and then sign on the signature control (see Figure 9). Click on the Send menu item to send the delivery information as well as the signature to the server.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist