> This method works - but it is not at all a clean design.
> It has the advantage that you don't have to issue
> FrmUpdateForm() to the calling form (which requires you
> to know _which_ form called you).
> But it has the disadvantage that you have to set a
> variable saying which form you called with FrmPopupForm().
you don't need to know which form called you in order to use FrmUpdateForm.
see example below:
// return to previous form
FrmReturnToForm(0);
// now, tell that form to update itself
FrmUpdateForm(FrmGetActiveFormID(), frmRedrawCode);
> 2. If you issue FrmUpdateForm() from the called (popped up)
> form, then this message will get back to the calling form.
> But you ahve to know which form called you, and that
> means you have to leave this lying around in a global variable.
nope, per above example.
by the way, here's code for a whiz-bang set of modal form APIs. i have been
using these for several months. the big difference between FrmPopupForm and
my FrmPopupModalForm, is that the latter does not return until the user
dismisses the form (it supports the appStopEvent, too, and passes it to your
modal form's event handler as well, so that the form can do any cleanup
that's necessary). the APIs are modeled after Win32's CreateDialog and
EndDialog APIs.
-------- snip --------
// -- Header File ----------
// assumes that IDC_FORM_OK is the ID of the "Ok" button in the form
// call FrmEndModalForm to close the form and cause FrmPopupModalForm to
return wReturn.
// can be called multiple times while exitting a form, the latest call wins
as far as wReturn is concerned.
void FrmEndModalForm(Word wReturn);
// set DWord parameter, which can be queried by the form handler code, via
FrmGetModalParam.
// this is useful for passing information to/from a modal form (can be a
pointer to a struct, for instance).
void FrmSetModalParam(DWord dwParam);
// query the DWord parameter that was optionally initialized via
FrmSetModalParam
DWord FrmGetModalParam(void);
// call FrmSetModalFlags to set behavior flags. currently only
modalOkShortcut is supported.
#define modalOkShortcut 0x0001 // translate graffiti "enter" stroke to
ctlSelect for IDC_FORM_OK
void FrmSetModalFlags(Word flags);
// call this with the resource ID of the form to pop up, and a pointer to
the
// event handler function to use (or 0 for a default modal form event
handler).
Word FrmPopupModalForm(Word formID, FormEventHandlerPtr pfnEventHandler);
// Note, if the appStopEvent occurs, it is passed to the form handler,
// so that the form can do any necessary cleanup. in that case,
// FrmPopupModalForm will end up returning the value of the
// Default Button Id for the form (which both Constructor and PilRC
// allow you to set).
// -- Code ----------
static Word s_wModalReturnValue = 0;
static DWord s_dwModalParam = 0;
static Word s_wModalFlags;
static Boolean s_fModal = fFalse;
#define PUSH_MODAL_STATE \
DWord _dwModalParam = s_dwModalParam; \
Word _wModalFlags = s_wModalFlags; \
Boolean _fModal = s_fModal;
#define POP_MODAL_STATE \
s_dwModalParam = _dwModalParam; \
s_wModalFlags = _wModalFlags; \
s_fModal = _fModal;
void FrmEndModalForm(Word wReturn)
{
s_wModalReturnValue = wReturn;
if (s_fModal)
{
FrmReturnToForm(0);
s_fModal = fFalse;
}
}
void FrmSetModalFlags(Word flags)
{
s_wModalFlags = flags;
}
void FrmSetModalParam(DWord dwParam)
{
s_dwModalParam = dwParam;
}
DWord FrmGetModalParam(void)
{
return s_dwModalParam;
}
static Boolean DefaultPopupFormHandleEvent(EventPtr pEvent)
{
Boolean fHandled = fTrue;
switch (pEvent->eType)
{
case ctlSelectEvent:
{
FormPtr pfrm = FrmGetActiveForm();
FormObjectKind kind;
kind = FrmGetObjectType(pfrm, FrmGetObjectIndex(pfrm,
pEvent->data.ctlSelect.controlID));
if (frmControlObj == kind &&
buttonCtl ==
((ControlPtr)pEvent->data.ctlSelect.pControl)->style)
{
FrmEndModalForm(pEvent->data.ctlSelect.controlID);
}
else
fHandled = fFalse;
}
break;
case frmOpenEvent:
FrmDrawForm(FrmGetActiveForm());
break;
default:
fHandled = fFalse;
}
return fHandled;
}
Word FrmPopupModalForm(Word formID, FormEventHandlerPtr pfnEventHandler)
{
EventType event;
Word err;
PUSH_MODAL_STATE
s_wModalReturnValue = 0;
s_wModalFlags = 0;
// popup form
FrmPopupForm(formID);
// spin event loop
s_fModal = fTrue;
do
{
EvtGetEvent(&event, evtWaitForever);
if (event.eType == frmLoadEvent && event.data.frmLoad.formID ==
formID)
{
FormPtr pfrm;
// load form resource
pfrm = FrmInitForm(formID);
Assert(pfrm);
// activate form
FrmSetActiveForm(pfrm);
// set event handler
FrmSetEventHandler(pfrm, pfnEventHandler ? pfnEventHandler :
DefaultPopupFormHandleEvent);
// set default return value
s_wModalReturnValue = pfrm->defaultButton;
continue;
}
else if (event.eType == appStopEvent)
{
// let the form know that it is being killed
FrmDispatchEvent(&event);
EvtAddEventToQueue(&event);
if (s_fModal)
{
s_fModal = fFalse;
FrmReturnToForm(0);
}
continue;
}
else if ((s_wModalFlags & modalOkShortcut) &&
event.eType == keyDownEvent &&
event.data.keyDown.chr == linefeedChr)
{
event.eType = ctlSelectEvent;
event.data.ctlSelect.controlID = IDC_FORM_OK;
event.data.ctlSelect.pControl = GetObjectPtr(IDC_FORM_OK);
}
if (!SysHandleEvent(&event) && !MenuHandleEvent(0, &event, &err))
FrmDispatchEvent(&event);
ErrorNonFatalDisplayIf(event.eType == frmCloseEvent &&
event.data.frmClose.formID == formID,
"frmCloseEvent should not happen in a modal
form. "
"did you accidentally call
FrmCloseAllForms?");
}
while (s_fModal);
POP_MODAL_STATE
return s_wModalReturnValue;
}