I have been trying to make the signature++ sample in the palm knowledge base
work in my palm os 4.1 device and I am having a really hard time with that.
I am not sure what changes will be required and how the bitmap will work for
the newer palm devices. Has anybody had any success with it? Here is the
code from the palm knowledge base. I am working with CW R 6, IDE version
4.0.1. Any help will be highly appreciated.

>From the palm knowledge base:
This sample shows how to capture a signature and convert it into a bitmap.
It also shows how to use a gadget to capture pen input and how to set up the
clipping region to a particular rectangle on the screen. Please note that
this sample code demonstrates a method that should not be used with Palm OS�
release 3.5 or higher. Instead, the Windows API available for Palm OS
release 3.5 or higher should be used in your application. Also, because
there is no API in the Palm OS prior to release 3.5 for converting a screen
rectangle into a bitmap, this sample includes code that is not supported and
will work only on Palm OS 2.x, 3.0, 3.1, and 3.2. This sample creates only a
noncompressed, 1-bit-deep bitmap.Three header files, KeyPrv.h, SysEvtPrv.h,
and SystemPrv.h, are needed to compile the sample code. All three of these
header files are in the Palm OS release 3.0 SDK. The SystemPrv.h header file
is in the Palm OS release 3.1 and Palm VII SDKs included with Metrowerks
CodeWarrior for the Palm OS R6, but not the other two files.
/***********************************************************************
 SAMPLE NAME:  Signature++
 FILE:        Signature.c
 DESCRIPTION:  Implementation file for the signature++ sample
 **********************************************************************/
 #include <Pilot.h>    // all the system toolbox headers
#include <SysEvtMgr.h>   // Needed for search for EvtSysEventAvail
#include <FeatureMgr.h>   // Needed to get the ROM version
#include "SignatureAppRsc.h" // application resource defines

/***********************************************************************
 * Global defines for this module
 **********************************************************************/
#define version20 0x02000000 // Palm OS 2.0 version number
#define version32 0x03200000 // Palm OS 3.2 version number

#define DB_NAME  "BitmapDB:dsSP"
#define DB_TYPE  'DATA'
#define DB_CREATOR 'dsSP'

/***********************************************************************
 * Global variables for this module
 **********************************************************************/
static BitmapPtr gBitmapPtr = NULL; // This will point to our signature
bitmap
static DmOpenRef gBitmapDB = NULL; // This will hold a reference to our DB

/***********************************************************************
 * Prototypes for internal functions
 **********************************************************************/
static Boolean  StartApplication(void);
static void   StopApplication(void);
static VoidPtr  GetObjectPtr(Int objectID);
static FieldPtr  GetFocusObjectPtr(void);
static BitmapPtr  GetSignatureBitmap( RectangleType* theBoundsPtr );
static void   GetSignatureGadgetBounds( RectangleType* theBoundsPtr );
static void   CaptureSignature(void);
static void   MainViewInit(FormPtr theFormPtr);
static Boolean  MainViewHandleEvent(EventPtr event);
static Boolean  ApplicationHandleEvent(EventPtr event);
static void   EventLoop(void);

/***********************************************************************
 *
 * FUNCTION:    RomVersionCompatible
 *
 * DESCRIPTION: Check that the ROM version meets your
 *              minimum and maximum requirement.  Warn if the app was
 *    switched to.
 *
 * PARAMETERS:  minVersion   - minimum rom version required
 *                                (see sysFtrNumROMVersion in SystemMgr.h
 *                                for format)
 *    maxVersion  - maximum rom version required
 *              launchFlags     - flags indicating how the application was
 *            launched.  A warning is displayed only if
 *                                these flags indicate that the app is
 *            launched normally.
 *
 * RETURNED:    zero if rom is compatible else an error code
 *
 ***********************************************************************/
static Err RomVersionCompatible(DWord minVersion, DWord maxVersion, Word
launchFlags)
{
 DWord  romVersion;
 SWord theShortVersion;

 // See if we're on a version of the ROM that we can run safely on.
 // The system records the version number in a feature.  A feature is a
 // piece of information which can be looked up by a creator and feature
 // number.
 FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
 theShortVersion = romVersion >> 16;

 if ( (theShortVersion < (minVersion >> 16)) ||
   (theShortVersion > (maxVersion >> 16)) )
 {
  // If the user launched the app from the launcher, explain
  // why the app shouldn't run.  If the app was contacted for something
  // else, like it was asked to find a string by the system find, then
  // don't bother the user with a warning dialog.  These flags tell how
  // the app was launched to decided if a warning should be displayed.
  if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
==
   (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
   {
   FrmAlert (RomIncompatibleAlert);

   // Pilot 1.0 will continuously relaunch this app unless we switch to
   // another safe one.  The sysFileCDefaultApp is considered "safe".
   if (romVersion < 0x02000000)
    AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch,
NULL);
   }

  return (sysErrRomIncompatible);
 }

 return 0;
}

