Print
O'Reilly Book Excerpts: Palm OS Programming, 2nd Edition

Structure of a Palm Application, Part 2

by Neil Rhodes and Julie McKeehan

A Simple Application

Now it's time to apply what you just learned about an application's interaction with the OS, its PilotMain routine, and the event loop to an actual application. We are using OReilly Starter, the application we first discussed in Chapter 4.

What the Application Does--Its User Interface

Our OReilly Starter application has two forms. On the first form, there are two buttons. Pressing the first one causes the Palm device to beep. Pressing the second button switches the view to the second form. The second form has a single button that returns to the previous form (see Figure 5-3). This is all there is to our simple application.

Figure 5-3. The OReilly Starter application

An Overview of the Source Files

Here are the source files that make up this application (as opposed to the tools-specific files like CodeWarrior .mcp files or PRC-Tools .def files).

Main.c
This file contains the main entry point (PilotMain) of the application. It also includes the event loop, application startup and shutdown code, and the code to load forms as needed.


MainForm.c
This contains the code that handles everything that occurs in the first form.


SecondForm.c
This contains the code for the second form.


Utils.c
This contains some utility routines that can be used throughout the application. You can include this same source file in all your applications.


Resources.rcp
This PilRC file contains the UI elements (the forms, form objects, and the application name).


ResourceDefines.h
This file defines constants for all the application's resources. This file is included by the .c files, as well as Resources.rcp.


In This Series

Structure of a Palm Application, Part 3
In this third excerpt from "Palm OS Programming, 2nd Edition," Neil Rhodes and Julie McKeehan discuss how the operating system communicates with an application when it's not running. This is the third in a series of three excerpts designed to familiarize developers with the structure of Palm apps.

Structure of a Palm Application, Part 1
In this excerpt from "Palm OS Programming, 2nd Edition," Neil Rhodes and Julie McKeehan introduce the terminology and conventions of a Palm application. This is the first in a series of three excerpts designed to familiarize developers with the structure of Palm apps.

MainForm.h
This declares the event handler for the main form. This is included by both Main.c and MainForm.c.


SecondForm.h
This declares the event handler for the second form. It is also included by both Main.c and SecondForm.c.


Constants.h
This file contains the defined constants used throughout the application.


Utils.h
This declares the utility functions in Utils.c.


The Source File of Main.c

Main.c starts with the #include files (see Example 5-4).

Example 5-4: First part of Main.c: #defines and #includes

#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 "MainForm.h"
#include "SecondForm.h"
#include "Utils.h"
#include "Constants.h"

Related Reading

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

TIP: PalmOS.h is an include file that contains most of the standard Palm OS include files. By default, it defines an ERROR_CHECK_LEVEL of ERROR_CHECK_PARTIAL, which is suitable for a release build. It doesn't, however, provide the checking we'd like for a debug build (see Chapter 7 for more information on debug builds). Thus, if we're compiling a DEBUG_BUILD, we redefine ERROR_CHECK_LEVEL. We must #include BuildDefines.h first, in order to obtain the definition of ERROR_CHECK_FULL.

We define DO_NOT_ALLOW_ACCESS_TO_INTERNALS_OF_STRUCTS to help with good coding practices. This will cause the 4.0 SDK to generate a compile-time error for us if we try to access fields within OS structures directly, rather than through appropriate API calls. You should always use the APIs, rather than fool around within an OS structure directly.

Example 5-5 shows the remainder of Main.c.

Example 5-5: Remaining functions in Main.c

static Boolean AppHandleEvent(EventPtr event)
{
  UInt16 formId;
  FormPtr form;
 
  if (event->eType == frmLoadEvent) {
    // Load the form resource.
    formId = event->data.frmLoad.formID;
    form = FrmInitForm(formId);
    ErrFatalDisplayIf(!form, "Can't initialize form");
    FrmSetActiveForm(form);
 
    // Set the event handler for the form.  The handler of the currently
    // active form is called by FrmHandleEvent each time it receives 
    // an event.
    switch (formId) {
    case MainForm:
      FrmSetEventHandler(form, MainFormHandleEvent);
      break;
 
    case SecondForm:
      FrmSetEventHandler(form, SecondFormHandleEvent);
      break;
 
    default:
      ErrFatalDisplay("Invalid Form Load Event");
      break;
 
    }
    return true;
  } else 
    return false;
}
 
static void AppEventLoop(void)
{
  Err error;
  EventType event;
 
  do {
    EvtGetEvent(&event, evtWaitForever);
    
    if (! SysHandleEvent(&event))
      if (! MenuHandleEvent(0, &event, &error))
        if (! AppHandleEvent(&event))
          FrmDispatchEvent(&event);
 
  } while (event.eType != appStopEvent);
}
 
 
static Err AppStart(void)
{
   return errNone;
}
 
 
static void AppStop(void)
{
  FrmCloseAllForms(  );
}
 
UInt32 PilotMain(UInt16 launchCode, MemPtr launchParameters, 
  UInt16 launchFlags)
{
#pragma unused(launchParameters)
  Err error;
 
  switch (launchCode) {
  case sysAppLaunchCmdNormalLaunch:
    error = RomVersionCompatible (kOurMinVersion, launchFlags);
    if (error) 
      return error;
    error = AppStart(  );
    if (error) 
rror;
      
    FrmGotoForm(MainForm);
    AppEventLoop(  );
    AppStop(  );
    break;
 
  default:
    break;
  }
  
  return errNone;
}

kOurMinVersion is defined as Version 3.0 of the Palm OS in Constants.h.

The Form Files of the Application

Main.c is the source file containing routines responsible for handling the main form (see Example 5-6).

Example 5-6: Main.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 "MainForm.h"
 
 
static void MainFormInit(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 MainFormDeinit(FormPtr form)
{
#pragma unused(form)
}
 
 
Boolean MainFormHandleEvent(EventPtr event)
{
  Boolean handled = false;
  FormPtr form;
 
  switch (event->eType) 
  {
  case frmOpenEvent:
    form = FrmGetActiveForm(  );
    MainFormInit(form);
    FrmDrawForm(form);
    // Here's where you'd add a call to FrmSetFocus.
    handled = true;
    break;
      
      
  case ctlSelectEvent:
  switch (event->data.ctlSelect.controlID) {
    case MainBeepButton:
      SndPlaySystemSound(sndWarning);
      handled = true;
      break;
        
    case MainGotoSecondFormButton:
      FrmGotoForm(SecondForm);
      handled = true;
      break;
    }
    break;
 
  case frmCloseEvent:
    MainFormDeinit(FrmGetActiveForm(  ));
    handled = false;
    break;
 
  default:
    break;
  }  
  return handled;
}

The event handler for the main form handles three different kinds of events:

  • frmOpenEvent
  • frmCloseEvent (discussed in Chapter 8, along with the previous event)
  • ctlSelectEvent (specifies that a control has been chosen)

The MainFormInit and MainFormDeinit routines are there because it is quite common to need to do some initialization when a form opens. You will often need to do some cleanup when a form closes. This is where such things should happen.

The MainFormHandleEvent handles the ctlSelectEvent by looking to see what control was chosen:

  • If the beep button is chosen, it plays a sound.
  • If the Goto button is chosen, it calls FrmGotoForm, which closes this form and opens the other one.

Pages: 1, 2

Next Pagearrow