Page 1 of 3
Signatures
Posted: Fri Dec 22, 2006 3:07 pm
by Randal
All,
Has anyone been able to capture a signature and save it as a graphic image?
Thanks,
Randal Ferguson
Posted: Fri Dec 22, 2006 5:20 pm
by Antonio Linares
Randal,
Class TWindow already provides a METHOD SaveToBmp( cBmpFile ) to save any window, dialog or control image as a BMP file.
All is needed is a sample that uses bLClicked, bMMoved and bLButtonUp DATAs to SetPixel( oWnd:hDC, nRow, nCol, nRGB( 255, 255, 255 ) ) and paint the pixels signature as pressed and later on save it to disk.
Posted: Fri Dec 22, 2006 9:27 pm
by Bill Simmeth
I've had better luck using the LineTo function. Using SetPixel made the signature look very "dotted". Something like this sample works very nicely...
Code: Select all
#include "FWCE.ch"
#include "DLL.ch"
function Main()
local oWnd, oSay, nHdc
PUBLIC nOldX := -1, nOldY := -1
DEFINE WINDOW oWnd TITLE "Draw"
@ 5,5 SAY oSay PROMPT "?" COLOR "N+/W*" PIXEL SIZE 60,15
@30,5 BUTTON "Clear" SIZE 50,20 PIXEL ACTION oWnd:refresh(.t.)
nHdc := GetDC(oWnd:hWnd)
oWnd:bLButtonUp := { |x,y,z| oSay:setText( "Up" ), DoDraw( nHdc, y, x ), nOldX := -1, nOldY := -1 }
oWnd:bMMoved := { |x,y,z| DoDraw( nHdc, y, x ) }
oWnd:activate( {|x,y,z| oSay:setText( "Down" ), DoDraw( nHdc, y, x ) } )
return nil
Function DoDraw( hDc, x, y )
If nOldX == -1 .And. nOldY == -1
nOldX := x
nOldY := y
MoveToEx( hDc, x, y )
Else
LineTo( hDc,x,y )
EndIf
RETURN Nil
DLL FUNCTION MoveToEx( nHdc AS HDC, nX AS _INT, nY AS _INT, NULL AS _INT ) AS BOOL PASCAL LIB "coredll.dll"
Merry Christmas y'all!
Posted: Fri Dec 22, 2006 10:05 pm
by Antonio Linares
Bill,
Excellent! It works very nicely!
We are going to include it in the FWPPC samples if you don't mind it, thanks!
Posted: Sat Dec 23, 2006 6:43 am
by Richard Chidiak
Antonio Linares wrote:Bill,
Excellent! It works very nicely!
We are going to include it in the FWPPC samples if you don't mind it, thanks!
Antonio
Indeed it is excellent.
How would you save only the signature to bmp without the clear button and ?
Ownd:savetobmp() will save the entire window
Richard
Posted: Sat Dec 23, 2006 8:14 am
by Antonio Linares
Richard,
We propose some modifications for the sample:
* To remove the pushbutton and the "?"
* To use a pulldown menu for Save and Cancel, this way the entire window client surface may be saved to a file.
* hDC needs to be released or it will consume GDI resources.
* Class TWindow Method SaveToBmp() may need a parameter to specify just the client area, without the caption and the menu.
Posted: Sat Dec 23, 2006 10:39 am
by Antonio Linares
This sample is based on Bill's one. Its working fine though we have not been able to remove the pulldown menu yet:
Code: Select all
#include "FWCE.ch"
static oWnd
function Main()
local hDC, lPaint := .f.
DEFINE WINDOW oWnd TITLE "Please sign" ;
MENU BuildMenu()
hDC = oWnd:GetDC()
oWnd:bLButtonUp = { | nRow, nCol | LineTo( hDC, nCol, nRow ), lPaint := .f. }
oWnd:bMMoved = { | nRow, nCol | If( lPaint, LineTo( hDC, nCol, nRow ),) }
ACTIVATE WINDOW oWnd ;
ON CLICK ( lPaint := .t., MoveTo( hDC, nCol, nRow ) ) ;
VALID ( oWnd:ReleaseDC(), .t. )
return nil
function BuildMenu()
local oMenu
DEFINE MENU oMenu RESOURCE 102 ;
BITMAPS 10 ; // bitmap resources ID
IMAGES 2 // number of images in the bitmap
REDEFINE MENUITEM ID 110 OF oMenu ;
ACTION ( oWnd:SaveToBmp( CurDir() + "\sign.bmp" ), oWnd:End() )
REDEFINE MENUITEM ID 120 OF oMenu ACTION oWnd:End()
return oMenu
It uses this RC:
Code: Select all
#ifdef _CE
#include "c:\vce\include\arm\windows.h"
#include "c:\vce\include\arm\commctrl.h"
#endif
#define I_IMAGENONE (-2)
#define IDS_HELP 104
#ifdef _CE
102 RCDATA
BEGIN
102, 3,
0, 110, TBSTATE_ENABLED, TBSTYLE_BUTTON, 201, 0, 0,
0, 105, TBSTATE_ENABLED, TBSTYLE_SEP, -1, 0, 0,
1, 120, TBSTATE_ENABLED, TBSTYLE_BUTTON, 202, 0, 0
END
#endif
STRINGTABLE DISCARDABLE
BEGIN
201 "Save"
202 "Cancel"
END
102 MENU DISCARDABLE
BEGIN
MENUITEM "", 110
MENUITEM "", 120
END
10 BITMAP "../bitmaps/pocket/okcancel.bmp"
Posted: Sat Dec 23, 2006 2:40 pm
by Richard Chidiak
Antonio
I did other tests based on Bill's sample and was thinking of buttons instead of menus. The problem is to be able to hide the buttons when saving the image. I am not yet there.
Here is my sample.
#include "C:\FWPPC\INCLUDE\FWCE.ch"
#include "C:\FWPPC\INCLUDE\DLL.ch"
function Main()
local oWnd, oSay, nHdc
PUBLIC nOldX := -1, nOldY := -1
HIDEKEYBOARD()
DEFINE WINDOW oWnd TITLE "Draw"
@ 5,5 SAY oSay PROMPT " " COLOR "N+/W*" PIXEL SIZE 15,15
@ 5,30 BUTTON obtn1 prompt "Clear" SIZE 50,20 PIXEL ACTION oWnd:refresh(.t.)
@ 5,100 BUTTON obtn2 prompt "Save" SIZE 80,20 PIXEL ACTION (OBTN1:HIDE(),OBTN2:HIDE(),OWND:SAVETOBMP(CurDir() + "\TESTppc.BMP"))
nHdc := GetDC(oWnd:hWnd)
oWnd:bLButtonUp := { |x,y,z| oSay:setText( " " ), DoDraw( nHdc, y, x ), nOldX := -1, nOldY := -1 }
oWnd:bMMoved := { |x,y,z| DoDraw( nHdc, y, x ) }
oWnd:activate( {|x,y,z| oSay:setText( " " ), DoDraw( nHdc, y, x ) } )
SHOWKEYBOARD()
return nil
Function DoDraw( hDc, x, y )
If nOldX == -1 .And. nOldY == -1
nOldX := x
nOldY := y
MoveToEx( hDc, x, y )
Else
LineTo( hDc,x,y )
EndIf
RETURN Nil
DLL FUNCTION MoveToEx( nHdc AS HDC, nX AS _INT, nY AS _INT, NULL AS _INT ) AS BOOL PASCAL LIB "coredll.dll"
Posted: Sat Dec 23, 2006 3:20 pm
by Maurizio
I use this for sending messages from the Pocket PC to the kitchen.
I save the position in an array , after I save the array in a file and I send
the file to the PC server where I then transform the file in an array and I print the message .
Code: Select all
#include "FWCE.ch"
static oWnd, lDown, hDC ,cFile,nOldRow,nOldCol
Static aDati := {}
//====================================================================================
Function Main()
lDown := .F.
nOldRow := 0
nOldCol := 0
DEFINE WINDOW oWnd TITLE "Signature"
oWnd:bLClicked := { || lDown := .T. }
oWnd:bLButtonUp := { || lDown := .F. ,nOldRow := 0 , nOldCOl := 0 }
oWnd:bMMoved := { |nRow, nCol, nKeyFlags| Draw(nCol,nRow)}
hDC := oWnd:GetDC()
@ 1, 1 BUTTON oBtn1 PROMPT "Refresh" ;
ACTION (oWnd:Refresh(),aDAti := {}) SIZE 80, 20
@ 3, 1 BUTTON oBtn1 PROMPT "S a v e" ;
ACTION Save() SIZE 80, 20
ACTIVATE WINDOW oWnd
return 0
//====================================================================================
STATIC FUNCTION Draw(nRow,nCol)
IF lDown
* SetPixel(hDC, nRow, nCol, RGB(0,0,0) )
IF nOldRow > 0
DrawLine(nRow,nCol)
aadd(aDAti,{nRow,nCol})
ELSE
// We will need to know when a line starts and finishes
aadd(aDAti,{nRow+1000,nCol+1000})
ENDIF
nOldRow := nRow
nOldCol := nCol
ENDIF
RETURN NIL
//=================================================
Static Procedure DrawLine( nRow,nCol )
LOCAL n, hPen, hOldPen
oWnd:GetDc()
hPen := CreatePen( 0, 1, RGB(0,0,0) )
hOldPen := SelectObject( oWnd:hDc, hPen )
MoveTo( oWnd:hDC,nOldRow,nOldCol )
LineTo( oWnd:hDC, nRow, nCol )
SelectObject( oWnd:hDc, hOldPen )
DeleteObject( hPen )
oWnd:ReleaseDc()
RETURN
//=================================================
Function Save()
Local nX := 0
Local cTxt := aSave(aDAti)
MemoWrit( CurDir() + "\Prova.txt", cTxt )
RETURN NIL
//-------------------------------------------------------------------------------------------
#pragma BEGINDUMP
#include "windows.h"
#include "hbapi.h"
#include "item.api"
HB_FUNC( SETPIXEL )
{
hb_retnl( SetPixel( ( HDC ) hb_parnl( 1 ), hb_parni( 2 ), hb_parni( 3 ), hb_parnl( 4 ) ) );
}
#pragma ENDDUMP
function ASave( aArray )
local n, cType, uData
local cInfo := ""
for n = 1 to Len( aArray )
cType = ValType( aArray[ n ] )
do case
case cType == "A"
cInfo += ASave( aArray[ n ] )
case cType == "O"
cInfo += aArray[ n ]:Save()
otherwise
cInfo += ( cType + I2Bin( Len( uData := cValToChar( aArray[ n ] ) ) ) + ;
uData )
endcase
next
return "A" + I2Bin( 2 + Len( cInfo ) ) + I2Bin( Len( aArray ) ) + cInfo
//----------------------------------------------------------------------------//
Posted: Sat Dec 23, 2006 5:05 pm
by Antonio Linares
Maurizio,
Yes, thats a very good idea too, to save the signature as an array of points (nCol, nRow) like a vectorial draw.
Posted: Sat Dec 23, 2006 5:07 pm
by Antonio Linares
Richard,
The buttons should dissapear, don't they ?
Posted: Sat Dec 23, 2006 5:15 pm
by Richard Chidiak
They are supposed to but they don't. This is the poblem.
Posted: Sat Dec 23, 2006 5:17 pm
by Antonio Linares
Richard,
Yes, the same happened with the pulldown menu. I guess it is caused as there is an existing hDC in use.
Maybe you may try to call oWnd:ReleaseDC() before hidding the buttons.
If you use Bill's code, then call ReleaseDC( oWnd:hWnd, oWnd:hDC )
Posted: Sat Dec 23, 2006 5:30 pm
by Richard Chidiak
Antonio
No change, same result. We need to update the window before saving it
I keep searching
Posted: Sun Dec 24, 2006 2:03 am
by Bill Simmeth
This sample uses a SAY object to collect the signature and its DC is saved to the bitmap file. It works nicely...
Code: Select all
#include "FWCE.ch"
#include "DLL.ch"
function Main()
local oMain, oSig, nHdc
local cDir := CurDir()
PUBLIC nOldX := -1, nOldY := -1
DEFINE WINDOW oMain TITLE "Draw"
@60,5 SAY oSig PROMPT "" SIZE 230,150 PIXEL BORDER
@25, 5 BUTTON "Clear" SIZE 50,20 PIXEL ACTION oSig:refresh(.t.)
@25,60 BUTTON "Save" SIZE 50,20 PIXEL ACTION ( oSig:saveToBmp( cDir + "\MySig.BMP" ), oSig:refresh(.t.) )
nHdc := GetDC( oSig:hWnd )
oSig:bLButtonUp := { |x,y,z| DoDraw( nHdc, y+1, x+1 ), nOldX := -1, nOldY := -1 }
oSig:bMMoved := { |x,y,z| DoDraw( nHdc, y, x ) }
oSig:bLClicked := { |x,y,z| DoDraw( nHdc, y, x ) }
ACTIVATE WINDOW oMain
return nil
Function DoDraw( hDc, x, y )
If nOldX == -1 .And. nOldY == -1
nOldX := x
nOldY := y
MoveToEx( hDc, x, y )
Else
LineTo( hDc,x,y )
EndIf
RETURN Nil
DLL FUNCTION MoveToEx( hWnd AS HDC, nX AS _INT, nY AS _INT, NULL AS _INT ) AS BOOL PASCAL LIB "coredll.dll"
Merry Christmas!!