11
Sep
09

Using Topaz Signature Pads to Capture Signatures for InfoPath 2007 Forms

This is a great solution created by Richard Wixom, whom I’ve worked with over the years.  Richard is the president and owner of DNSalePrice.com.  He spends a lot of his time buried in algorithms deciphering the goings on in the domain name industry and creating huge databases with information about domain names.  We collaboratively worked on this solution and thought it was an interesting exercise that others might appreciate.

TOPAZ Signature Pads can be enabled for InfoPath 2007 with the signature image then stored and embedded within the InfoPath form. The following approach uses C#/.Net managed code with the code and appropriate DLL’s embedded within published InfoPath forms. Standard InfoPath features such as email distribution, SharePoint storage, etc. are available for InfoPath client. Web-enabled InfoPath forms are not supported.

Prerequisites for enabling TOPAZ Signature Pads with InfoPath 2007:

1. TOPAZ signature pad hardware and software installed.

2. Security level for InfoPath form set to Full Trust and signed.

3. Programming language for InfoPath form set to “C#”

4. Compatibility for InfoPath form and “Design form template that can be opened in browser” is not set.

5. Local access to the C# SigPlusNET assembly. This can be found in the Topaz’s “SigPlusNETDemoCSharp” download that is available here.

Setup requires three steps:

1. Adding the required controls to InfoPath form

2. Adding DLL reference to code

3. Adding required code

Estimated time to complete should be under five minutes.

Add Required Controls

In “Design” mode, create a new InfoPath form and verify/set settings as stated in “Prerequisites.” Add two Buttons, a Text Box and a Picture control to the form. Use a layout similar to the following:

clip_image002

Set the control properties on the first button (Label and ID) as shown below. Both C# and XML are case-sensitive languages so be sure to use the same letter case as shown.

clip_image004

Set the control properties for the second button as shown below:clip_image006

For the Text Box properties, under Data tab, set Field name as shown below:

clip_image008

For the Text Box properties, Display tab, check “Read-only” as shown below:

clip_image010

For the Text Box properties, Size tab, set size values as shown below:

clip_image012

For the Picture properties, under the Data tab, enter Field name as shown below and uncheck the box to “Allow the user to browse, delete, and replace pictures.”

clip_image014

Under Tools/Programming, open Microsoft Visual Studio Tools for Applications. In the Project Explorer (see tabs on right), right-click on “Reference”, select “Add Reference” and add the following two references:

1. Under the .Net tab, locate and add “System.Drawing”.

2. Under the Browse tab, navigate the full path to SigPlusNETDemoCSharp (see Prerequisites) and add “SigPlus.dll”.

Project Explorer should now look like the following (see highlighted reference):clip_image016

Now cut and paste the following replacement code over the default code — EXCEPT you will need to preserve the default namespace that is provided. The following is an example of the default namespace that you’ll need to preserve when pasting the replacement code.

clip_image018

Replacement code:

