O'Reilly Book Excerpts: Palm OS Programming, 2nd Edition
Structure of a Palm Application, Part 2
by Neil Rhodes and Julie McKeehanA 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.
|
|
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.
- 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.
|
In This Series
Structure of a Palm Application, Part 3
Structure of a Palm Application, Part 1 |
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 |
TIP: PalmOS.h is an include file that contains most of the standard Palm OS include files. By default, it defines an
ERROR_CHECK_LEVELofERROR_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 aDEBUG_BUILD, we redefineERROR_CHECK_LEVEL. We must #include BuildDefines.h first, in order to obtain the definition ofERROR_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 |



