Signature control

Last post 01-03-2006 21:56 by Anonymous. 3 replies.
Page 1 of 1 (4 items)
Sort Posts: Previous Next
  • 09-04-2005 20:51

    Signature control

    In case anyone may have some use for this, here is some VB.NET code I have for converting signatures which came from the obsolete GetSignature method so they can be loaded using the newer LoadSignatureEx method:

    (Note can someone please update the Obsolete attributes on the LoadSignature and GetSignature methods in the source file Signature.cs so it only generates a warning instead of a build error)

        Function UpgradeSignature(ByVal baFrom() As Byte) As Byte()
    'This ensures that the signature byte array is correct for the OpenNetCF 1.4 signature control
    'LoadSignature and GetSignature (all values were 32 bit) have been replaced with
    'LoadSignatureEx and GetSignatureEx (all values either 8 or 16 bit depending on signature dimensions)
    If baFrom.Length < 4 Then
    Return baFrom
    ElseIf Not (baFrom(2) = 0 And baFrom(3) = 0) Then
    'already at correct version
    Return baFrom
    Else
    'old version. convert to new version
    Dim idx As Int32
    Dim width As Int32
    Dim height As Int32
    Dim word As Int32
    Dim ms As MemoryStream = New MemoryStream
    Dim writer As BinaryWriter = New BinaryWriter(ms)
    Dim points As Int32
    Dim currX As Int32 = -1
    Dim currY As Int32 = -1

    For idx = 0 To baFrom.Length() - 3 Step 4
    word = Convert.ToInt32(baFrom(idx))
    word = word + (Convert.ToInt32(baFrom(idx + 1)) * &H100)
    'ignore the upper bytes of the word as they will be 0 and will be stripped anyway

    If idx = 0 Then
    '1st word is width
    width = word
    writer.Write(Convert.ToInt16(width))
    ElseIf idx = 4 Then
    '2nd word is height
    height = word
    writer.Write(Convert.ToInt16(height))
    Else
    If points = 0 Then
    'get next line. note this should always occur for 3rd word
    points = word
    writer.Write(Convert.ToInt16(points))
    Else
    If currX = -1 Then
    currX = word
    If width < 256 Then
    writer.Write(Convert.ToByte(word))
    Else
    writer.Write(Convert.ToInt16(word))
    End If
    ElseIf currY = -1 Then
    currY = word
    points -= 1
    If height < 256 Then
    writer.Write(Convert.ToByte(word))
    Else
    writer.Write(Convert.ToInt16(word))
    End If

    currX = -1
    currY = -1
    End If

    End If
    End If
    Next

    writer.Close()
    ms.Close()
    Return ms.ToArray()
    End If

    End Function


    In addition, I've seen requests from people asking how to use the signature data to get a bitmap. Here is some VB6 code to do it. This code also handles different versions of stored signatures.
    Note you will need to create a Form called frmDrawSignature with a PictureBox on it named Picture1.
    You can load the arrSig byte array from an ADO recordset using rst("SigField").GetChunk(rst("SigField").ActualSize)

    You can then call the function to set the Picture property of a PictureBox control (or like my case, an ActiveReports Image control)
    e.g. imgSignature.Picture = DrawSignature(mbytSig, vbWhite)


    Function DrawSignature(arrSig() As Byte, BackColor As Long) As StdPicture
    Dim pic As PictureBox
    Dim word As Long
    Dim lngIndex As Long
    Dim lngPointsToRead As Long
    Dim lngCurrX As Long
    Dim lngCurrY As Long
    Dim lngPrevX As Long
    Dim lngPrevY As Long
    Dim lngWidth As Long
    Dim lngHeight As Long

    On Error GoTo Err_DrawSignature

    Load frmDrawSignature
    Set pic = frmDrawSignature.Picture1
    pic.BackColor = BackColor
    pic.Cls
    lngCurrX = -1
    lngCurrY = -1
    lngPrevX = -1
    lngPrevY = -1

    If UBound(arrSig) < 3 Then
    Exit Function
    End If

    'if 3rd and 4th bytes are zero then this is old format signature (OpenNetCF 1.2)
    'old sig has 32 bit values, new sig has 16 bit values
    If arrSig(2) = 0 And arrSig(3) = 0 Then
    For lngIndex = 0 To UBound(arrSig) - 3 Step 4
    word = arrSig(lngIndex)
    word = word + CLng(arrSig(lngIndex + 1)) * &H100
    word = word + CLng(arrSig(lngIndex + 2)) * &H10000
    'no unsigned ints so need to handle if > &H7FFFFFFF
    If arrSig(lngIndex + 3) < 128 Then
    word = word + CLng(arrSig(lngIndex + 3)) * &H1000000
    Else
    word = word + (CLng(arrSig(lngIndex + 3)) - 128) * &H1000000
    word = -2147483648# + word
    End If
    If lngIndex = 0 Then
    '1st word is width
    lngWidth = word
    pic.Width = lngWidth * Screen.TwipsPerPixelX
    ElseIf lngIndex = 4 Then
    '2nd word is height
    lngHeight = word
    pic.Height = lngHeight * Screen.TwipsPerPixelY
    Else
    If lngPointsToRead = 0 Then
    'get next line. note this should always occur for 3rd word
    lngPointsToRead = word
    lngPrevX = -1
    lngPrevY = -1
    Else
    If lngCurrX = -1 Then
    lngCurrX = word * Screen.TwipsPerPixelX
    ElseIf lngCurrY = -1 Then
    lngCurrY = word * Screen.TwipsPerPixelY
    lngPointsToRead = lngPointsToRead - 1

    If lngPrevX <> -1 Then
    pic.Line (lngPrevX, lngPrevY)-(lngCurrX, lngCurrY)
    End If

    lngPrevX = lngCurrX
    lngPrevY = lngCurrY
    lngCurrX = -1
    lngCurrY = -1
    End If
    End If
    End If
    Next
    Else
    'new format sig (OpenNetCF 1.4)
    'width, height & linecount stored as 16 bit ints
    'point.x stored as byte if width <256, otherwise 16 bit int
    'point.y stored as byte if height <256, otherwise 16 bit int

    word = arrSig(0)
    word = word + CLng(arrSig(1)) * &H100
    lngWidth = word
    pic.Width = lngWidth * Screen.TwipsPerPixelX
    word = arrSig(2)
    word = word + CLng(arrSig(3)) * &H100
    lngHeight = word
    pic.Height = lngHeight * Screen.TwipsPerPixelY

    lngIndex = 4
    Do While True
    If lngIndex > UBound(arrSig) Then Exit Do

    If lngPointsToRead = 0 Then
    'get next line. note this should always occur for 3rd word
    word = arrSig(lngIndex)
    lngIndex = lngIndex + 1
    word = word + CLng(arrSig(lngIndex)) * &H100
    lngPointsToRead = word
    lngPrevX = -1
    lngPrevY = -1
    Else
    If lngCurrX = -1 Then
    word = arrSig(lngIndex)
    If lngWidth > 255 Then
    lngIndex = lngIndex + 1
    word = word + CLng(arrSig(lngIndex)) * &H100
    End If
    lngCurrX = word * Screen.TwipsPerPixelX
    ElseIf lngCurrY = -1 Then
    word = arrSig(lngIndex)
    If lngHeight > 255 Then
    lngIndex = lngIndex + 1
    word = word + CLng(arrSig(lngIndex)) * &H100
    End If
    lngCurrY = word * Screen.TwipsPerPixelY
    lngPointsToRead = lngPointsToRead - 1

    If lngPrevX <> -1 Then
    pic.Line (lngPrevX, lngPrevY)-(lngCurrX, lngCurrY)
    End If

    lngPrevX = lngCurrX
    lngPrevY = lngCurrY
    lngCurrX = -1
    lngCurrY = -1
    End If
    End If

    lngIndex = lngIndex + 1
    Loop
    End If

    Set DrawSignature = pic.Image

    Exit_DrawSignature:
    Set pic = Nothing
    If IsFormLoaded("frmDrawSignature") Then Unload frmDrawSignature
    Exit Function

    Err_DrawSignature:
    MsgBox "Error " & Err.Number & " " & Err.Description & " in basMisc.DrawSignature"
    Resume Exit_DrawSignature
    Resume
    End Function


    (If you need the IsFormLoaded function, Google for it)

    Regards.
    Graeme Francis
  • 10-06-2005 8:40 In reply to

    Re: Signature control

    Here is the C# version... Tested on the v1.2 side. Not on the v1.4 side, but should work.

    This is the Compact Framework version as well!

    private System.Drawing.Image DrawSignature(byte[] arrSig, System.Drawing.Color BackColor)
    {
    System.Windows.Forms.PictureBox pic;
    int word;
    int lngIndex;
    int lngPointsToRead = 0;
    int lngCurrX;
    int lngCurrY;
    int lngPrevX;
    int lngPrevY;
    int lngWidth = 1;
    int lngHeight;
    Bitmap bit = new Bitmap(1, 1);
    Graphics g = Graphics.FromImage(bit);
    pic = new PictureBox();
    Pen blackPen = new Pen(Color.Black);
    lngCurrX = -1;
    lngCurrY = -1;
    lngPrevX = -1;
    lngPrevY = -1;
    if (arrSig.Length < 3)
    {
    return null;
    }
    if (arrSig[2] == 0 & arrSig[3] == 0)
    {
    for (lngIndex = 0; lngIndex <= arrSig.Length - 3; lngIndex += 4)
    {
    word = arrSig[lngIndex];
    word = word + System.Convert.ToInt32(arrSig[lngIndex + 1]) * 256;
    word = word + System.Convert.ToInt32(arrSig[lngIndex + 2]) * 65536;
    if (arrSig[lngIndex + 3] < 128)
    {
    word = word + System.Convert.ToInt32(arrSig[lngIndex + 3]) * 16777216;
    }
    else
    {
    word = word + (System.Convert.ToInt32(arrSig[lngIndex + 3]) - 128) * 16777216;
    word = -2147483648 + word;
    }
    if (lngIndex == 0)
    {
    lngWidth = word;
    }
    else if (lngIndex == 4)
    {
    lngHeight = word;
    bit = new Bitmap(lngWidth, lngHeight);
    g = Graphics.FromImage(bit);
    g.Clear(BackColor);
    }
    else
    {
    if (lngPointsToRead == 0)
    {
    lngPointsToRead = word;
    lngPrevX = -1;
    lngPrevY = -1;
    }
    else
    {
    if (lngCurrX == -1)
    {
    lngCurrX = word;
    }
    else if (lngCurrY == -1)
    {
    lngCurrY = word;
    lngPointsToRead = lngPointsToRead - 1;
    if (lngPrevX != -1)
    {
    g.DrawLine(blackPen, lngPrevX, lngPrevY, lngCurrX, lngCurrY);
    }
    lngPrevX = lngCurrX;
    lngPrevY = lngCurrY;
    lngCurrX = -1;
    lngCurrY = -1;
    }
    }
    }
    }
    }
    else
    { //OpenNETCF v1.4 version
    word = arrSig[0];
    word = word + System.Convert.ToInt32(arrSig[1]) * 256;
    lngWidth = word;
    word = arrSig[2];
    word = word + System.Convert.ToInt32(arrSig[3]) * 256;
    lngHeight = word;
    bit = new Bitmap(lngWidth, lngHeight);
    g = Graphics.FromImage(bit);
    g.Clear(BackColor);
    lngIndex = 4;
    while (true)
    {
    if (lngIndex > arrSig.Length)
    {
    goto exitDoLoopStatement0;
    }
    if (lngPointsToRead == 0)
    {
    word = arrSig[lngIndex];
    lngIndex = lngIndex + 1;
    word = word + System.Convert.ToInt32(arrSig[lngIndex]) * 256;
    lngPointsToRead = word;
    lngPrevX = -1;
    lngPrevY = -1;
    }
    else
    {
    if (lngCurrX == -1)
    {
    word = arrSig[lngIndex];
    if (lngWidth > 255)
    {
    lngIndex = lngIndex + 1;
    word = word + System.Convert.ToInt32(arrSig[lngIndex]) * 256;
    }
    lngCurrX = word;
    }
    else if (lngCurrY == -1)
    {
    word = arrSig[lngIndex];
    if (lngHeight > 255)
    {
    lngIndex = lngIndex + 1;
    word = word + System.Convert.ToInt32(arrSig[lngIndex]) * 256;
    }
    lngCurrY = word;
    lngPointsToRead = lngPointsToRead - 1;
    if (lngPrevX != -1)
    {
    g.DrawLine(blackPen, lngPrevX, lngPrevY, lngCurrX, lngCurrY);
    }
    lngPrevX = lngCurrX;
    lngPrevY = lngCurrY;
    lngCurrX = -1;
    lngCurrY = -1;
    }
    }
    lngIndex = lngIndex + 1;
    }
    exitDoLoopStatement0: ;
    }
    pic.Image = bit;
    return pic.Image;
    }
  • 10-10-2005 16:27 In reply to

    Re: Signature control

    thanks a lot.

    in the OpenNETCF v1.4 version of the c# code
    there seems to be a bug in the line:

    if (lngIndex > arrSig.Length)

    i think it should be:

    if (lngIndex >= arrSig.Length)

    after fixing that, it works great now.

    again, thanks a lot.

  • 01-03-2006 21:56 In reply to

    Re: Signature control

    I am saving signature to the database on the PDA, and am able to retrieve and display it back. However I run into problems after I sync, and try to display it on the web. I tried to convert it to an Image using DrawSignature C# method above, but cannot do it since System.Windows.Forms.PictureBox class is not available in ASP.Net. Can you please help?

    Thanks,
    Ilya
Page 1 of 1 (4 items)