This framework runs a 2nd form at the same time as the 1st main form for use
as a navigation bar.
Back in the middle of March people gave me some very good ideas on
how possibly to run two different forms at the same time. I believe I have
a "solid" solution here. Everything seems to work perfectly as far as I can
tell. In the follow paragraphs I'll describe my goal, my methodology and
attach some source code.
GOAL;
The goal is to have this second form act as a navigation bar. The
end application (That I will not discuss here.) basically mimics a sequence
of processing steps. Each processing step is represented by forms 1 to n.
The navigation form is the 2nd form that is always running. The navigation
form is responsible for the sequencing of the 1 to n forms.
--------------------
| |
| |
| Area for Forms |
| 1 to n |
| |
| |
| |
--------------------
| |
| Navigation Form |
| |
--------------------
METHODOLOGY;
In the application event handler I check all pen down events. If
any of the pen down events are below the 1 to n form area, I set the active
form to the navigation form and set the navigation event handler as well.
No matter if I do or don't set the navigation stuff I don't set the handled
flag, that way the event is passed on to the next event handler.
In the navigation event handler any time I detect a new 1 to n form
is to be displayed I set the active form back to the current form that is
still showing above the navigation form. At this point I then go to the new
form and set it's event handler. While the navigation event handler is
active, if a pen up event occurs that ends above the navigation form or in
the title area of the navigation form, I set the active form back to the
current form that is still showing above the navigation form leave the
current 1 to n form intact.
The other forms, that is forms 1 to n are only used here for testing
purposes.
SOURCE CODE;
########## start of Main.c ##########
#include <PalmOS.h>
#include "NavBar_res.h"
extern Boolean frmNav_HandleEvent(EventPtr event);
extern Boolean frm1_HandleEvent(EventPtr event);
extern Boolean frm2_HandleEvent(EventPtr event);
extern Boolean frm3_HandleEvent(EventPtr event);
extern FormPtr FormPtrs[3]; //Ptrs to all other forms besides NavBar form
extern FormEventHandlerPtr CurrHandlerPtrs[3]; //Ptrs to all other event
handlers
extern FormPtr NavFrmP; //Ptr to NavBar form
/************************************************************/
static Int16 StartApplication(void)
{
FrmGotoForm(frmNav); //Start up NavBar form 1st
FrmPopupForm(frm1); //Start 1st other form without erasing NavBar
form
return 0;
}
static Boolean ApplicationHandleEvent(EventPtr event)
{
UInt16 formID;
FormPtr form;
Boolean handled = false;
Int16 srtY;
switch (event->eType)
{
/* If pen down event is below the normal/other/(1 to n) form
area Y>146,
set the active form to the navigation form and set the
navigation
event handler as well. */
case penDownEvent: //Don't set handled flag; pass it on to
other handlers
srtY = event->screenY; //Save window Y so you can
restore below
/* Had to use the Y of display instead of window. When
using the
normal window Y, the 1st penDown Y value is the
offset of
the NavBar form which is < 14. A second
penDown's Y value will
be beyound the 146 value. But we want to change
the active form
on the 1st penDown event if it's beyound the 146
screen boundary */
WinWindowToDisplayPt(&event->screenX,
&event->screenY);
if (event->screenY > 146) //Then switch active form
to NarBar form
{
//Restore window Y<14 so NavBar handler can
find UI correct control
event->screenY = srtY;
FrmSetActiveForm(NavFrmP);
FrmSetEventHandler(NavFrmP,
(FormEventHandlerPtr) frmNav_HandleEvent);
}
break;
case frmLoadEvent:
formID = event->data.frmLoad.formID;
form = FrmInitForm(formID);
FrmSetActiveForm(form);
switch (formID)
{
case frm1: // Set event handler for frm1
FrmSetEventHandler(form,
(FormEventHandlerPtr) frm1_HandleEvent);
//Need the following 2 items in
NavBar event handler
FormPtrs[0] = form;
CurrHandlerPtrs[0] =
&frm1_HandleEvent;
break;
case frm2: // Set event handler for frm2
FrmSetEventHandler(form,
(FormEventHandlerPtr) frm2_HandleEvent);
//Need the following 2 items in
NavBar event handler
FormPtrs[1] = form;
CurrHandlerPtrs[1] =
&frm1_HandleEvent;
break;
case frm3: // Set event handler for frm3
FrmSetEventHandler(form,
(FormEventHandlerPtr) frm3_HandleEvent);
//Need the following 2 items in
NavBar event handler
FormPtrs[2] = form;
CurrHandlerPtrs[2] =
&frm1_HandleEvent;
break;
case frmNav: // Set event handler for frmNav
FrmSetEventHandler(form,
(FormEventHandlerPtr) frmNav_HandleEvent);
//Needed in this event handler for
future penDownEvent's
NavFrmP = form;
break;
}
handled = true;
break;
}
return handled;
}
static void EventLoop(void)
{
Int16 error;
EventType event;
do
{
EvtGetEvent(&event, evtWaitForever);
if (!SysHandleEvent(&event))
{
if (!MenuHandleEvent(0, &event, &error))
{
if (!ApplicationHandleEvent(&event))
FrmDispatchEvent(&event);
}
}
}
while (event.eType != appStopEvent);
}
static void StopApplication(void)
{
FrmCloseAllForms(); //Clean up all forms including NavBar form
}
UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
Int16 error;
if (cmd == sysAppLaunchCmdNormalLaunch)
{
error = StartApplication();
if (error) return error;
EventLoop();
StopApplication();
}
return 0;
}
########## end of Main.c ##########
########## start of frmNav.c ##########
#include <PalmOS.h>
#include "NavBar_res.h"
Boolean frmNav_HandleEvent(EventPtr event);
FormPtr NavFrmP; //Ptr to NavBar form
FormPtr FormPtrs[3]; //Ptrs to all other forms besides NavBar form
FormEventHandlerPtr CurrHandlerPtrs[3]; //Ptrs to all other event handlers
//This should be the starting other/(1 to n) form started in
StartApplication()
UInt16 CurrFrm = 1;
UInt16 NewFrm = 1;
Boolean frmNav_HandleEvent(EventPtr event)
{
FormPtr form;
Boolean handled = false;
ControlPtr ctlNavPopUp =
FrmGetObjectPtr(NavFrmP, FrmGetObjectIndex(NavFrmP,
popNav));
ListPtr lstNavPopUp =
FrmGetObjectPtr(NavFrmP, FrmGetObjectIndex(NavFrmP,
lstNav));
switch (event->eType)
{
/* When switching forms 4 things must be done;
1.) Determine the next other/(1 to n) form to display
2.) Set the NavBar popup trigger lable to the new form name
3.) The currently active form is the NavBar form. Set the
active
form back to the other/(1 to n) form that is currently
displayed
so it will be erase and removed from memory when
FrmGotoForm is called.
4.) Call FrmGotoForm which the new current form. This
requires that
all forms have even 1000 IDs. i.e. frm1=1000,
frm2=2000, frm3=3000, etc...
The CurrFrm is really a indexing number. */
case ctlSelectEvent: //Either the Forward or Back button was
pressed
if (event->data.ctlSelect.controlID == btnForw)
{
NewFrm = CurrFrm + 1; //Sequence to the next
form
//However if beyound the last form goto the
1st form
if (NewFrm > 3) NewFrm = 1;
LstSetSelection(lstNavPopUp, NewFrm - 1);
CtlSetLabel(ctlNavPopUp,
LstGetSelectionText(
lstNavPopUp,
LstGetSelection(lstNavPopUp)));
FrmSetActiveForm(FormPtrs[CurrFrm - 1]);
CurrFrm = NewFrm;
FrmGotoForm(CurrFrm * 1000);
handled = true;
}
else if (event->data.ctlSelect.controlID == btnBack)
{
NewFrm = CurrFrm - 1; //Sequence back one
form
//If less than the 1st form goto the last
form
if (NewFrm < 1) NewFrm = 3;
LstSetSelection(lstNavPopUp, NewFrm - 1);
CtlSetLabel(ctlNavPopUp,
LstGetSelectionText(
lstNavPopUp,
LstGetSelection(lstNavPopUp)));
FrmSetActiveForm(FormPtrs[CurrFrm - 1]);
CurrFrm = NewFrm;
FrmGotoForm(CurrFrm * 1000);
handled = true;
}
break;
case popSelectEvent: //Popup trigger list was selected
/* The user selected the same form that is already
being displayed
so don't redraw it just reset that forms event
handler. */
if (event->data.popSelect.selection == (CurrFrm -
1))
{
FrmSetActiveForm(FormPtrs[event->data.popSelect.priorSelection]);
FrmSetEventHandler(FormPtrs[CurrFrm - 1],
(FormEventHandlerPtr)
CurrHandlerPtrs[CurrFrm - 1]);
}
else //Goto the new form that was choosen in the
list
{
//PalmOS take care of determining new form
and setting trigger label
CtlSetLabel(ctlNavPopUp,
LstGetSelectionText(
event->data.popSelect.listP,
event->data.popSelect.selection));
FrmSetActiveForm(FormPtrs[event->data.popSelect.priorSelection]);
CurrFrm = event->data.popSelect.selection +
1;
FrmGotoForm(CurrFrm * 1000);
}
handled = true;
break;
/* If a penUp occured in either the other/(1 to n) form area
or
in the NavBar form's title area then reset the active
form to
the other/(1 to n) form that is already displayed and
reset it's
event handler. Don't redraw the other/(1 to n) form area.
*/
case penUpEvent:
if (event->data.penUp.end.y < 147 ||
FrmPointInTitle(
FormPtrs[CurrFrm - 1], event->screenX,
event->screenY))
{
FrmSetActiveForm(FormPtrs[CurrFrm - 1]);
FrmSetEventHandler(FormPtrs[CurrFrm - 1],
(FormEventHandlerPtr)
CurrHandlerPtrs[CurrFrm - 1]);
handled = true;
}
break;
case frmOpenEvent:
form = FrmGetActiveForm();
FrmDrawForm(form);
handled = true;
break;
}
return handled;
}
########## end of frmNav.c ##########
########## start of OtherForms.c ##########
#include <PalmOS.h>
#include "NavBar_res.h"
/* The event handlers in this module don't matter. They should be replaced
with event handlers from your own application. This module is only
provided
to demonstrate the usage of NavBar */
Boolean frm1_HandleEvent(EventPtr event);
Boolean frm2_HandleEvent(EventPtr event);
Boolean frm3_HandleEvent(EventPtr event);
char strX[] = "xxx";
FieldPtr fldpX;
char strY[] = "yyy";
FieldPtr fldpY;
char strAdd1[3];
FieldPtr fldpAdd1;
int intAdd1 = 0;
Boolean frm1_HandleEvent(EventPtr event)
{
FormPtr form;
Boolean handled = false;
form = FrmGetActiveForm();
switch (event->eType)
{
case penDownEvent: //Don't set handled flag; pass it on
fldpX = FrmGetObjectPtr(form, FrmGetObjectIndex(form,
fldX));
StrIToA(strX, event->screenX);
FldSetTextPtr(fldpX, strX);
fldpY = FrmGetObjectPtr(form, FrmGetObjectIndex(form,
fldY));
StrIToA(strY, event->screenY);
FldSetTextPtr(fldpY, strY);
FrmDrawForm(form);
break;
case ctlSelectEvent:
if (event->data.ctlSelect.controlID == cmdAdd1)
{
intAdd1++;
fldpAdd1 = FrmGetObjectPtr(form,
FrmGetObjectIndex(form, fldAdd1));
StrIToA(strAdd1, intAdd1);
FldSetTextPtr(fldpAdd1, strAdd1);
FrmDrawForm(form);
handled = true;
break;
}
case frmOpenEvent:
FrmDrawForm(form);
handled = true;
break;
}
return handled;
}
Boolean frm2_HandleEvent(EventPtr event)
{
FormPtr form;
Boolean handled = false;
form = FrmGetActiveForm();
switch (event->eType)
{
case penDownEvent: //Don't set handled flag; pass it on
fldpX = FrmGetObjectPtr(form, FrmGetObjectIndex(form,
fldX));
StrIToA(strX, event->screenX);
FldSetTextPtr(fldpX, strX);
fldpY = FrmGetObjectPtr(form, FrmGetObjectIndex(form,
fldY));
StrIToA(strY, event->screenY);
FldSetTextPtr(fldpY, strY);
FrmDrawForm(form);
break;
case ctlSelectEvent:
if (event->data.ctlSelect.controlID == cmdAdd1)
{
intAdd1++;
fldpAdd1 = FrmGetObjectPtr(form,
FrmGetObjectIndex(form, fldAdd1));
StrIToA(strAdd1, intAdd1);
FldSetTextPtr(fldpAdd1, strAdd1);
FrmDrawForm(form);
handled = true;
break;
}
case frmOpenEvent:
FrmDrawForm(form);
handled = true;
break;
}
return handled;
}
Boolean frm3_HandleEvent(EventPtr event)
{
FormPtr form;
Boolean handled = false;
form = FrmGetActiveForm();
switch (event->eType)
{
case penDownEvent: //Don't set handled flag; pass it on
fldpX = FrmGetObjectPtr(form, FrmGetObjectIndex(form,
fldX));
StrIToA(strX, event->screenX);
FldSetTextPtr(fldpX, strX);
fldpY = FrmGetObjectPtr(form, FrmGetObjectIndex(form,
fldY));
StrIToA(strY, event->screenY);
FldSetTextPtr(fldpY, strY);
FrmDrawForm(form);
break;
case ctlSelectEvent:
if (event->data.ctlSelect.controlID == cmdAdd1)
{
intAdd1++;
fldpAdd1 = FrmGetObjectPtr(form,
FrmGetObjectIndex(form, fldAdd1));
StrIToA(strAdd1, intAdd1);
FldSetTextPtr(fldpAdd1, strAdd1);
FrmDrawForm(form);
handled = true;
break;
}
case frmOpenEvent:
FrmDrawForm(form);
handled = true;
break;
}
return handled;
}
########## end of OtherForms.c ##########
########## start of NavBar_res.h ##########
#define frmNav 4000
#define btnBack 4001
#define btnForw 4002
#define lstNav 4003
#define popNav 4004
//All other/(1 to n) forms must have IDs that are multiples of 1000
#define frm1 1000
#define frm2 2000
#define frm3 3000
#define cmdAdd1 5001
#define fldAdd1 5002
#define fldX 5003
#define fldY 5004
########## end of NavBar_res.h ##########
########## start of NavBar.rcp ##########
#include "NavBar_res.h"
ICON "computer_22x22x1.bmp"
SMALLICON "computer_15x9x1.bmp"
FORM ID frmNav AT (0 147 160 13)
NOFRAME
USABLE
BEGIN
TITLE "GoTo"
/* Set the label to your applications 1st form */
POPUPTRIGGER "frm1" ID popNav AT (34 1 49 11) USABLE FONT 0
/* The following list should contain the forms from your own
application */
LIST "frm1" "frm2" "frm3"
ID lstNav AT (34 1 49 11) VISIBLEITEMS 2 NONUSABLE
POPUPLIST ID popNav lstNav
BUTTON "Back" ID btnBack AT (86 1 35 11) USABLE FONT 0
BUTTON "Forward" ID btnForw AT (123 1 36 11) USABLE FONT 0
END
/*** The following forms should be replaced with your own application
forms
and should not extent below the 146 screen cordinate ***/
FORM ID frm1 AT (0 0 160 147)
NOFRAME
USABLE
BEGIN
TITLE "frm1"
BUTTON "Add 1" ID cmdAdd1 AT (15 35 AUTO AUTO)
FIELD fldAdd1 AT (60 35 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
LABEL "X = " AUTOID AT (10 70)
LABEL "Y = " AUTOID AT (10 85)
FIELD fldX AT (28 70 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
FIELD fldY AT (28 85 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
END
FORM ID frm2 AT (0 0 160 147)
NOFRAME
USABLE
BEGIN
TITLE "frm2"
BUTTON "Add 1" ID cmdAdd1 AT (15 35 AUTO AUTO)
FIELD fldAdd1 AT (60 35 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
LABEL "X = " AUTOID AT (10 70)
LABEL "Y = " AUTOID AT (10 85)
FIELD fldX AT (28 70 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
FIELD fldY AT (28 85 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
END
FORM ID frm3 AT (0 0 160 147)
NOFRAME
USABLE
BEGIN
TITLE "frm3"
BUTTON "Add 1" ID cmdAdd1 AT (15 35 AUTO AUTO)
FIELD fldAdd1 AT (60 35 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
LABEL "X = " AUTOID AT (10 70)
LABEL "Y = " AUTOID AT (10 85)
FIELD fldX AT (28 70 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
FIELD fldY AT (28 85 50 15) NONEDITABLE SINGLELINE MAXCHARS 4
END
########## end of NavBar.rcp ##########
--
For information on using the Palm Developer Forums, or to unsubscribe, please see
http://www.palmos.com/dev/tech/support/forums/