Generating signatures

How to generate programmatly a user signature ?
must present a support as a form to draw manually the user signature and save it as image format.
can integrate it in a field table or put it simply in a folder and call it when needed.
i present 3 solutions to do that
-a pure vfp solution with native and extended gdiplusX
-a mixed code vfp+pure javascript solution
-using a cool com microsoft object shipped with win8.1 and win10 (this last for sure).
-i hope soon publishing a pure vfp solution with APIs only.
this code produces a signature as image.
it uses a toolbar class with some utilities.
*draw signature with vfp native functions
*can clear drawing or make eraser to clear some drawing portion (can choose its width).
*can use pen (with drawWidth property) and choose its color.
*uses gdiplusX to capture drawing as png image and resize it as wanted (width x height)
*can view image produced
*system.app of gdiplusX library must be in source folder in preference.
Click on code to select [then copy] -click outside to deselect
*1*
Publi yform
yform=Newobject("ysignature")
yform.Show
Read Events
Retu
*
Define Class ysignature As Form
Height = 480
Width = 680
ShowTips=.T.
ShowWindow = 2
AutoCenter = .T.
Caption = "Enter Your Signature Below"
FillStyle = 0
Icon = ""
BackColor = Rgb(255,255,255)
otoolbar = .F.
Name = "Form1"
Procedure capture
Local lcdest
m.lcdest=m.yrep+"ysignature.png"
Local loBMP As xfcbitmap
Thisform.otoolbar.Hide()
sleep(20)
With _Screen.System.drawing
loBMP = .Bitmap.fromscreen(_Screen.ActiveForm.HWnd,0+Sysmetric(3),0+Sysmetric(9)+Sysmetric(4),Thisform.Width,Thisform.Height)
Local lnWidth, lnHeight
lnWidth=Thisform.otoolbar.text1.Value
lnHeight=Thisform.otoolbar.text2.Value
If lnWidth=0
lnWidth=120
Endi
If lnHeight=0
lnHeight=60
Endi
******
* Create a New Image with the desired size
Local loResized As xfcbitmap
loResized = .Bitmap.New(lnWidth, lnHeight,.Imaging.PixelFormat.Format32bppARGB)
* Set the image resolution to be the same as the original
loResized.SetResolution(loBMP.HorizontalResolution,loBMP.VerticalResolution)
* Obtain a Graphics object to get the rights to draw on it
Local loGfx As xfcGraphics
loGfx = .Graphics.FromImage(loResized)
* Set some properties, to ensure to have a better quality of image
loGfx.SmoothingMode = .Drawing2D.SmoothingMode.HighQuality
loGfx.InterpolationMode = .Drawing2D.InterpolationMode.HighQualityBicubic
* Draw the source image on the new image at the desired dimensions
loGfx.DrawImage(loBMP, 0, 0, lnWidth, lnHeight)
* Save the resized image as Png
loResized.Save(m.lcdest, .Imaging.ImageFormat.Png)
Endwith
Thisform.otoolbar.Show()
Messagebox(m.lcdest+" captured !",0+32+4096,'',1200)
Endproc
Procedure Init
Do Locfile('system.app') &&put system.app in source folder
Declare Integer Sleep In kernel32 Integer
Publi m.yrep
m.yrep=Addbs(Justpath(Sys(16,1)))
With Thisform
.ScaleMode = 3
.MousePointer = 2
.DrawMode = 13
.DrawWidth = 3
Endwith
Endproc
Procedure MouseMove
Lparameters nButton, nShift, nXCoord, nYCoord
If nButton = 1 And This.MousePointer = 2
Thisform.Line(nXCoord, nYCoord)
Endif
Endproc
Procedure MouseDown
Lparameters nButton, nShift, nXCoord, nYCoord
If Thisform.MousePointer = 2
Thisform.PSet(nXCoord, nYCoord)
Endif
Endproc
Procedure Activate
If Type("thisform.oToolbar")="O" And;
!Isnull(Thisform.otoolbar)
Return
Endif
Thisform.otoolbar=Create("ysign",Thisform)
Thisform.otoolbar.Dock(0)
Thisform.otoolbar.Show
Thisform.MouseDown(Thisform.Width/2,Thisform.Height/2)
Endproc
Procedure Destroy
Clea Events
Endproc
Enddefine
*
*-- EndDefine: ysignature
*
Define Class ysign As Toolbar
Caption = "Toolbar1"
Height = 42
Left = 0
Top = 0
Width = 528
ShowWindow = 1
oformref = .F.
Name = "aa"
Add Object separator13 As Separator With ;
Top = 3, ;
Left = 5, ;
Height = 0, ;
Width = 0, ;
Name = "Separator13"
Add Object separator12 As Separator With ;
Top = 3, ;
Left = 13, ;
Height = 0, ;
Width = 0, ;
Name = "Separator12"
Add Object label1 As Label With ;
autosize=.t.,;
FontBold = .T., ;
FontSize = 12, ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,0,128), ;
Caption = "Pen", ;
Height = 24, ;
Left = 13, ;
Top = 3, ;
Width = 36, ;
Name = "Label1"
Add Object separator11 As Separator With ;
Top = 3, ;
Left = 56, ;
Height = 0, ;
Width = 0, ;
Name = "Separator11"
Add Object spinner2 As Spinner With ;
FontBold = .T., ;
Height = 24, ;
KeyboardHighValue = 100, ;
KeyboardLowValue = 1, ;
Left = 56, ;
MousePointer = 15, ;
SpinnerHighValue = 100.00, ;
SpinnerLowValue = 1.00, ;
Top = 3, ;
Width = 44, ;
Value = 4, ;
Name = "Spinner2"
Add Object separator7 As Separator With ;
Top = 3, ;
Left = 107, ;
Height = 0, ;
Width = 0, ;
Name = "Separator7"
Add Object check1 As Checkbox With ;
autosize=.t.,;
Top = 3, ;
Left = 107, ;
Height = 25, ;
Width = 78, ;
FontBold = .T., ;
FontSize = 14, ;
Alignment = 0, ;
Caption = "Eraser", ;
Value = .F., ;
MousePointer = 15, ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,0,128), ;
Name = "Check1"
Add Object separator8 As Separator With ;
Top = 3, ;
Left = 192, ;
Height = 0, ;
Width = 0, ;
Name = "Separator8"
Add Object spinner1 As Spinner With ;
FontBold = .T., ;
Height = 24, ;
KeyboardHighValue = 100, ;
KeyboardLowValue = 1, ;
Left = 192, ;
MousePointer = 15, ;
SpinnerHighValue = 100.00, ;
SpinnerLowValue = 1.00, ;
Top = 3, ;
Width = 44, ;
Value = 14, ;
Name = "Spinner1"
Add Object separator2 As Separator With ;
Top = 3, ;
Left = 243, ;
Height = 0, ;
Width = 0, ;
Name = "Separator2"
Add Object separator1 As Separator With ;
Top = 3, ;
Left = 251, ;
Height = 0, ;
Width = 0, ;
Name = "Separator1"
Add Object separator3 As Separator With ;
Top = 3, ;
Left = 259, ;
Height = 0, ;
Width = 0, ;
Name = "Separator3"
Add Object command2 As CommandButton With ;
Top = 3, ;
Left = 259, ;
Height = 36, ;
Width = 55, ;
FontBold = .T., ;
FontSize = 10, ;
Anchor = 0, ;
Caption = "Capture", ;
MousePointer = 15, ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,128,0), ;
Themes = .F., ;
Name = "command2"
Add Object separator9 As Separator With ;
Top = 3, ;
Left = 321, ;
Height = 0, ;
Width = 0, ;
Name = "Separator9"
Add Object command1 As CommandButton With ;
Top = 3, ;
Left = 321, ;
Height = 36, ;
Width = 72, ;
FontBold = .T., ;
FontSize = 10, ;
Anchor = 8, ;
Caption = " Clear ", ;
TabStop = .F., ;
ToolTipText = "Touch or Click to Clear Signature.", ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,0,128), ;
Themes = .F., ;
Name = "Command1"
Add Object separator10 As Separator With ;
Top = 3, ;
Left = 400, ;
Height = 0, ;
Width = 0, ;
Name = "Separator10"
Add Object command3 As CommandButton With ;
Top = 3, ;
Left = 400, ;
Height = 36, ;
Width = 84, ;
FontBold = .T., ;
FontSize = 10, ;
Anchor = 8, ;
Caption = "Color", ;
MousePointer = 15, ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,0,128), ;
Themes = .F., ;
Name = "Command3"
Add Object separator4 As Separator With ;
Top = 3, ;
Left = 491, ;
Height = 0, ;
Width = 0, ;
Name = "Separator4"
Add Object image1 As Image With ;
Picture = Home(1)+"graphics\icons\win95\explorer.ico", ;
Height = 32, ;
Left = 491, ;
MousePointer = 15, ;
Top = 3, ;
Width = 32, ;
Name = "Image1"
Add Object separator5 As Separator With ;
Top = 46, ;
Left = 5, ;
Height = 0, ;
Width = 0, ;
Name = "Separator5"
Add Object txt1 As TextBox With ;
top=56 , ;
left=5 , ;
height=27 , ;
width=40, ;
value=120 , ;
tooltiptext="Image Width",;
Name="text1"
Add Object separator5_ As Separator With ;
Top = 46, ;
Left = 5, ;
Height = 0, ;
Width = 0, ;
Name = "Separator5_"
Add Object txt1 As TextBox With ;
top=56 , ;
left=5 , ;
height=27 , ;
width=40, ;
value=60 , ;
tooltiptext="Image Height",;
Name="text2"
Add Object separator6 As Separator With ;
Top = 46, ;
Left = 5, ;
Height = 0, ;
Width = 0, ;
Name = "Separator6"
Add Object separator71 As Separator With ;
Top = 46, ;
Left = 5, ;
Height = 0, ;
Width = 0, ;
Name = "Separator71"
Add Object yhelp As Label With ;
FontBold = .T., ;
FontSize = 16, ;
Caption = "?", ;
Height = 24, ;
Left = 13, ;
Top = 3, ;
Width = 36, ;
ForeColor = Rgb(0,0,255), ;
mousepointer=15 , ;
Name = "yHelp"
Procedure Init
#Define ERR_NOFORMPARM_LOC "You must pass a form reference to create this toolbar."
Parameter oForm
If Type("m.oForm")#"O" Or Isnull(m.oForm) Or Upper(oForm.BaseClass) # "FORM"
Messagebox(ERR_NOFORMPARM_LOC)
Return .F.
Endif
This.oformref = oForm
Endproc
Procedure spinner2.InteractiveChange
_Screen.ActiveForm.DrawWidth = This.Value
Endproc
Procedure check1.Click
With _Screen.ActiveForm
If This.Value
.DrawWidth = This.Parent.spinner1.Value
.ForeColor=.BackColor
Else
.DrawWidth =This.Parent.spinner2.Value
.DrawMode = 13
Endif
Endwith
Endproc
Procedure spinner1.InteractiveChange
If This.Parent.check1.Value
_Screen.ActiveForm.DrawWidth = This.Value
Endif
Endproc
Procedure command2.Click
_Screen.ActiveForm.capture()
Endproc
Procedure command1.Click
_Screen.ActiveForm.Cls
This.Parent.check1.Value=.F.
Endproc
Procedure command3.Click
Local m.xcolor
m.xcolor=Getcolor()
If m.xcolor=-1
Return .F.
Endi
With _Screen.ActiveForm
.ForeColor=m.xcolor
.DrawMode=13
Endwith
This.Parent.check1.Value=.F.
Endproc
Procedure image1.Init
This.Picture=Home(1)+"graphics\icons\win95\explorer.ico"
Endproc
Procedure image1.Click
Local m.oo
m.oo=m.yrep+"ysignature.png"
If File(m.oo)
Run/N explorer &oo
Endi
Endproc
Procedure yhelp.Click
local m.myvar
text to m.myvar noshow
this produces a signature as image
*draw signature with vfp native functions
*can clear drawing or make eraser to clear some drawing portion (can choose its width).
*can build pen (with drawWidth) and choose its color.
*uses gdiplusX to capture drawing as png image and resize it as wanted (width x height)
*can view image produced
*system.app of gdiplusX library must be in source folder in preference.
endtext
Messagebox(m.myvar,0+32+4096,"ysignature application")
Endproc
Enddefine
*
*-- EndDefine: ysign
/image%2F1435407%2F20150212%2Fob_ccbf17_demo3.jpg)
Old foxdraw resurrected in one prg - Visual Foxpro codes
This reproduces in one prg the old sample vfp drawing shipped since vfp5.(samples\solution) it builds a toolbar with some drawing tools and a drawing area.the toolbar can be dockable in 4 form side
http://yousfi.over-blog.com/2015/02/old-foxdraw-resurrected-in-one-prg.html
Click on code to select [then copy] -click outside to deselect
*2* a web signature with html5 canvas
*this builds an html5 canvas on a form(IE11 recquired-vfp browser emulation as IE11 recquired)
*choose a pencil color and draw signature.can erase drawing(see button "eraser")
*can clear the drawing with eraser button and mousedown...
*can save signature as PNG imlage on disc (rightclick on and choose a destination png file on disc)
*original javascript source from Web (http://stackoverflow.com/questions/2368784/draw-on-html5-canvas-using-a-mouse)
Publi yform
yform=Newobject("ysign")
yform.Show
Read Events
Retu
*
Define Class ysign As Form
BorderStyle = 0
Height = 440
Width = 850
ShowWindow = 2
MaxButton=.F.
AutoCenter = .T.
Caption = "Canvas Signature-save as PNG..."
Name = "Form1"
Add Object olecontrol1 As OleControl With ;
oleclass="Shell.explorer.2",;
Top = -24, ;
Left = -84, ;
Height = 469, ;
Width = 960, ;
Name = "Olecontrol1"
Procedure Destroy
Erase Addbs(Sys(2023))+"temp.html" &&clean
Clea Events
Endproc
Procedure Init
Set Safe Off
Endproc
Procedure olecontrol1.Init
Local m.myvar
TEXT to m.myvar noshow
<html>
<meta http-equiv="X-UA-Compatible" content="IE=11" >
<script type="text/javascript">
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "black",
y = 2;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
canvas.addEventListener("mousemove", function (e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
findxy('out', e)
}, false);
}
function color(obj) {
switch (obj.id) {
case "green":
x = "green";
break;
case "blue":
x = "blue";
break;
case "red":
x = "red";
break;
case "yellow":
x = "yellow";
break;
case "orange":
x = "orange";
break;
case "black":
x = "black";
break;
case "white":
x = "white";
break;
}
if (x == "white") y = 14;
else y = 2;
}
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function erase() {
var m = confirm("Want to clear");
if (m) {
ctx.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display = "none";
}
}
function save() {
document.getElementById("canvasimg").style.border = "2px solid";
var dataURL = canvas.toDataURL();
document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").style.display = "inline";
alert("Rightclick and saves as PNG....");
}
function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
draw();
}
}
}
</script>
<body onload="init()";>
<canvas id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;cursor:pointer;"></canvas>
<div style="position:absolute;top:12%;left:40%;">Choose Color</div>
<div style="position:absolute;top:17%;left:45%;width:10px;height:10px;background:green;" id="green" onclick="color(this)"></div>
<div style="position:absolute;top:17%;left:46%;width:10px;height:10px;background:blue;" id="blue" onclick="color(this)"></div>
<div style="position:absolute;top:17%;left:47%;width:10px;height:10px;background:red;" id="red" onclick="color(this)"></div>
<div style="position:absolute;top:19%;left:45%;width:10px;height:10px;background:yellow;" id="yellow" onclick="color(this)"></div>
<div style="position:absolute;top:19%;left:46%;width:10px;height:10px;background:orange;" id="orange" onclick="color(this)"></div>
<div style="position:absolute;top:19%;left:47%;width:10px;height:10px;background:black;" id="black" onclick="color(this)"></div>
<div style="position:absolute;top:22%;left:43%;">Eraser</div>
<div style="position:absolute;top:22%;left:48%;width:15px;height:15px;background:white;border:2px solid;" id="white" onclick="color(this)"></div>
<img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="display:none;">
<input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:88%;left:12%;">
<input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:88%;left:18%;">
</body>
</html>
ENDTEXT
Local m.ldest
m.lcdest=Addbs(Sys(2023))+"temp.html"
Strtofile(m.myvar,m.lcdest)
This.silent=.T.
This.Navigate(m.lcdest)
Endproc
Enddefine
*
*-- EndDefine: ysign
Click on code to select [then copy] -click outside to deselect
![]()
*3* updated on 12 september 2016 * this refers to windows10 inkObjCore.dll to create a com object who is a surface for drawing *maybe its also available on win8 and win8.1 (to confirm) *maybe this dll is an update of lnObj.dll of old version (to confirm). *this code creates a new object using the InkCollector class. *Attach the InkCollector to a form using the form's window handles. *Activate the InkCollector by setting its Enabled property to true (.T.) *Run the following code and start inking! *Note that the object created dont can be embed directly as an activeX on the form (result error if the case). *the result drawing can be saved as gif on the disc when rleasing the form. *it can be used as a quick signature tool. *refrence:https://msdn.microsoft.com/en-us/library/ms965060.aspx *with this article can build many configurations * with this drawing COM object. *this code can be available on any Microsoft Tablet PC Platform SDK Local yform As Form yform = Newobject("ydraw") *-- Create a new InkCollector, and set the *-- window handle to be the form on which Publi oInkCollector As MSINKAUT.inkcollector.1 *-- we want to work with the InkCollector oInkCollector =Newobject("msinkaut.inkcollector.1") oInkCollector.HWnd = yform.HWnd *can use another properties marginX,marginY,... With oInkCollector.defaultDrawingAttributes .Color=255 &&can set any pen color (getcolor()) .Width=150 && set a pen width in activeX scale .penTip=0 &&ball (1=rectangle) .antiAliased=.T. .fitToCurve=.F. Endwith *-- That's it, we're done setting it up. Enable *-- the InkCollector so we can start using it. oInkCollector.Enabled = .T. *set the drawing area object on the form (otherwise all the form surface is the drawing area by default) Local oInkRectangle As MSINKAUT.inkrectangle * Create an inkrectangle object oInkRectangle = Newobject("msinkaut.inkrectangle") * set the drawing area. With oInkRectangle .Top = yform.shape1.Top .Left =yform.shape1.Left .Right =.Left+yform.shape1.Width .Bottom =.Top+yform.shape1.Height Endwith * here we set the rectangle of drawing area oInkCollector.SetWindowInputRectangle(oInkRectangle) *-- InkCollector is turned on, show the form yform.Show(1) &&modal Return *form class Define Class ydraw As Form ShowWindow=0 Desktop=.T. AutoCenter=.T. Caption="Draw in the shape area" Add Object shape1 As Shape With ; width=200,; height=200,; top=20,; left=20,; name="shape1" Procedure Init With Thisform.shape1 .Left=20 .Top=20 .Width=.Parent.Width-2*20 .Height=.Parent.Height-2*20 .BackColor=Rgb(255,255,210) Endwith *Can create buttons to save as image (save(2) method), clear canvas,choose penwidth,pencolor.... *this code below asks to save as gif the drawing(it represents the adjustable area drawn on the form) Procedure QueryUnload lsInk=oInkCollector.Ink.Save(2) &&save as gif file Strtofile(lsInk, Getfile("gif")) Endproc Procedure Destroy oInkCollector=Null Release oInkCollector Endproc Enddefine *Enddefine Yform
Click on code to select [then copy] -click outside to deselect
to test if the com msinkaut objects are installed on your machine or Tablet for the code above, you can insert these codes:
*inkCollector object
Try
oInkEdit = Newobject("msinkaut.inkcollector.1")
Catch
messagebox( "msinkaut.inkcollector.1 control is not installed!",0+32+4096)
Endtry
*inkRectangle object
Try
oInkEdit = Newobject("msinkaut.inkrectangle")
Catch
messagebox( "msinkaut.inkrectangle control is not installed!",0+32+4096)
Endtry
this drawing is saved as any pointed gif on disc when releasing the form.discarding dont save anything.
Important:All Codes above are tested on VFP9SP2 & windows 10 pro and IE. emulation.