WAIT-FOR statement (.NET and ABL)
(Windows only; GUI for .NET only)This WAIT-FOR statement instructs the AVM to stop executing the current block and remain in a wait state (blocking) until a .NET method that it calls returns. The AVM continues to respond to all incoming ABL events (see the WAIT-FOR statement (ABL only) reference entry) as well as .NET events, and it executes any associated triggers, event procedures, or .NET event handlers while in this wait state.
Note: ABL supports a separate version of the WAIT-FOR statement (ABL WAIT-FOR) that blocks only for ABL events. For more information, see the WAIT-FOR statement (ABL only) reference entry.Syntax
object-reference
A reference to an object that generally inherits from the .NET classSystem.Windows.Forms.Form
orSystem.Windows.Forms.CommonDialog
. OpenEdge provides a particular subclass ofSystem.Windows.Forms.Form
—the Progress.Windows.Form class—which you can use to create .NET forms in an ABL session that co-exist more naturally with ABL windows.type-name
method-name
parameters
SETreturn-value
Provides the return value from the method,method-name
( ), which is set when the WAIT-FOR statement completes execution. Thereturn-value
can be a variable, property, or field that has the same data type as themethod-name
( ) return value, typicallySystem.Windows.Forms.DialogResult
.To use this option,method-name
( )
must be a non-VOID method. If you specify this option for a VOID method, such asSystem.Windows.Forms.Application:Run( )
, ABL raises a compile-time error.For more information on .NET input-blocking methods that you can call in the WAIT-FOR statement, see the notes of this reference entry.
ExampleThe ABL-derived .NET class,
r-WaitForms
, inherits the Progress.Windows.Form class to implement a non-modal .NET form. When you try to close the displayed form, a dialog box appears that prompts if you want the form to complete closing or not. If you choose to complete closing, the form closes. If you choose to cancel the closing, the form remains displayed, and you can try to close the form, again.When you instantiate
r-WaitForms
, it initializes and subscribes a handler (theForm_Closing( )
method) to theFormClosing
event of the form. You can then display the form by calling theDoWait( )
method on ther-WaitForms
instance. This method executes the WAIT-FOR statement, which calls the .NET input-blocking methodSystem.Windows.Forms.Application:Run( )
. (For more information on this method, see the notes.) When you try to close the displayed form, this causes the non-modal form to publish itsFormClosing
event, which executes theForm_Closing( )
method to handle the event.
The
Form_Closing( )
method passes INPUT parameters from .NET for theFormClosing
event. One of these parameters (e
) is aSystem.Windows.Forms.FormClosingEventArgs
object, which contains a Cancel property whose setting allows the event handler to either complete theFormClosing
event or interrupt and cancel theFormClosing
event. To determine how to set this property, the event handler instantiates, initializes, and displays another Progress.Windows.Form class (rDialog
) as a modal dialog box.The dialog box contains two buttons,
rOKButton
andrCancelButton
, whoseDialogResult
properties are set to theSystem.Windows.Forms.DialogResult
enumeration values OK and Cancel, respectively. The event handler displaysrDialog
as a modal form by executing the WAIT-FOR statement, which calls the modal input-blocking methodSystem.Windows.Forms.Form:ShowDialog( )
. (For more information on this method, see the notes.)When you click one of the two dialog buttons, this causes the dialog box to close and the
ShowDialog( )
method to return. This automatically sets theDialogResult
property onrDialog
to the value of theDialogResult
property on the button that you have clicked and also returns the same property value as the value ofShowDialog( )
, which the WAIT-FOR statement assigns to the variable,enDialogResult
. The event handler then uses the staticAreEqual( )
method on the Progress.Util.EnumHelper class to test the value ofenDialogResult
and set thee:Cancel
property to either complete theFormClosing
event or cancel theFormClosing
event and leave the non-modal form open for further input. TheDispose( )
method call at the end of the event handler is required to allow the modal form object to be garbage collected (see the notes).Note: The calls toSystem.Windows.Forms.MessageBox:Show( )
display a message box similar to the ABL MESSAGE statement with the VIEW-AS ALERT-BOX option.To instantiate
r-WaitForms
and display the non-modal form, you can thus run a procedure with code like this:
Notes
- If you use any .NET forms in an ABL session, you can execute only one .NET WAIT-FOR statement that processes events for all .NET non-modal forms and their controls. This statement must be the first WAIT-FOR statement for processing non-modal events in your application. Following this statement, from event handlers and trigger blocks, you can execute multiple input-blocking statements to process any modal .NET form or ABL dialog box. ABL events for non-modal windows and their child widgets, or for non-GUI ABL features, such as asynchronous remote procedure calls and socket operations, all work in the context of this single non-modal .NET WAIT-FOR statement.
Caution: Using stacked input-blocking statements other than for dialog boxes is not recommended. If you do so, you must take special care to ensure that any WAIT-FOR statements that you simultaneously execute to process non-modal events complete their execution in reverse order of invocation. Otherwise, your application will have unpredictable behavior.- To block on any number of non-modal .NET forms (and ABL windows), you must use a WAIT-FOR statement that executes the
System.Windows.Forms.Application:Run( )
input-blocking method (as shown for the example class,r-WaitForms
):
You can specifyform-object-ref
as an object reference to a single .NET non-modal form object, on which the WAIT-FOR statement blocks, displays, and waits to close. If you specifyform-object-ref
, the statement also displays any additional non-modal forms that you have previously initialized by setting their Visible properties to TRUE or by invoking theirShow( )
methods. However, .NET automatically displaysform-object-ref
, itself, without having to set its Visible property or run itsShow( )
method. You can also use triggers, event procedures, and .NET event handlers to create and display additional non-modal .NET forms (or ABL windows) after the WAIT-FOR statement blocks for events.The conditions for unblocking this WAIT-FOR statement differ, depending on whether you specifyform-object-ref
. However, whatever conditions unblock the WAIT-FOR statement also automatically close any open .NET forms. This is different from ABL windows, which you must explicitly open and close using ABL statements or widget attributes without regard to the execution of a WAIT-FOR statement.Withform-object-ref
, the WAIT-FOR statement unblocks and continues execution with the following statement if one of the following actions occurs:
- Your application explicitly calls the
form-object-ref
:Close( )
method, which automatically calls theDispose( )
method to garbage collect the form.- The user clicks the form Close (
X
) button in the upper right corner of theform-object-ref
form, and you do not cancel the action in a handler for theFormClosing
event, as in the example. This action also automatically calls theform-object-ref
:Close( )
method.- Your application calls the
System.Windows.Forms.Application:Exit( )
method.When you use any of these techniques to unblock the WAIT-FOR statement, all currently displayed non-modal forms close, in addition to the form specified byform-object-ref
, and including any non-modal .NET forms that were created and displayed after the WAIT-FOR statement blocked.Caution: If you are executing the READKEY statement within a trigger or event handler while blocking on aform-object-ref
, and the user clicks the form Close (X
) button, the ABL application shuts down unconditionally. For example, the following READKEY loop can cause this shutdown to occur:This shutdown occurs because .NET generates a WM_QUIT message in response to clicking the Close (
DO WHILE LASTKEY != KEYCODE("F3"):
READKEY.
IF LASTKEY = KEYCODE("F3") THEN RETURN.
END.X
) button that READKEY interprets (by design) as a message to shut down the application.Caution: You might have a problem displaying message boxes after invokingApplication:Exit( )
orApplication:ExitThread( )
. One way this can happen: if you use any two of the techniques for unblocking the WAIT-FOR, such as by callingClose( )
, then callingApplication:Exit( )
, any subsequent executions of the MESSAGE statement with the VIEW-AS ALERT-BOX option or any subsequent calls toSystem.Windows.Forms.MessageBox:Show( )
might not display the specified message box and the user will hear a beep sound instead.If you do not specifyform-object-ref
, the statement displays and blocks for input on any non-modal forms that you have previously initialized by setting theirVisible
properties to TRUE or by invoking theirShow( )
methods. Withoutform-object-ref
, you also do not need to have a .NET form instantiated before you execute the WAIT-FOR statement. Without any non-modal .NET form created, this statement processes ABL events until you create and initialize your first .NET non-modal form for display in an associated event handler or trigger, at which point the same WAIT-FOR statement processes both .NET and ABL events.Also, if you do not specifyform-object-ref
, the WAIT-FOR statement unblocks and continues execution with the following statement only when you invoke theSystem.Windows.Forms.Application:Exit( )
method at some point in the ABL session. This method closes all non-modal .NET forms that are currently open before unblocking the WAIT-FOR statement. Note that using this technique, you must be sure to create and initialize at least one .NET form or ABL window (non-modal or modal) so there are active components to work with during the input-blocking state. Otherwise, the blocking WAIT-FOR statement blocks indefinitely or until the user presses CTRL+BREAK.Note: When working with any displayed non-modal form, except the form specified byform-object-ref
, the user (using the Close (X
) button) or the application (using theClose( )
method) can close the form. However, this does not by itself unblock the blocking WAIT-FOR statement. If you want the WAIT-FOR to unblock other than by closing the form specified byform-object-ref
, your application must callApplication:Exit( )
.- To block on a .NET modal dialog box, you must use a WAIT-FOR statement that executes the
ShowDialog( )
input-blocking method on the specified form object (as shown forrDialog
in the example class,r-WaitForms.cls
):
This causes the WAIT-FOR statement to display the form specified by thedialog-object-ref
object reference, and block for input on that form as a dialog box. You can also specify the object reference of a form (parent-form
) that becomes the parent of the dialog box referenced bydialog-object-ref
. (This allows the .NET dialog box to to display centered over the parent form.)Note that by convention, every .NET class that can implement a modal dialog box has aShowDialog( )
method, such asSystem.Windows.Forms.Form
andSystem.Windows.Forms.CommonDialog
, as well as classes that derive from them, likeSystem.Windows.Forms.OpenFileDialog
. Therefore, this syntax for the WAIT-FOR statement allows you to open all these different types of dialog boxes.Note: TheSystem.Windows.Forms.MessageBox
class does not work this way. Instead, it is similar to the MESSAGE statement with the VIEW-AS ALERT-BOX option, which handles its own input without events. Similarly, you can only open aMessageBox
by invoking its staticShow( )
method outside of a WAIT-FOR statement.Withdialog-object-ref
:ShowDialog( )
, the WAIT-FOR statement unblocks and continues execution with the following statement if one of the following actions occurs:
- The user clicks the dialog box Close (
X
) button in the upper right corner of the dialog box.- You set the
dialog-object-ref
:DialogResult
property (if the form class supports it) to a validSystem.Windows.Forms.DialogResult
enumeration value.- You call the
dialog-object-ref
:Close( )
method. Note that calling this method also automatically calls theDispose( )
method on the form, making the form object available for garbage collection.For any of these actions, theFormClosing
andFormClosed
events are also published ondialog-object-ref
, and you can handle theFormClosing
event in order to prevent the form from being closed by cancelling the action, as shown in the example.Caution: Unlike for non-modal forms, when the user clicks the Close (X
) button on a dialog box, or when you set the value of thedialog-object-ref
:DialogResult
property, the .NET Framework does not automatically call theClose( )
method ondialog-object-ref
and therefore does not also call theDispose( )
method. Instead, .NET hides the form so it can be shown again without creating a new instance of the dialog box. Because of this behavior, when the form is no longer needed by your application, you must call thedialog-object-ref
:Dispose( )
method to enable garbage collection for the form and all the .NET controls that it contains.
If the form contains any ABL-derived controls (including any ABL-derived control containers, such as user controls), those controls will also not be garbage collected until you callDispose( )
, because the form itself is still holding a reference to them. Thus, callingDispose( )
on the modal form also causesDispose( )
to be called on these ABL-derived controls, which enables them for garbage collection, again, as long as there are no other references to them in the ABL session.At this point, you can check the user response to the dialog box. Note thatShowDialog( )
returns aDialogResult
(enumeration) value with the result of the dialog box. You can access this value using the SET option (as shown in ther-WaitForms.cls
example) or by checking thedialog-object-ref
:DialogResult
property (if the form object is still available and the class supports it).Note: Not all .NET form classes provide a publicDialogResult
property—for example,System.Windows.Forms.FileDialog
. For a form that does not provide this property, you can handle dialog box results in the following ways: 1) by using the SET option to return the form’sShowDialog( )
method value, 2) by using event handlers subscribed to the events that the form provides, for example, theFileOk
orHelpRequest
event, or 3) by testing the values of properties that might otherwise be set depending on input to the dialog box, such as theFileName
property of theSystem.Windows.Forms.OpenFileDialog
object..NET does not set thedialog-object-ref
:DialogResult
property automatically except in two cases:
- The user clicks the dialog box Close (
X
) button in the upper right corner, which sets the property to theDialogResult:Cancel
enumeration value.- The user clicks a button (or any control that implements the
System.Windows.Forms.IButtonControl
interface) contained by the dialog box whoseDialogResult
property you have set with a validDialogResult
enumeration value. In this case, .NET automatically sets thedialog-object-ref
:DialogResult
property to the value of the button property.Otherwise, your application must set the value ofdialog-object-ref
:DialogResult
directly, typically in an event handler. Note that if you want .NET to automatically set thedialog-object-ref
:DialogResult
property from a buttonDialogResult
property, your application must initialize theDialogResult
value for the button property before the user clicks a given button.- You can detect that a specific form is closing by handling its
FormClosing
event; you can detect that a specific form has already closed by handling itsFormClosed
event. However, note that theClosed
event does not fire for non-modal .NET forms that you close by callingApplication:Exit( )
and that are not specified by theform-object-ref
parameter passed to theApplication:Run( )
method.Caution: Do not delete the ABL object reference to the object (sender) that publishes aFormClosing
event from within itsFormClosing
event handler. This causes theFormClosing
event to be published a second time. If you need to delete the sender for an event that is associated with closing a form before the AVM garbage collects it, execute the DELETE OBJECT statement for the sender within a handler for itsFormClosed
event.Note: .NET supports aClosing
andClosed
event on forms. However, use theFormClosing
andFormClosed
events, instead, because they work better.- If you specify a non-blocking method in a WAIT-FOR statement, the method executes and the WAIT-FOR immediately returns, resuming execution with the next available statement. ABL does not prevent this. However, the WAIT-FOR statement, in this case, works no differently than invoking the method as a statement by itself.
Note: Progress Software Corporation recommends that you do not invoke non-blocking methods using the WAIT-FOR statement.- The one WAIT-FOR statement that you execute for non-modal .NET forms after setting their
Visible
properties to TRUE or by invoking theirShow( )
methods, must call theApplication:Run( )
method to make the forms visible and usable. If you execute any other form of the WAIT-FOR statement after making non-modal .NET forms visible, such as one that blocks for an ABL event (even a developer event, such as U1 OF THIS-PROCEDURE), the ABL virtual machine (AVM) raises STOP on this WAIT-FOR statement.- You cannot set the
Visible
property or call theShow( )
method on a modal .NET form before executing a WAIT-FOR statement on theShowDialog( )
method. If you execute a WAIT-FOR statement that calls theShowDialog( )
method on a modal .NET form that you have previously made visible, .NET raises a run-time exception.- Once you execute a non-modal WAIT-FOR statement that calls the
Application:Run( )
method, the statement goes into a wait state that allows any event handlers or triggers to run in response to all types of ABL-supported events, including .NET events, ABL UI events, and ABL non-UI events (such as socket events). In the associated event handlers or triggers, you can then create and display additional .NET non-modal forms (by setting theirVisible
properties or invoking theirShow( )
methods) or ABL non-modal windows (for example, by setting their VISIBLE attributes to TRUE, executing DISPLAY statements, or executing a VIEW statement), and the existing WAIT-FOR statement processes events associated with these new non-modal .NET forms or ABL windows in addition to any other events it is already processing. To open modal dialog boxes (.NET or ABL) from an event handler or trigger, you must execute an additional WAIT-FOR statement for each dialog box that you open. Each such WAIT-FOR statement then blocks until its associated modal dialog box is closed, allowing the event handler or trigger that invoked the statement to resume execution.- .NET does not support blocking for multiple non-modal forms simultaneously at more than one point in an application. If you attempt to execute more than one non-modal WAIT-FOR statement that calls
Application:Run( )
by invoking a second such WAIT-FOR statement in an event handler or trigger, .NET raises an exception, which in turn raises STOP on this second WAIT-FOR statement.Caution: After you execute an additional WAIT-FOR statement that callsApplication:Run( )
, even if you trap the STOP condition with ON STOP, .NET does not allow another call toApplicaton:Run( )
in the same session. You must exit the ABL session and fix the application to avoid such simultaneous calls toApplicaton:Run( )
.- You must execute a separate WAIT-FOR statement for each modal .NET dialog box or ABL dialog box that you open. The modal nature of each dialog box guarantees that the corresponding WAIT-FOR statements unblock and resume execution with the statements that follow them in order of the most recently opened dialog box. However, while blocking on any .NET or ABL modal dialog box, you cannot then execute a non-modal WAIT-FOR statement calling
Application:Run( )
, even if no previous non-modal WAIT-FOR statement is still in a wait state. Attempting to call a non-modal WAIT-FOR statement while any modal .NET dialog box or ABL dialog box is open raises a run-time error.- If you add non-modal .NET forms to an existing ABL application that already contains WAIT-FOR statements to process non-modal ABL GUI and non-GUI events, replace these WAIT-FOR statements (except those that block on ABL modal dialog boxes) with a single WAIT-FOR statement that calls
Application:Run( )
. In order to have an active .NET form in your application, you must execute your latest (and usually only)WAIT-FOR
statement in the format that calls a .NET input-blocking method (for example, waiting onApplication:Run( )
) so that it is in effect to process .NET events. This allows the application to handle the same ABL events after adding .NET forms that it handled before you added the .NET forms.- You cannot use the APPLY statement to force a WAIT-FOR statement that is blocking on .NET forms to unblock and continue execution with the statement following the WAIT-FOR statement. Instead, call the appropriate .NET method (for example,
Close( )
orApplication:Exit( )
) to unblock the WAIT-FOR statement and continue with the next statement.- To handle a particular .NET event while the WAIT-FOR statement that processes the event is executing, you must subscribe a .NET event handler to the specified event using the Subscribe( ) event method before the event is raised. For more information on event methods and event handlers for .NET events, see the "Class Events Reference" section.
- If an ABL handler for a .NET event raises an unhandled error condition or throws an error object out of the handler, the AVM does not throw a .NET
Exception
back to the .NET Common Language Runtime (CLR), but displays a message to the default output device and continues blocking for events.- You cannot invoke the non-modal .NET
System.Windows.Forms.Application:Run( )
method or the .NETShowDialog( )
method used to display a modal dialog box in any ABL context other than in a WAIT-FOR statement. Any attempt to do so raises a run-time error.See alsoType-name syntax, USING statement, WAIT-FOR statement (ABL only)
OpenEdge Release 10.2B
|