using Microsoft.Office.InfoPath;
using System;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using mshtml;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace _0900_A_with_Signature ç [retain the default value here]
{
public partial class FormCode
{
internal Topaz.SigPlusNET SigPlus = new Topaz.SigPlusNET();
// NOTE: The following procedure is required by Microsoft Office InfoPath.
// It can be modified using Microsoft Office InfoPath.
public void InternalStartup()
{
((ButtonEvent)EventManager.ControlEvents["Button_Sign"]).Clicked += new ClickedEventHandler(Button_Sign_Clicked);
((ButtonEvent)EventManager.ControlEvents["Button_Done"]).Clicked += new ClickedEventHandler(Button_Done_Clicked);
}
public void Button_Sign_Clicked(object sender, ClickedEventArgs e)
{
SetSignatureImage(String.Empty);
SetTopazMessage("Sign on signature pad and then click \"Done\".");
SigPlus.SetTabletState(1); //tablet on
SigPlus.ClearTablet();
}
public void Button_Done_Clicked(object sender, ClickedEventArgs e)
{
SigPlus.SetTabletState(0); //tablet off
SigPlus.SetImageXSize(400);
SigPlus.SetImageYSize(100);
SigPlus.SetImagePenWidth(11);
SigPlus.SetJustifyMode(5);
Image sigImage = SigPlus.GetSigImage();
String sigBase64 = ImageToBase64(sigImage, ImageFormat.Jpeg);
//verify signature entered and read
if (sigBase64.Length > 2000)
{
SetSignatureImage(sigBase64);
SetTopazMessage(string.Empty);
}
else { SetTopazMessage("Signature not recoginized. Please verify signature pad, then click \"Sign\" button and follow instructions."); }
}
public void SetTopazMessage(string message)
{
string XpathForTopazMessage = "/my:Fields/my:TopazMessage";
XPathNavigator messageField = this.MainDataSource.CreateNavigator().SelectSingleNode(XpathForTopazMessage, NamespaceManager);
messageField.SetValue(message);
}
public void SetSignatureImage(string base64Image)
{
string XpathForSignatureImage = "/my:Fields/my:SignatureImage";
XPathNavigator imageField = this.MainDataSource.CreateNavigator().SelectSingleNode(XpathForSignatureImage, NamespaceManager);
DeleteNil(imageField); //remove xsi:nil attribute
imageField.SetValue(base64Image);
}
public string ImageToBase64(Image image, ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}
public void DeleteNil(XPathNavigator node)

{

if (node.MoveToAttribute("nil","http://www.w3.org/2001/XMLSchema-instance"))
{
node.DeleteSelf();
}
}
}
}

Click on “Build” and verify that your template builds without programming errors. If you encounter any errors, correct as required. The most common error will be incorrect entry of control ids as noted above.

Save your source files, close Visual Studio for Applications, add required content and controls to your InfoPath form and publish.

Advertisements

