This document covers the following topics:
The execution of the TERMINATE and STOP statements relies on stack-based exception handling in order to immediately abort the application’s execution, which is not guaranteed to work within event-driven (i.e., dialog-based) applications in consumer versions of Windows. In particular, this can be the case where one or more events on the Natural call stack have been synchronously raised in response to the corresponding system event(s). This is because the relevant section of the system call stack in such situations can contain Windows system code that has been compiled with a small performance optimization to not generate the required stack frame information at run-time.
Furthermore, because the Windows system code involved changes over time, a TERMINATE or STOP statement that works on one version of Windows is not guaranteed to continue to work on all later versions, or even on all later Service Packs for the same version.
For these reasons, the use of the TERMINATE and STOP statements in dialog-based applications is discouraged.
A universal solution is not available. However, in many cases, the problem can be circumvented by performing the termination asynchronously. For example, instead of coding a TERMINATE or STOP statement directly, one instead asynchronously invokes a user-defined event for the dialog via the CALL-DIALOG action, and places the TERMINATE or STOP statement within the event handler for the user-defined event, as illustrated in the example below.
In particular, this workaround is applicable in situations where no dialog boxes are active.
Suppose that the CLOSE event for a modeless dialog contains a TERMINATE statement.
/* CLOSE event TERMINATE
This TERMINATE statement fails in some Windows versions in the case where the user attempts to close the dialog via the Close (X) icon.
To solve this problem, we can firstly define a user-defined event for the dialog (e.g., with the name "TERMINATE"), and insert the TERMINATE statement there:
/* TERMINATE event TERMINATE
Secondly, we replace the original TERMINATE statement in the CLOSE event with the following two statements:
/* CLOSE event PROCESS GUI ACTION CALL-DIALOG WITH #DLG$WINDOW NULL-HANDLE 'TERMINATE' FALSE GIVING *ERROR ESCAPE ROUTINE IMMEDIATE
The CALL-DIALOG action with the
FALSE
parameter causes the TERMINATE event to be
executed asynchronously. The ESCAPE
statement by-passes any subsequent event code and is absolutely necessary in
this case to ensure that the DELETE-WINDOW action generated
by the Dialog Editor is not performed, so that the dialog remains active until
the TERMINATE event is received.