Hi there again,
I've now discovered why FrmSetActiveForm when called prior to FrmDrawForm was
causing a bus error under OS 3.0. I think that it also explains OS 3.5 tolerance of
the same code.
The problem occurs in the context of processing a frmCloseEvent. Here's an event
trace:
1. OS sends frmCloseEvent which invokes my handler. We'll refer here to the active
form as 'close window'.
2. I display a progress message (using the logic below). We'll refer here to the
message form as 'message window'.
3. Having displayed the message (after the FrmSetActiveForm (curFrm); statement),
EnterWindowID refers to 'close window' and ExitWindowID refers to 'message
window'. This makes sense. (EnterWindowID and ExitWindowID are the OS globals
for winExitEvent/winEnterEvent generation)
4. Upon completion of the frmCloseEvent I perform a FrmEraseForm and FrmDeleteForm
of 'close window' (a fairly standard thing to do in a frmCloseEvent).
5. ExitWindowID now refers to 'close window' given that FrmDeleteForm causes this
to be so.
6. Now both EnterWindowID and ExitWindowID refer to 'close window'!
If I had not displayed a progress message then EnterWindowID would refer to nothing
at last step. Thus, to get around the problem I call WinSetActiveWindow with a 0 for
its param. This causes EnterWindowID to be set to zero.
The problem for OS 3.0 then goes away.
I believe that the reason for OS 3.5 not complaining is due to it not sending out
WinEnterEvent/WinExitEvent via WinSetActiveWindow. I have previously reported this
issue and am waiting to hear back. :-)
'hope the above helps.
Kind regards,
Christopher
Christopher Hunt wrote:
> Hi there,
>
> As promised, I'm letting you know of things still not working quite right.
>
> The suggestion of using FrmSetActiveForm in the following manner sort of works
> but there are complications with backwards compatibility:
>
> *****
> curFrm = FrmGetActiveForm ();
> frm = FrmInitForm (waitDialog);
> FrmSetActiveForm (frm);
> FrmDrawForm (frm);
>
> //... do stuff ...
>
> FrmEraseForm (frm);
> FrmDeleteForm (frm);
>
> if (curFrm)
> FrmSetActiveForm (curFrm);
> *****
>
> Calling FrmSetActiveForm prior to FrmDrawForm causes OS 3.0 to crash with a bus
> error.
>
> Here's the sequence of what goes on:
> 1. I call FrmGotoForm and receive a frmCloseEvent.
> 2. In my frmCloseEvent handler I display a progress dialog in accordance with the
> above logic.
> 3. I subsequently continue processing frmCloseEvent and then call FrmEraseForm
> and FrmDeleteForm for the form indicated by frmCloseEvent. There is no
> save-behind for this form; thus FrmEraseForm shouldn't be trying to restore bits
> etc.
> 4. Back in my event loop I get a bus error. The bus error occurs when processing
> winEnterEvent (winExitEvent gets processed ok). The stack trace is:
>
> 00014944 #0000000064 10C3F51A EvtGetEvent+0034
> 00014924 #0000000032 10C58416 WinDisplayToWindowPt+000C
>
> My log file trace also shows that the enter and exit forms are the same (which is
> weird...):
>
> 7783.579: <- EvtGetEvent: winExitEvent Enter: 0x00001b50 Exit: 0x00001b50
> 7783.579: --- System Call 0xA0A9: SysHandleEvent.
> 7783.579: --- System Call 0xA1BF: MenuHandleEvent.
> 7783.579: --- System Call 0xA1A0: FrmDispatchEvent.
> 7783.580: --- System Call 0xA11D: EvtGetEvent.
> 7783.580: --- System Call 0xA1AF: InsPtCheckBlink.
> 7783.580: --- System Call 0xA20D: WinDisplayToWindowPt.
> 7783.580: --- System Call 0xA0F2: ScrSendUpdateArea.
> 7783.580: <- EvtGetEvent: winEnterEvent Enter: 0x00001b50 Exit: 0x00001b50
> 7783.580: --- System Call 0xA0A9: SysHandleEvent.
> 7783.580: --- System Call 0xA1BF: MenuHandleEvent.
> 7783.580: --- System Call 0xA1A0: FrmDispatchEvent.
> 7783.580: --- System Call 0xA11D: EvtGetEvent.
> 7783.581: --- System Call 0xA1AF: InsPtCheckBlink.
> 7783.581: --- System Call 0xA20D: WinDisplayToWindowPt.
>
> However, if I remove the call to FrmSetActiveForm that precedes FrmDrawForm then
> I don't get an error. My concern is that by not having FrmSetActiveForm at that
> point, I might be doing something unorthodox.
>
> The other interesting point to note is that I don't get the bus error under the
> 3.5 debug rom.
>
> Any thoughts?
>
> Kind regards,
> Christopher
>
> Christopher Hunt wrote:
>
> > Thanks David. I had actually sort of tried this before and it crashed (I
> > suspect that it would have for a non-debug ROM also given that the crash was a
> > bus error). One thing that I wasn't doing though was calling FrmSetActiveForm
> > prior to FrmDrawForm. I've now re-compiled and am re-testing. I'll let you
> > know if things go wrong!
> >
> > Kind regards,
> > Christopher
> >
> > David Fedor wrote:
> >
> > > >...do some stuff
> > > >
> > > > mFormSentry = FrmDeleteFormSentry(0); // Calls FrmDeleteForm
> > > > if (mPreviousWinHandle)
> > > > {
> > > > ::WinSetDrawWindow(mPreviousWinHandle);
> > > > ::WinSetActiveWindow(mPreviousWinHandle); // THIS BIT HAS HAD TO BE
> > > >ADDED
> > > > }
> > >
> > > Instead of calling the two Window manager routines, just call
> > > FrmSetActiveForm() giving it the previously active form (if any).
> > > Otherwise you have activated a window without the form manager knowing
> > > about it. FrmSetActiveForm() does a bunch of stuff, including restoring
> > > the previous bits, letting the Graffiti shift indicator know what's going
> > > on, sets focus appropriately...
> > >
> > > So your code, in order to cleanly put up a form over something and then
> > > take it back down again, without going through the normal event loop
> > > mechanisms, should look like this:
> > >
> > > curFrm = FrmGetActiveForm ();
> > > frm = FrmInitForm (waitDialog);
> > > FrmSetActiveForm (frm);
> > > FrmDrawForm (frm);
> > >
> > > //... do stuff ...
> > >
> > > FrmEraseForm (frm);
> > > FrmDeleteForm (frm);
> > >
> > > if (curFrm)
> > > FrmSetActiveForm (curFrm);
> > >
> > > (This was in fact taken from the way that the launcher does its "Please
> > > wait" dialog.)
> > >
> > > As for why it used to work - well, it would sort of have worked, except for
> > > all the other things that FrmSetActiveForm() would have done. Yet another
> > > reason to use the debug 3.5 roms, since they help you catch great things
> > > like this, as you've just found! I bet that running your app on a release
> > > 3.5 rom would have worked as before, right?
> > >
> > > -David Fedor
> > > Palm Developer Support
>
> --
> Christopher Hunt
> Class Action Pty. Ltd.
--
Complete time zone management for the Palm(tm) connected organizer.
Check out http://www.classactionpl.com/