/***********************************************************************
 *
 * FUNCTION:    GetObjectPtr
 *
 * DESCRIPTION: P10. This routine returns a pointer to an object in the
active form.
 *
 * PARAMETERS:  objectID - id of the object
 *
 * RETURNED:    pointer to the object's data structure
 *
 ***********************************************************************/
static VoidPtr GetObjectPtr(Int objectID)
{
 FormPtr frm;

 frm = FrmGetActiveForm();
 return(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, objectID)));
}

/***********************************************************************
 *
 * FUNCTION:    GetFocusObjectPtr
 *
 * DESCRIPTION: This routine returns a pointer to the field object, in
 *              the current form, that has the focus.
 *
 * PARAMETERS:  nothing
 *
 * RETURNED:    pointer to a field object or NULL of there is no focus
 *
 ***********************************************************************/
static FieldPtr GetFocusObjectPtr(void)
{
 FormPtr frm;
 Int focus;

 // Get a pointer to tha active form and the index of the form object with
focus.
 frm = FrmGetActiveForm();
 focus = FrmGetFocus(frm);

 // If no object has the focus return NULL pointer.
 if (focus == noFocus)
  return(NULL);

 // Return a pointer to the object with focus.
 return(FrmGetObjectPtr(frm, focus));
}

/***********************************************************************
/   MAJOR CHANGES FROM THE STARTER PROJECT TEMPLATE BEGIN HERE
/***********************************************************************

/***********************************************************************
 *
 * FUNCTION:     StartApplication
 *
 * DESCRIPTION:  This routine sets up the initial state of the application.
 *               It opens the application's database and sets up global
variables.
 *
 * PARAMETERS:   None.
 *
 * RETURNED:     true if error (database couldn't be created)
 *
 ***********************************************************************/
static Boolean StartApplication(void)
{
    Err   theError;
    UInt  theIndex = 0;
    VoidHand theRecHandle;
    VoidPtr  theRecPtr;
    ULong  theSize;

    // Check and see if our application's database exists.  If not, then
    // create it.  This database will be used to store the bitmap.
 gBitmapDB = DmOpenDatabaseByTypeCreator(DB_TYPE, DB_CREATOR,
dmModeReadWrite);
 if (!gBitmapDB)
 {
  // Create the database
  theError = DmCreateDatabase(0, DB_NAME, DB_CREATOR, DB_TYPE, false);
  if (theError) return theError;

  // Then open it
  gBitmapDB = DmOpenDatabaseByTypeCreator(DB_TYPE, DB_CREATOR,
dmModeReadWrite);
  if (!gBitmapDB) return (1);
 }
 else
 {
  // Try to find an existing bitmap.  If one exists, then use that
  // as the default bitmap;
  if (DmNumRecords( gBitmapDB ) > 0)
  {
   // Grab out database record and lock it down if it exists
   theRecHandle = DmGetRecord( gBitmapDB, theIndex );
   if (theRecHandle)
   {
    theRecPtr = MemHandleLock( theRecHandle );

    // Copy the data from the record into the bitmap pointer global
    theSize = MemPtrSize(theRecPtr);
    gBitmapPtr = MemPtrNew( theSize );
    MemMove( gBitmapPtr, theRecPtr, theSize );

    // Finally, unlock the record handle
    MemHandleUnlock( theRecHandle );
   }
  }
 }

 return false;
}

/***********************************************************************
 *
 * FUNCTION:    StopApplication
 *
 * DESCRIPTION: This routine closes the application's database
 *              and saves the current state of the application.
 *
 * PARAMETERS:  nothing
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void StopApplication(void)
{
 UInt  theIndex = 0;
 VoidHand theRecHandle;
 VoidPtr  theRecPtr;
 ULong  theSize;

 // Save out the bitmap to the application database

 // First remove any existing record
 if (DmNumRecords( gBitmapDB ) > 0)
  DmRemoveRecord( gBitmapDB, theIndex );

 if (gBitmapPtr)
 {
  // Create a record from our bitmap
  theSize = MemPtrSize( gBitmapPtr );
  theRecHandle = DmNewHandle( gBitmapDB, theSize );
  if (!theRecHandle)
   return;

  // Copy the bitmap data into the new record
  theRecPtr = MemHandleLock( theRecHandle );
  DmWrite( theRecPtr, 0, gBitmapPtr, theSize );
  MemHandleUnlock( theRecHandle );

  // Now, attach the new record to the database
  DmAttachRecord( gBitmapDB, &theIndex, theRecHandle, NULL );
 }

 // Close the application's database
 DmCloseDatabase( gBitmapDB );
}

/***********************************************************************
 *
 * FUNCTION:     GetSignatureBitmap
 *
 * DESCRIPTION:  This routine converts the screen drawing into a bitmap
 *     WARNING:  THIS CODE IS NOT SUPPORTED CODE AND MAY NOT WORK
 *     ON DEVICES WHOSE OS VERSION IS OTHER THAN 2.X, 3.0,
 *     3.1, OR 3.2.
 *
 * PARAMETERS:   theBoundsPtr - the bounds of the gadget
 *
 * RETURNED:     A pointer to the bitmap
 *
 ***********************************************************************/
static BitmapPtr GetSignatureBitmap( RectangleType* theBoundsPtr )
{
 WinHandle theWindowHandle;
 Word  theError;
 BitmapPtr theBitmapPtr = NULL;
 Word  theRowBytes, theHeight;

 // First, free the previous bitmap if it exists
 if (gBitmapPtr)
 {
  MemPtrFree( gBitmapPtr );
  gBitmapPtr = NULL;
 }

 // Create an offscreen window to copy the bits bounded by the gadget into.
 // This will make converting the window into a bitmap a little easier for
us
 // You could just copy the screen bits directly into the bitmap, but that
 // would require more pointer arithmetic and POSE complains when you read
 // directly from the screen.
 theWindowHandle = WinCreateOffscreenWindow( theBoundsPtr->extent.x,
       theBoundsPtr->extent.y, screenFormat, &theError );

 if (!theError)
 {
  // Now, copy the gadgets screen rectangle into the new window.  This will
offset
  // the screen bits to (0, 0) in the offscreen window.
  WinCopyRectangle( NULL, theWindowHandle, theBoundsPtr, 0, 0, scrCopy );

  // Now, this is the tricky part.  There is no API for getting the bits on
the screen
  // into a bitmap, so this code is unsupported and will only work on Palm
OS 2.x, 3.0,
  // 3.1, and 3.2 devices.  This is why we limit this sample to only those
versions in
  // the RomVersionCompatible function.  This code will also only work on a
device with
  // a screen depth of 1.
  // WARNING:  THIS CODE IS NOT SUPPORTED CODE AND MAY NOT WORK ON DEVICES
  // WHOSE OS VERSION IS OTHER THAN 2.X, 3.0, 3.1, OR 3.2

  // Cache a couple of important bits of information
  theRowBytes = theWindowHandle->gDeviceP->rowBytes;
  theHeight = theWindowHandle->gDeviceP->height;

  // Now, allocate our bitmap and set all the important bits of information.
  theBitmapPtr = MemPtrNew( sizeof(BitmapType) + (theRowBytes*theHeight) );
  if (theBitmapPtr)
  {
   MemSet( theBitmapPtr, sizeof(BitmapType) + (theRowBytes*theHeight), 0 );

   theBitmapPtr->width = theWindowHandle->gDeviceP->width;
   theBitmapPtr->height = theWindowHandle->gDeviceP->height;
   theBitmapPtr->rowBytes = theWindowHandle->gDeviceP->rowBytes;
   theBitmapPtr->pixelSize = theWindowHandle->gDeviceP->pixelSize;
   theBitmapPtr->nextDepthOffset = NULL;

   // CreateOffscreenWindow does not, by default, create a compressed window
   theBitmapPtr->flags.compressed = theWindowHandle->gDeviceP->compressed;

   // All bitmaps are version 1 bitmaps without a color table.
   theBitmapPtr->version = 1;
   theBitmapPtr->flags.hasColorTable = 0;

   // Move the offscreen bits into our bitmap.  The baseAddr field
   // contains the bit array of our bitmap for 1-bit, uncompressed bitmaps.
   MemMove( (Ptr)((ULong)(theBitmapPtr) + sizeof(BitmapType)),
      theWindowHandle->gDeviceP->baseAddr, theRowBytes * theHeight );
  }

  // Delete the window that we created with WinCreateOffscreenWindow
  WinDeleteWindow( theWindowHandle, false );
 }

 // Finally, return our bitmap
 return theBitmapPtr;
}

/***********************************************************************
 *
 * FUNCTION:     GetSignatureGadgetBounds
 *
 * DESCRIPTION:  This routine grabs the bounds of the signature gadget
 *
 * PARAMETERS:   theBoundsPtr - the bounds of the gadget
 *
 * RETURNED:     nothing
 *
 ***********************************************************************/
static void GetSignatureGadgetBounds( RectangleType* theBoundsPtr )
{
 FormPtr   theFormPtr;
 FormGadgetType* theGadgetPtr;

 theFormPtr = FrmGetActiveForm();
 theGadgetPtr = GetObjectPtr( MainSignatureGadget );

 FrmGetObjectBounds( theFormPtr,
   FrmGetObjectIndex(theFormPtr, MainSignatureGadget), theBoundsPtr );
}

/***********************************************************************
 *
 * FUNCTION:     CaptureSignature
 *
 * DESCRIPTION:  This routine captures the signature and converts it
 *      into a bitmap
 *
 * PARAMETERS:   None
 *
 * RETURNED:     nothing
 *
 ***********************************************************************/
static void CaptureSignature()
{
 SWord    x, y, prevX, prevY;
 Boolean    penDown;
 RectangleType  theClipRectangle;
 RectangleType  theGadgetBounds;

 // Grab the gadget's bounds
 GetSignatureGadgetBounds( &theGadgetBounds );

 // Grab the coordinates of the pen
 EvtGetPen( &prevX, &prevY, &penDown );

 // Save off the current clip rectangle and set the new clipping
 // rectangle to be the bounds of the signature gadget.
 WinGetClip( &theClipRectangle );
 WinSetClip( &theGadgetBounds );

 // Track the pen
 do
 {
  EvtGetPen(&x, &y, &penDown);

  // Don't bother to do anything if the user hasn't moved
  // the pen!
  if ((x != prevX || y != prevY))
  {
   WinDrawLine( prevX, prevY, x, y );

   prevX = x;
   prevY = y;
  }
 } while (penDown);

 // Turn the drawing into a bitmap and save the bitmap in a global
 gBitmapPtr = GetSignatureBitmap( &theGadgetBounds );

 // Restore the old clipping rectangle
 WinSetClip( &theClipRectangle );
}

/***********************************************************************
 *
 * FUNCTION:  MainViewInit
 *
 * DESCRIPTION: Initializes for the "main" form.
 *
 * PARAMETERS:  theFormPtr - a pointer to the form
 *
 * RETURNED:  nothing
 *
 ***********************************************************************/
static void MainViewInit( FormPtr theFormPtr )
{
 RectangleType theBounds;

 GetSignatureGadgetBounds( &theBounds );

 // Draw a frame around our gadget so that users know where to sign
 WinDrawRectangleFrame( simpleFrame, &theBounds );

 // Draw the signature bitmap if it exists (it would have been setup
 // by StartApplication)
 if (gBitmapPtr)
  WinDrawBitmap( gBitmapPtr, theBounds.topLeft.x, theBounds.topLeft.y );

}

/***********************************************************************
 *
 * FUNCTION:  MainViewHandleEvent
 *
 * DESCRIPTION: Handles processing of events for the "main" form.
 *
 * PARAMETERS:  event - the most recent event.
 *
 * RETURNED:  True if the event is handled, false otherwise.
 *
 ***********************************************************************/
static Boolean MainViewHandleEvent(EventPtr event)
{
 Boolean   handled = false;
 FormPtr   theFormPtr;
 SWord    x, y;
 Boolean   penDown;
 RectangleType theGadgetBounds;

 switch (event->eType)
  {
   // A frmUpdateEvent will only come through if we explicitly call
FrmUpdateForm,
   // or if a dialog was opened over our form and there wasn't enough memory
to save
   // the bits behind the dialog.
   case frmUpdateEvent:
    theFormPtr = FrmGetActiveForm();

    // If a bitmap ptr exists, then draw it.
    if (gBitmapPtr)
    {
     // Grab the gadget's bounds
     GetSignatureGadgetBounds( &theGadgetBounds );

     // Draw the signature bitmap
     WinDrawBitmap( gBitmapPtr, theGadgetBounds.topLeft.x,
theGadgetBounds.topLeft.y );
    }

    // Note that we don't set handled to true.  This is so the OS will
    // tell the rest of the form to redraw itself.

    break;

   case ctlSelectEvent:
    if (event->data.ctlSelect.controlID == MainClearButton)
    {
     // Grab the gadget's bounds
     GetSignatureGadgetBounds( &theGadgetBounds );

     // Erase the rectangle
     WinEraseRectangle( &theGadgetBounds, 0 );

     // Free the memory held by the bitmap
     if (gBitmapPtr)
     {
      MemPtrFree( gBitmapPtr );
      gBitmapPtr = NULL;
     }
    }

    break;

   case penDownEvent:
    // Grab the bounds for the signature gadget
    GetSignatureGadgetBounds( &theGadgetBounds );

    // Grab the location of the pen down event
    EvtGetPen( &x, &y, &penDown );

    // Capture the signature if the point was within the signature
    // gadget's bounds
    if (RctPtInRectangle( x, y, &theGadgetBounds) )
    {
     CaptureSignature();
     handled = true;
    }

    break;

     case frmOpenEvent:
    theFormPtr = FrmGetActiveForm();

    // Initialize the main view
    MainViewInit(theFormPtr);

    // Draw the form.
    FrmDrawForm( theFormPtr );

    handled = true;
    break;
   case menuEvent:
    if (event->data.menu.itemID == OptionsAboutSignature)
    {
     MenuEraseStatus( 0 );
     AbtShowAbout( DB_CREATOR );
     handled = true;
    }
    break;

  }

 return(handled);
}

/***********************************************************************
/   MAJOR CHANGES FROM THE STARTER PROJECT TEMPLATE END HERE
/***********************************************************************

/***********************************************************************
 *
 * FUNCTION:     ApplicationHandleEvent
 *
 * DESCRIPTION: This routine loads a form resource and sets the event
handler for the form.
 *
 * PARAMETERS:   event - a pointer to an EventType structure
 *
 * RETURNED:     True if the event has been handled and should not be
 *      passed to a higher level handler.
 *
 ***********************************************************************/
static Boolean ApplicationHandleEvent(EventPtr event)
{
 FormPtr frm;
 Int  formId;
 Boolean handled = false;

 if (event->eType == frmLoadEvent)
  {
  // Load the form resource specified in the event then activate the form.
  formId = event->data.frmLoad.formID;
  frm = FrmInitForm(formId);
  FrmSetActiveForm(frm);

  // Set the event handler for the form.  The handler of the currently
  // active form is called by FrmDispatchEvent each time it receives an
event.
  switch (formId)
   {
   case MainForm:
    FrmSetEventHandler(frm, MainViewHandleEvent);
    break;
   }
  handled = true;
  }

 return handled;
}


/***********************************************************************
 *
 * FUNCTION:  EventLoop
 *
 * DESCRIPTION:  A simple loop that obtains events from the Event
 *     Manager and passes them on to various applications and
 *     system event handlers before passing them on to
 *     FrmDispatchEvent for default processing.
 *
 * PARAMETERS:  None.
 *
 * RETURNED:  Nothing.
 *
 ***********************************************************************/
static void EventLoop(void)
{
 EventType event;
 Word   error;

 do
  {
  // Get the next available event.
  EvtGetEvent(&event, evtWaitForever);

  // Give the system a chance to handle the event.
  if (! SysHandleEvent(&event))

   // Give the menu bar a chance to update and handle the event.
   if (! MenuHandleEvent(0, &event, &error))

    // Give the application a chance to handle the event.
    if (! ApplicationHandleEvent(&event))

     // Let the form object provide default handling of the event.
     FrmDispatchEvent(&event);
  }
 while (event.eType != appStopEvent);
}


/***********************************************************************
 *
 * FUNCTION:  PilotMain
 *
 * DESCRIPTION:  This function is the equivalent of a main() function
 *      under standard "C".  It is called by the Emulator to begin
 *      execution of this application.
 *
 * PARAMETERS:  cmd - command specifying how to launch the application.
 *      cmdPBP - parameter block for the command.
 *      launchFlags - flags used to configure the launch.
 *
 * RETURNED:  Any applicable error codes.
 *
 ***********************************************************************/
DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
{
 Word error;  // Error starting the app

 // This app makes use of PalmOS 2.0 features.  It will crash if
 // run on an earlier version of PalmOS.  Detect and warn if this happens,
 // then exit.
 error = RomVersionCompatible (version20, version32, launchFlags);
 if (error)
  return error;

 // Check for a normal launch.
 if (cmd == sysAppLaunchCmdNormalLaunch)
  {
  // Initialize the application's global variables and database.
  if (!StartApplication())
   {
    // Start the first form.
    FrmGotoForm(MainForm);

    // Start the event loop.
    EventLoop();

    // Clean up before exiting the applcation.
    StopApplication();
   }
  }

 return 0;
}



-- 
For information on using the Palm Developer Forums, or to unsubscribe, please 
see http://www.palmos.com/dev/support/forums/

Reply via email to