Cascaded+ON+CLOSE+handling

//by Richard Russell, September 2010//

The article Cascaded error handling explains how a procedure or function can take some 'local' remedial action in the event of an error (for example to cleanup after a **Windows API** operation) and then pass responsibility for dealing with the error to the code from which it was called. In principle there may be several cascaded procedures or functions, each of which needs to handle the error before passing it 'down the chain'.

A very similar situation can occur when the user closes the window. The procedure or function which is being executed when the **ON CLOSE** event occurs may need to perform some 'local' cleanup operations before the 'global' ON CLOSE handler finally quits the program. Again, in principle there may be several cascaded procedures or functions which each need to handle the ON CLOSE event.

The most elegant way to achieve this is to combine the cascaded ON ERROR and ON CLOSE handling, by allocating an error number (**111** in this example) to the ON CLOSE event. The short program below illustrates this technique; the user is prompted either to press **Escape** (which results in an error) or to click **Close** (which triggers the ON CLOSE event). The code waits in an 'infinite loop' within **PROC2** until one or other of these happens.

After the event is handled in **PROC2** it is passed down to **FN1** and then to **PROC0**; finally the catch-all ON ERROR or ON CLOSE statement in the main program is activated. For the purposes of illustration, the handling of the ON ERROR and ON CLOSE events at each stage consists simply of printing a message to the screen; in a practical example this would be replaced by the necessary cleanup code.

code format="bb4w" PRINT "Click Close to test cascaded ON CLOSE handling" PRINT "Press Escape to test cascaded ON ERROR handling" PRINT ON ERROR PRINT "Error handled in Main: " REPORT$ : END ON CLOSE PRINT "Close handled in Main" : END PROC0 END DEF PROC0 LOCAL dummy ON CLOSE LOCAL ERROR 111, "Close" ON ERROR LOCAL RESTORE LOCAL \ \ IF ERR = 111 PRINT "Close handled in PROC0" : PROCclose ELSE \ \ PRINT "Error handled in PROC0" : ERROR ERR,REPORT$ dummy = FN1 ENDPROC DEF FN1 ON CLOSE LOCAL ERROR 111, "Close" ON ERROR LOCAL RESTORE LOCAL \ \ IF ERR = 111 PRINT "Close handled in FN1" : PROCclose ELSE \ \ PRINT "Error handled in FN1" : ERROR ERR,REPORT$ PROC2 = 1     DEF PROC2 ON CLOSE LOCAL ERROR 111, "Close" ON ERROR LOCAL RESTORE LOCAL \ \ IF ERR = 111 PRINT "Close handled in PROC2" : PROCclose ELSE \ \ PRINT "Error handled in PROC2" : ERROR ERR,REPORT$ REPEAT WAIT 1 UNTIL FALSE ENDPROC DEF PROCclose IF !392 PROC(^@%+392) ELSE QUIT ENDPROC code Note that in a real-world example the final ON CLOSE handler would probably **QUIT** the program. That isn't done here because the displayed output would disappear!

There is a theoretical possibility that an ON CLOSE event could occur //between// the **ON CLOSE** and **ON ERROR** statements in PROC0. In that very unlikely circumstance, the close would be handled as an error. Apart from the user receiving an unexpected message, it should be harmless.