Page 1 of 3

Signatures

PostPosted: 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

PostPosted: 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.

PostPosted: 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  Expand view
#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!

PostPosted: 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!

PostPosted: 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

PostPosted: 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.

PostPosted: 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  Expand view
#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  Expand view
#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"

Image

PostPosted: 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"

PostPosted: 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  Expand view

#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

//----------------------------------------------------------------------------//

















PostPosted: 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.

PostPosted: Sat Dec 23, 2006 5:07 pm
by Antonio Linares
Richard,

The buttons should dissapear, don't they ?

PostPosted: Sat Dec 23, 2006 5:15 pm
by Richard Chidiak
They are supposed to but they don't. This is the poblem.

PostPosted: 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 )

PostPosted: 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

PostPosted: 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  Expand view
#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!!