TechTricks
Technical answers from the trenches 
 
 
 
 

     
   
Providing Consistent Exits from your Forms
 
   
by Lance Leonard 
 Posted: 13 July 2000
 
   
 
 Applies to: All Versions
 
   
 
Audience: Beginner
 
       
   

Introduction

Consistency 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 )
The other button is labelled Cancel and, as you might expect, its pushButton() event contains the following code:
   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 open
It 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:

  • Clicking the little [X] button in the upper, right corner of the dialog.
  • Double-clicking the Control menu.
  • Dropping the Control menu and then choosing Close.
  • Pressing <Ctrl+F4>.

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:

  • Executes only when the form is the object generating the menu action.
  • Only executes when the action that triggered the event is one that closes the form.
  • Blocks the default behavior of the menuControlClose() action by setting an error code that prevents that behavior from taking place. (The default behavior, of course, being whatever is required to close a form.)
  • Overrides the default behavior by triggering the pushButton() event on your Cancel button.
  • Assumes you've named your Cancel button btnCancel.

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.

Summary

Remember, 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.

 

       

Top

Feedback About Paradox Delphi Assorted Web Stuff
 
 
Copyright © 2000-2004, techtricks.com; All Rights Reserved.
Acknowledgements, Disclaimers, Terms and Conditions.
Article last updated on 14 June 2003

 

Other Sites: Paradox, Delphi, Perl, Web Stuff, and More


 

[- End -]