|
Technical answers from the trenches |
|
Providing Consistent Exits from your Forms
| ||||
by Lance Leonard |
Posted: 13 July 2000 |
|||
  |
Applies to: All Versions |
|||
  |
Audience: Beginner |
|||
IntroductionConsistency is said to be the hobgoblin of little minds. This may be true, but it offers certain advantages for Paradox developers. Strive to design your applications so they always behave in predictable ways, regardless of (or perhaps, in spite of) your users' actions. By doing so, you'll find you'll reduce the number of surprises encountered while you maintain and support your applications. This article demonstrates this by showing how a simple user action can trip up the most carefully designed application. It also shows how to create forms that behave more consistently when users exit them. In turn, this makes the code that calls these forms easier to develop and maintain.
Here's the scenario: Suppose you've just designed a dialog box for your application. You've included two buttons. One is labelled OK and contains the following code in its pushButton() event: doDefault ; do the button animation formReturn( TRUE ) doDefault ; do the button animation formReturn( FALSE ) When incorporating this dialog into an application, many Paradox developers use something along these lines:
var
frm Form
endVar
frm.open( "MYDIALOG" )
if frm.wait() then
doSomething()
endIf
frm.close()
The expectation is, of course, that the doSomething() code is executed when the user exits by clicking the OK button. After deploying this, though, you get a frantic call from the user saying that they received the following error You have tried to access a document that is not openIt gets worse. You try it out on your machine and it works fine. You ask the user what they did to trigger the error and they say something to the effect of "I just closed it." You're ready to pull your hair out, right? In this case, the form was probably closed in one of the following ways:
The error is being triggered on the frm.close() line, the one that closes the form when you're finished with it. Look back at the code, which clearly expects the user to exit the wait loop by closing the form with either the OK or Cancel button. Unfortunately, every action in the above list ends the wait loop and closes the form. Your carefully crafted pushButton code is not called. This also means that the frm variable no longer points to a valid form at the end of the wait() loop. Thus, the frm.close() line triggers an error. In other words, the user did something that you didn't plan or code for. (Users, clients, and project sponsors tend to do that.) To resolve this, you need to override this behavior and add code that manages the form consistently. If you're new to Paradox and ObjectPAL, you may be getting a little nervous. After all, that's four more places you need code on your dialog box, right? Not necessarily. The designers of Paradox realized that while supporting multiple ways to close a form (and perform other actions) is great for end-users, it's a royal pain for developers. To deal with situations like this, Paradox translates a great many user activities into actions and menuActions, which can be trapped (and overridden) in the action() and menuAction() events, respectively. If you add the following code to the menuAction of your dialog's Form object, you can override the exits generated by these and a few other actions:
if not eventInfo.isPreFilter() then
if eventInfo.id() = menuControlClose then
eventInfo.setErrorCode( userError )
btnCancel.pushButton()
endIf
endIf
If you are new to Paradox and/or ObjectPAL, the above code:
This forces these actions to behave as if the user has clicked the Cancel button in the first place. In turn, this lets your original code run unchanged. Note: There is an alternate approach, one that is a good idea even if you override the menuControlClose menuAction. Specifically, change your calling code to something along these lines:
var
frm Form
endVar
frm.open( "MYDIALOG" )
if frm.wait() then
doSomething()
endIf
try
frm.close()
onFail
; do nothing; it's already closed
endTry
In this case, a Try/OnFail block overrides the way Paradox handles the error that occurs. Instead of displaying the error, nothing happens. In most cases, you will want error messages to appear because they indicate situations that you've not handled in your code. In this single instance, though, it is an effective hack. Keep in mind that this is a hack, for it works around the problem. The menuAction approach is far superior because it prevents the problem from occurring in the first place. It's a subtle, but important distinction. SummaryRemember, Paradox is just a computer program. It does not infer from the context, it only follows instructions. More often than not, unexpected program behavior is the result of Paradox doing precisely what you told it to. Your job, as a developer, is to provide an environment where it can consistently operate the way you intend it to. In doing so, you'll find fewer hobgoblins bedevilling you. |
|||
|
||||||||
|
Copyright © 2000-2004, techtricks.com; All Rights Reserved. Acknowledgements, Disclaimers, Terms and Conditions. |
||||||||
|
Article last updated on 14 June 2003
|
||
|
|
||
|
[- End -]
|