16 Responses to “Using Topaz Signature Pads to Capture Signatures for InfoPath 2007 Forms”


  1. February 25, 2010 at 10:17 am

    I have done everything as stated on the blog, I am getting this error. The link is a screen shot. I am awful when it comes to the C# stuff. Thanks for your help.

    Thanks,
    Shawn

  2. March 1, 2010 at 9:20 am

    I have followed the instructions for using a Topaz Signature Pad with InfoPath to the T and it isn’t working. I get the following errors:

    An unhandled exception has occurred in the form’s code.

    System.NullReferenceException
    Object reference not set to an instance of an object.
    at _0900_A_with_Signature.FormCode.DeleteNil(XPathNavigator node)
    at _0900_A_with_Signature.FormCode.SetSignatureImage(String base64Image)
    at _0900_A_with_Signature.FormCode.Button_Sign_Clicked(Object sender, ClickedEventArgs e)
    at Microsoft.Office.InfoPath.Internal.ButtonEventHost.OnButtonClick(DocActionEvent pEvent)
    at Microsoft.Office.Interop.InfoPath.SemiTrust._ButtonEventSink_SinkHelper.OnClick(DocActionEvent pEvent)

    Any ideas on what I am doing wrong? any help would be greatly appreciated.

  3. 3 Russell Wright
    March 1, 2010 at 10:39 pm

    Of course, one of the things that happens when you post code that is not fully debugged is that you get, well, uh…bugs. Try something like this in SetSignatureImage.

    internal void SetSignatureImage(string base64Image, ClickedEventArgs e)
    {

    try
    {
    XPathNavigator imageField = GetNavigator(baseSignatureImage, e);
    DeleteNil(imageField); //remove xsi:nil attribute
    imageField.SetValue(base64Image);
    }
    catch
    {
    UnexpectedError();
    }

    }

  4. 4 Nick
    April 22, 2010 at 8:26 am

    I was also receiving the same error message as Julie Ziriax and replaced SetSignatureImage with what you provided, but it is still giving me errors while building.

    No overload for method ‘SetSignatureImage’ takes ‘1’ arguments (occurs twice)
    The name ‘GetNavigator’ does not exist in the current context
    The name ‘baseSignatureImage’ does not exist in the current context
    The name ‘UnexpectedError’ does not exist in the current context

    After trying on my own for a while, the best I could do was still having DeleteNil create the same error message as before.

    Any help would be much appreciated

  5. May 4, 2010 at 9:44 am

    The code below works beautifully for us.

    using Microsoft.Office.InfoPath;
    using System;
    using System.Drawing;
    using System.IO;
    using System.Windows.Forms;
    using System.Xml;
    using System.Xml.XPath;
    using mshtml;

    namespace Sign2
    {
    public partial class FormCode
    {
    Topaz.SigPlusNET SigPlusNET1;

    // NOTE: The following procedure is required by Microsoft Office InfoPath.
    // It can be modified using Microsoft Office InfoPath.
    public void InternalStartup()
    {
    ((ButtonEvent)EventManager.ControlEvents[“CTRL1_5”]).Clicked += new ClickedEventHandler(CTRL1_5_Clicked);
    ((ButtonEvent)EventManager.ControlEvents[“CTRL2_5”]).Clicked += new ClickedEventHandler(CTRL2_5_Clicked);
    ((ButtonEvent)EventManager.ControlEvents[“CTRL3_5”]).Clicked += new ClickedEventHandler(CTRL3_5_Clicked);
    ((ButtonEvent)EventManager.ControlEvents[“CTRL7_5”]).Clicked += new ClickedEventHandler(CTRL7_5_Clicked);
    ((ButtonEvent)EventManager.ControlEvents[“CTRL8_5”]).Clicked += new ClickedEventHandler(CTRL8_5_Clicked);
    ((ButtonEvent)EventManager.ControlEvents[“CTRL9_5”]).Clicked += new ClickedEventHandler(CTRL9_5_Clicked);
    }

    // NOTE: The following procedure is required by Microsoft Office InfoPath.
    // It can be modified using Microsoft Office InfoPath.

    public void CTRL1_5_Clicked(object sender, ClickedEventArgs e)
    {
    // Initiate the signature pad
    SigPlusNET1 = new Topaz.SigPlusNET();

    SigPlusNET1.SetTabletState(1);
    }

    public void CTRL2_5_Clicked(object sender, ClickedEventArgs e)
    {
    if (SigPlusNET1.NumberOfTabletPoints() > 0)
    {

    Image myimage = null;

    SigPlusNET1.SetImageXSize(250);
    SigPlusNET1.SetImageYSize(100);
    SigPlusNET1.SetJustifyMode(5);
    SigPlusNET1.SetImagePenWidth(7);

    SigPlusNET1.SetImageFileFormat(0);
    if (SigPlusNET1.NumberOfTabletPoints() > 0)
    {
    myimage = SigPlusNET1.GetSigImage();
    }
    else
    {
    MessageBox.Show(“Please sign the signature pad and try again”);
    return;
    }

    /// set the form picture field to the image read from the SigPad
    // get access to the picture attachment field
    XPathNavigator MyPic = this.CreateNavigator().SelectSingleNode(“/my:myFields/my:Signature”, NamespaceManager);
    DeleteNil(MyPic);

    // this is where the real work is done. Simply take the bytes from the signature image and convert them to base64.
    MyPic.SetValue(Convert.ToBase64String(imageToByteArray(myimage)));

    /// cleanup
    // dispose of the field
    MyPic = null;
    }
    else
    {
    MessageBox.Show(“No signature captured!”);
    }
    }

    public void CTRL3_5_Clicked(object sender, ClickedEventArgs e)
    {
    SigPlusNET1.ClearTablet();

    // get access to the picture attachment field
    XPathNavigator MyPic = this.CreateNavigator().SelectSingleNode(“/my:myFields/my:Signature”, NamespaceManager);
    DeleteNil(MyPic);

    // Clear the signature
    MyPic.SetValue(“”);
    }
    public void CTRL7_5_Clicked(object sender, ClickedEventArgs e)
    {
    // Initiate the signature pad
    SigPlusNET1 = new Topaz.SigPlusNET();

    SigPlusNET1.SetTabletState(1);
    }

    public void CTRL8_5_Clicked(object sender, ClickedEventArgs e)
    {
    if (SigPlusNET1.NumberOfTabletPoints() > 0)
    {

    Image myimage = null;

    SigPlusNET1.SetImageXSize(250);
    SigPlusNET1.SetImageYSize(100);
    SigPlusNET1.SetJustifyMode(5);
    SigPlusNET1.SetImagePenWidth(7);

    SigPlusNET1.SetImageFileFormat(0);
    if (SigPlusNET1.NumberOfTabletPoints() > 0)
    {
    myimage = SigPlusNET1.GetSigImage();
    }
    else
    {
    MessageBox.Show(“Please sign the signature pad and try again”);
    return;
    }

    /// set the form picture field to the image read from the SigPad
    // get access to the picture attachment field
    XPathNavigator MyPic = this.CreateNavigator().SelectSingleNode(“/my:myFields/my:Signature2”, NamespaceManager);
    DeleteNil(MyPic);

    // this is where the real work is done. Simply take the bytes from the signature image and convert them to base64.
    MyPic.SetValue(Convert.ToBase64String(imageToByteArray(myimage)));

    /// cleanup
    // dispose of the field
    MyPic = null;
    }
    else
    {
    MessageBox.Show(“No signature captured!”);
    }
    }

    public void CTRL9_5_Clicked(object sender, ClickedEventArgs e)
    {
    SigPlusNET1.ClearTablet();

    // get access to the picture attachment field
    XPathNavigator MyPic = this.CreateNavigator().SelectSingleNode(“/my:myFields/my:Signature2”, NamespaceManager);
    DeleteNil(MyPic);

    // Clear the signature
    MyPic.SetValue(“”);
    }

    public void DeleteNil(XPathNavigator node)
    {
    if (node.MoveToAttribute(“nil”, “http://www.w3.org/2001/XMLSchema-instance”))
    node.DeleteSelf();
    }

    public byte[] imageToByteArray(System.Drawing.Image imageIn)
    {
    MemoryStream ms = new MemoryStream();
    try
    {
    imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
    }
    catch
    {
    MessageBox.Show(“Conversion of image failed”);
    }
    return ms.ToArray();
    }
    }
    }

  6. 6 Cameron
    December 19, 2011 at 2:22 pm

    Thanks Russell. I had to tweak the code a little to make your example work. Basically where it says

    string XpathForTopazMessage = “/my:Fields/my:TopazMessage”;
    AND
    string XpathForSignatureImage = “/my:Fields/my:SignatureImage”;

    The xpath is incorrect. In order to get the correct XPath, just get it from Infopath by right clicking on the My Fields on the right and selecting Copy XPath.

    Corrected XPath
    “/my:myFields/my:TopazMessage”;
    “/my:myFields/my:SignatureImage”;

  7. 7 Chuito
    January 9, 2013 at 2:20 pm

    For a strange situation i have to replace using to Imports and the rest of the code doesn’t work i have 66 Errors, can anyone help me?

  8. 9 Chuito
    January 9, 2013 at 3:05 pm

    Error= Newline in constant, ) expected
    if (node.MoveToAttribute(“nil”,”http://www.w3.org/2001/XMLSchema-instance"))
    {
    node.DeleteSelf();
    }
    help please

  9. 12 rbell6
    January 23, 2013 at 1:04 pm

    that is a good solution, I was wondering if there is a way to also have the signature be displayed on screen as it is being drawn, maybe with ink picture? That would be helpful for people that don’t have a signature pad with LCD.

  10. 13 rbell6
    January 23, 2013 at 1:06 pm

    Is there a way to have the signature show on screen while drawing? This would be helpful if someone doesn’t have lcd on signature pad.

  11. May 23, 2014 at 1:04 am

    Topaz Signature Pads are very helpful for my business because I have to sign thousands of documents and checks daily. It has made my work a lot simpler.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Asif Rehmani’s SharePoint Videos

SharePoint-Videos

Click to access a wealth of SharePoint videos

SharePoint Rx

SharePoint Rx Home

Categories

Posts by Date

September 2009
M T W T F S S
« Aug   Dec »
 123456
78910111213
14151617181920
21222324252627
282930  
Support Wikipedia

%d bloggers like this: