Print

Structure of a Palm Application, Part 2
Pages: 1, 2

The EventType data structure

In order to handle events within your form's event handler, you have to become familiar with the EventType data structure (the data that comes back from EvtGetEvent). Here are the fields within that structure:



eType
The type of the event (an enumeration: examples are menuEvent, penDownEvent, keyDownEvent, and so on).
penDown
Was the stylus down when this event occurred?
tapCount
For OS 3.5 and later, the number of successive taps. On a double-tap, you'll get two events. The first will have a tapCount of 1, and the second a tapCount of 2. Note: the value in this field is undefined prior to the 3.5 version of the OS.
screenX
The horizontal location of the stylus (in screen coordinates).
screenY
The vertical location of the stylus (in screen coordinates).

Each event type also has specific associated data. For example, menu events have the menu item ID, control events have the control ID, key events have the character. This data is stored in a union of structures, with a separate structure defined for each kind of event. The union of structures' name is data. Within that union, the name of the structure is the name of the event type, without the event suffix. For example, the data for a menuEvent is found in the data.menu structure, the data for a ctlSelectEvent is found in data.ctlSelect.

Example 5-7 shows SecondForm.c, which contains the code responsible for the second form.

Example 5-7: SecondForm.c

/*
 Copyright (c) 2000-2001, Neil Rhodes and Julie McKeehan
   neil@pobox.com
 All rights reserved.
 
From the book "Palm OS Programming (2nd edition)" by O'Reilly.
 
Permission granted to use this file however you see fit.
*/
 
#define DO_NOT_ALLOW_ACCESS_TO_INTERNALS_OF_STRUCTS
#include <BuildDefines.h>
#ifdef DEBUG_BUILD
#define ERROR_CHECK_LEVEL ERROR_CHECK_FULL
#endif
#include <PalmOS.h>
#include "ResourceDefines.h"
#include "SecondForm.h"
 
 
static void SecondFormInit(FormPtr form)
{
#pragma unused(form)
  // Warning-- don't do any drawing in this routine.
  // Also, don't call FrmSetFocus from here (it must be called *after*
  // FrmDrawForm).
}
 
static void SecondFormDeinit(FormPtr form)
{
#pragma unused(form)
}
 
 
Boolean SecondFormHandleEvent(EventPtr event)
{
  Boolean handled = false;
  FormPtr form;
 
 
  switch (event->eType) {
  case frmOpenEvent:
    form = FrmGetActiveForm(  );
    SecondFormInit(form);
    FrmDrawForm(form);
    // Here's where you'd add a call to FrmSetFocus.
    handled = true;
    break;
      
      
  case ctlSelectEvent:
    switch (event->data.ctlSelect.controlID) {
    case SecondGotoMainFormButton:
      FrmGotoForm(MainForm);
      handled = true;
      break;
    }
    break;
 
  case frmCloseEvent:
    SecondFormDeinit(FrmGetActiveForm(  ));
    handled = false;
    break;
 
  default:
    break;
  }
  
  return handled;
}

This code is very similar in structure to that of MainForm.c. The difference is what happens when a control is chosen.

The Utility and Resource Files

Here is a look at the utility and resource files that OReilly Starter uses.

Utils.c contains several utility routines in this source file, but we use only one in this application. Example 5-8 shows that sole routine.

Example 5-8: Utils.c (abridged to show only the routine we use)

/*
 Copyright (c) 2000-2001, Neil Rhodes and Julie McKeehan
    neil@pobox.com
 All rights reserved.
 
From the book "Palm OS Programming (2nd edition)" by O'Reilly.
 
Permission granted to use this file however you see fit.
*/
 
#define DO_NOT_ALLOW_ACCESS_TO_INTERNALS_OF_STRUCTS
#include <BuildDefines.h>
#ifdef DEBUG_BUILD
#define ERROR_CHECK_LEVEL ERROR_CHECK_FULL
#endif
#include <PalmOS.h>
#include "Utils.h"
#include "ResourceDefines.h"
 
Err RomVersionCompatible(UInt32 requiredVersion, UInt16 launchFlags)
{
  UInt32 romVersion;
 
  // See if we're on minimum required version of the ROM or later.
  FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
  if (romVersion < requiredVersion) {
    UInt16 safeToCallAlertFlags;
    
    safeToCallAlertFlags = 
      sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp;
    if ((launchFlags & (safeToCallAlertFlags)) == safeToCallAlertFlags) {
      FrmAlert (RomIncompatibleAlert);
    
      // Pilot 1.0 will continuously relaunch this application 
      //unless we switch to another safe one.
      if (romVersion < sysMakeROMVersion(2,0,0,sysROMStageRelease,0))
        AppLaunchWithCommand(sysFileCDefaultApp, 
          sysAppLaunchCmdNormalLaunch, NULL);
    }
    
    return (sysErrRomIncompatible);
  }
 
  return errNone;
}

You'll normally use this routine as-is in every application you write. It works by calling the Feature Manager (which contains runtime information about the Palm device) to find out what ROM version this Palm device is running. If the version is not earlier than the requested one, the routine returns no error. Otherwise, it will display an alert and return an error. Last of all, it deals with a potentially infinite relaunch problem in the 1.0 version of the OS by explicitly launching some other application.

The Resources.rcp PilRC file, shown in Example 5-9, can be compiled by either the PilRC command line, when using the PRC-Tools, or by the PilRC plug in, when using the CodeWarrior environment.

Example 5-9: Resources.rcp

#include "ResourceDefines.h"
 
APPLICATIONICONNAME 1000 "Starter"
 
ALERT ID RomIncompatibleAlert
CONFIRMATION
BEGIN
  TITLE "System Incompatible"
  MESSAGE "System Version 3.0 or greater " \
    "is required to run this application."
  BUTTONS "OK" 
END
 
FORM ID MainForm AT (0 0 160 160)
USABLE
BEGIN
  TITLE "OReilly Starter Main"
  BUTTON "Beep" ID MainBeepButton AT (40 100 AUTO AUTO)
  BUTTON "Goto Second Form" ID MainGotoSecondFormButton AT 
    (PrevLeft PrevBottom + 5 AUTO AUTO)
END
 
FORM ID SecondForm AT (0 0 160 160)
USABLE
BEGIN
  TITLE "OReilly Starter Second"
  BUTTON "Goto Main Form" ID SecondGotoMainFormButton AT 
    (40 130 AUTO AUTO)
END

This defines the name of the application as it appears in the Application launcher, the alert that's shown if run on an older system, and the two forms.

Header Files

Example 5-10 shows Constants.h, which defines two constants: our creator ID and the minimum version for which we'll run.

Example 5-10: Constants.h

#ifndef CONSTANTS_H
#define CONSTANTS_H
 
#define kAppFileCreator         '????'
 
// The minimum OS version we support.
#define kOurMinVersion  sysMakeROMVersion(3,0,0,sysROMStageRelease,0)
#endif

The next file, ResourceDefines.h, is included by both the .c files and the .rcp file to define the constants used by the UI (see Example 5-11).

Example 5-11: ResourceDefines.h

#define RomIncompatibleAlert           1001
 
#define MainForm                       2000 
#define MainBeepButton                 2001
#define MainGotoSecondFormButton       2002
 
#define SecondForm                     3000 
#define SecondGotoMainFormButton       3001

MainForm.h file defines the function that is exported from MainForm.c (see Example 5-12).

Example 5-12: MainForm.h

#ifndef MAINFORM_H
#define MAINFORM_H

Boolean MainFormHandleEvent(EventPtr event);

#endif

SecondForm.h file defines the function that is exported from SecondForm.c (see Example 5-13).

Example 5-13: SecondForm.h

#ifndef SECONDFORM_H
#define SECONDFORM_H
 
Boolean SecondFormHandleEvent(EventPtr event);
 
 
#endif

Utils.h exports some useful utility routines (see Example 5-14).

Example 5-14: Utils.h

#ifndef UTILS_H
#define UTILS_H
 
Err RomVersionCompatible(UInt32 requiredVersion, UInt16 launchFlags);
void *GetObjectPtr(FormPtr form, UInt16 objectID);
void *GetObjectPtrFromActiveForm(UInt16 objectID);
 
#endif

OReilly Starter Summary

In this simple application, we have all the major elements of any Palm application. In review, these are:

  • A set of necessary include files
  • A startup routine called AppStart, which handles all our initial setup
  • A PilotMain routine that starts an AppEventLoop to handle events passed to it by the system
  • An event loop that continually hands events to a series of four managing routines--SysHandleEvent, MenuHandleEvent, AppHandleEvent, and FrmDispatchEvent
  • Routines to handle our form-specific functionality
  • A closing routine called AppStop, which handles the proper closing of our application

In the next installment, learn how the operating system communicates with an application when it's not running

Neil Rhodes and Julie McKeehan are experienced authors who, through their company, Calliope Enterprises, work closely with Palm Computing to develop new training materials, materials that are based on this book.

Palm OS Programming

Related Reading

Palm OS Programming
The Developer's Guide
By Neil Rhodes, Julie McKeehan

Return to the Wireless DevCenter