Introduction
There have been several people asking Palm handheld questions lately in the various CP forums and, although Code Project is mainly a Windows programming site, I think it would benefit from a few Palm articles. So, without further adue, here's a little something to wet your appetite.
Palm Development Resources
The demo application and source code were created using Metrowerk's CodeWarrior for PalmOS IDE (version 6). The resources were made using Contstructor for PalmOS. I believe there is an evaluation version you can download from Metrowerks. Also, you can download the Palm Emulator from Palm and find most development information there as well.
If you want completely free dev tools, there is a GNU compiler for the Palm as well. The demo application was not designed using the GNU compiler so I don't know if it will work or not.
When you write a production Palm application, you will need to sign-up for a unique 4 digit ID number that will differentiate your application resources from any others (kind of like a GUID, but not as complex).
Palm Application Terminology
All OSes have their own terminology and the PalmOS is no exception. The following is a list of some of the more relevant terms used in PalmOS programming: 1
Window
A rectangular area in which things like dialogs, forms, and menus are drawn by the application.
Form
An application window that covers the entire screen. A form may also contain controls, text areas, and menus. Only one active form is allowed at a time.
Database
A collection of persistent memory chunks. There are resource and record databases.
Resource
A piece of data stored in a resource database. Identified by a resource type and number.
Record
A data structure identified by a unique record ID. Application data is typically stored in a record database.
Launch Code
A parameter passed to an application that specifies what the application should do when executed.
Alert
A warning or information dialog that needs to be dismissed by the user.
Like Microsoft Windows, the PalmOS is an event-driven operating system. Only one application can be open at a time and all applications contain an event loop which retrieves events and acts upon them.
Palm Application Structure
The entry point to every palm application is the PilotMain
function.
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
2
The first parameter, cmd
, is the launch code for the application. There are several available launch codes, but to start an application normally, use the constant sysAppLaunchCmdNormalLaunch
.
The second parameter, cmdPBP
, is a pointer to a structure containing any launch-command-specific parameters, or NULL if the launch code has none. A MemPtr
is simply a void *.
The final parameter, launchFlags
, indicates whether your application's global variables are available, whether your application is now the active application, whether it already was the active application, and so on.
UInt32 PilotMain( UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
switch (cmd)
{
case sysAppLaunchCmdNormalLaunch:
AppEventLoop();
FrmCloseAllForms();
break;
default:
break;
}
return 0;
}
The
PiltoMain
function calls the main event loop function. In this function, we continually process events for our application and the system (See
Figure 1 for an illustration). We first get an event using the
EvtGetEvent
function, and then dispatch that event to 4 event handlers. If an event handler returns true, the event was handled and will not process further. If it is not handled, it is sent to each successive handler for processing. The loop continues until the
appStopEvent
is received.
static void AppEventLoop(void)
{
UInt16 error;
EventType event;
do
{
EvtGetEvent(&event, evtWaitForever);
if (! SysHandleEvent(&event))
if (! MenuHandleEvent(0, &event, &error))
if (! ApplicationHandleEvent(&event))
FrmDispatchEvent(&event);
} while (event.eType != appStopEvent);
}
SysHandleEvent
and
MenuHandleEvent
handle Palm system events and menu events respectively, but the
ApplicationHandleEvent
and
FrmDispatchEvent
are where most of the real action is handled in a Palm application.
The
ApplicationHandleEvent
function is where you set the event handlers for all of your forms using
void FrmSetEventHandler (FormType *formP, FormEventHandlerType *handler)
. A form event handler routine is of the form:
Boolean FormEventHandlerType (EventType *eventP)
. You are basically setting a callback function up as an event handler (just like Window's WindowProcedure).
|
static Boolean MainFormHandleEvent(EventPtr eventP)
{
Boolean handled = false;
FormPtr frmP = FrmGetActiveForm();
switch (eventP->eType)
{
case frmOpenEvent:
FrmDrawForm(frmP);
handled = true;
break;
default:
break;
}
return handled;
}
|
static Boolean AppHandleEvent(EventPtr eventP)
{
UInt16 formId;
FormPtr frmP;
Boolean bRetVal = false;
if (eventP->eType == frmLoadEvent) {
formId = eventP->data.frmLoad.formID;
frmP = FrmInitForm(formId); FrmSetActiveForm(frmP);
switch (formId)
{
case MainForm:
FrmSetEventHandler(frmP, MainFormHandleEvent);
break;
default:
break;
}
bRetVal = true;
}
return bRetVal;
}
The
FrmDispatchEvent
routine provides indirect form-specific event handling. To provide this,
FrmDispatchEvent
calls the form's event handler (MainFormHandleEvent in the example above).
A "Hello World!" Example
As an example on how to write your first Palm application, I'll use the never tiresome "Hello World!" example. I will open a form with a button which, when pressed, will write "Hello World!" to the center of the screen.
The demo source code's PilotMain
and main event loop are almost identical to what we covered in the Palm Application Structure section with the exception of the FrmGotoForm
function call. void FrmGotoForm (UInt16 formId)
sends a close event to the currently active form and load and open events to the form specified by fromId
. The application event handler will then set the form event handler for this form given the formId
. So in summary, FrmGotoForm
closes the active form and opens a new one.
When the "Say Hello" button is pressed on the form, a ctlSelectEvent
event is sent to the form which is then passed to the form button handler routine, MainFormButtonHandler
.
static Boolean MainFormButtonHandler(FormPtr formP, EventPtr eventP)
{
Boolean handled = false;
switch (eventP->data.ctlEnter.controlID)
{
case MainSayHelloButton:
SayHello();
handled = true;
break;
default:
break;
}
return handled;
}
The above switch statement finds the control that was selected and calls my SayHello function (below).
static void SayHello()
{
short nCharWidth = 0;
short width = 0, height = 0;
Char* pText = (Char*) MemPtrNew(13);
StrCopy(pText, "Hello World!");
nCharWidth = FntCharsWidth(pText, StrLen(pText));
WinGetWindowExtent(&width, &height);
WinDrawChars(pText, StrLen(pText), (width/2) - (nCharWidth/2), height/2);
MemPtrFree(pText);
}
Most Palm code is similar to standard C/C++ but string and memory functions are optimized for the platform. Using the standard C/C++ functions may increase the size of your compiled executable and on the Palm, size does matter.
To begin with, we allocate 13 bytes for our "Hello World!" string using the
MemPtrNew
function which acts just like
malloc
.
We then use Palm's
StrCopy
function in place of the standard
strcpy
.
FntCharsWidth
returns the width of a string in pixels using the current font.
WinGetWindowExtent
receives the width and height of the Palm screen area. You should not assume that the Palm screen is 160x160 anymore (the new Palm Tungsten T has a 320x320 screen area).
After getting the screen size and string size, we finally draw the characters to the center of the screen using
void WinDrawChars (const Char *chars, Int16 len, Coord x, Coord y)
.
We then free the memory allocated for the string using
MemPtrFree
.
After saying hello, the demo app will just sit there waiting for your input until you close the aplication using the standard Home button on the Palm.
Conclusion
I hope you found this article to be understandable and interesting. The Palm platform is certainly here to stay and fun to develop for so I encourage you to give it a try.
Let me know if you are interested in more articles, if so they may include information on how to create and use a palm database, plus palm "conduit" development.
Also, I have not included the PalmOS.h file with the demo project because it is readily available with the Palm SDK which can be downloaded from the PalmOS website.
Sources
1 Rhodes, McKeehan: "Palm Programming The Developer's Guide, First Edition", 67-69.
2 Palm Inc., System Manager {online} Available
http://lovecraft.die.udec.cl/prog_lang/PalmOS/SystemManager.html#941792, 2001.
Helpful Links:
Palm OSĀ® Programmer's API Reference