Try OpenEdge Now
skip to main content
GUI for .NET Programming
Creating and Using Forms and Controls : ABL support for managing .NET forms and controls : Blocking on non-modal forms
 

Blocking on non-modal forms

You can create non-modal forms from one or more instances of System.Windows.Forms.Form or any derived class. OpenEdge provides the .NET derived class, Progress.Windows.Form, which is specifically designed to work within an ABL session, allowing you either to create non-modal forms directly from this class or to create non-modal forms using ABL classes that you derive from it. To block on one or more non-modal forms, you call one of two overloadings of the static Run( ) method on the .NET System.Windows.Forms.Application class. You can use this method to block on any combination of non-modal .NET forms and ABL windows, and to process all non-GUI ABL events in a session.
This is the syntax for calling the Application:Run( ) method in a .NET WAIT-FOR statement:

Syntax

WAIT-FOR System.Windows.Forms.Application:Run( [form-object-ref] ) .
The form-object-ref is the object reference to one of several non-modal forms that you want to serve as the main form for your application. You can therefore block on non-modal forms by specifying a main form or block without specifying a main form. In both cases, this statement displays and blocks for input on all non-modal forms that you have initialized for display using their respective Show( ) methods or Visible properties (see Preparing to block on .NET forms).
If you specify a main form using form-object-ref, you do not have to set this form to be visible prior to executing the WAIT-FOR statement. In this case, the Application:Run(form-object-ref) method automatically displays the form specified by form-object-ref (sets its Visible property to TRUE). In addition, the Application:Run( ) method returns when this main form is closed by the user. Otherwise, you can programmatically cause the Run( ) method to return by call the Close( ) method on form-object-ref. Calling Close( ) also automatically calls the Dispose( ) method, which allows the form object and all the .NET controls that it contains to be to be garbage collected. For more information on the Close( ) and Dispose( ) methods, see Common .NET public control methods.
Caution: If you block using a main form (form-object-ref), and you have a trigger or event handler containing a loop that processes an ABL READKEY statement, if the user clicks the Close (X) button on the main form during execution of this loop, the session will shut down unconditionally. Therefore, avoid using READKEY statements in any applications that access .NET forms.
For example, this code fragment initializes four form objects and displays them:
USING System.Windows.Forms.* FROM ASSEMBLY.

DEFINE VARIABLE rForm1 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm2 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm3 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm4 AS CLASS Progress.Windows.Form NO-UNDO.

rForm1 = NEW Progress.Windows.Form( ).
rForm2 = NEW Progress.Windows.Form( ).
rForm3 = NEW Progress.Windows.Form( ).
rForm4 = NEW Progress.Windows.Form( ).

rForm1:Text = "Form1".
rForm1:Size = NEW System.Drawing.Size(300, 300).
rForm2:Text = "Form2".
rForm2:Size = NEW System.Drawing.Size(300, 300).
rForm3:Text = "Form3".
rForm3:Size = NEW System.Drawing.Size(300, 300).
rForm4:Text = "Form4".
rForm4:Size = NEW System.Drawing.Size (300, 300).

rForm2:Show( ).
rForm3:Show( ).

WAIT-FOR Application:Run( rForm1 ).

MESSAGE "End of Application" VIEW-AS ALERT-BOX INFORMATION.
When the WAIT-FOR statement executes, it displays the forms referenced by rForm1, rForm2, and rForm3, but not the form referenced by rForm4 because this form has not been made visible.
When you close the main form referenced by rForm1, all other forms displayed for the blocking WAIT-FOR statement also close. In this example, when you click the Close (X) button on the form displayed for rForm1, this calls the Close( ) method on rForm1, and also calls the Close( ) method on rForm2 and rForm3. This is indicated by the fact that the MESSAGE statement displays its message box after all the forms have closed. You can also call the Close( ) method on rForm1 from an event handler to accomplish the same result.
The following example extends the previous example by allowing you to display another form, rForm4, using an event handler for the Click event on rForm1:
USING System.Windows.Forms.* FROM ASSEMBLY.

DEFINE VARIABLE rForm1 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm2 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm3 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm4 AS CLASS Progress.Windows.Form NO-UNDO.

rForm1 = NEW Progress.Windows.Form( ).
rForm2 = NEW Progress.Windows.Form( ).
rForm3 = NEW Progress.Windows.Form( ).

rForm1:Text = "Form1".
rForm1:Size = NEW System.Drawing.Size(300, 300).
rForm2:Text = "Form2".
rForm2:Size = NEW System.Drawing.Size(300, 300).
rForm3:Text = "Form3".
rForm3:Size = NEW System.Drawing.Size(300, 300).

rForm1:Click:Subscribe( "Form1_Click" ).

rForm2:Show( ).
rForm3:Show( ).

WAIT-FOR Application:Run( rForm1 ).

MESSAGE "End of Application" VIEW-AS ALERT-BOX INFORMATION.

PROCEDURE Form1_Click:
  
  DEFINE INPUT PARAMETER sender AS CLASS System.Object NO-UNDO.
  DEFINE INPUT PARAMETER e AS CLASS System.EventArgs NO-UNDO.
  
rForm4 = NEW Progress.Windows.Form( ).
  rForm4:Text = "Form4".
  rForm4:Size = NEW System.Drawing.Size (300, 300).
  rForm4:Show( ).  

END PROCEDURE.
Thus, when you click anywhere in the client area of the form for rForm1 after it displays, rForm4 displays also.
Finally, when you call the Application:Run( ) method without specifying a main form, the WAIT-FOR statement also displays and blocks on all properly initialized non-modal forms. However without a main form, the only way to return from the Application:Run( ) method is to call the Application:Exit( ) method from some event handler or trigger. Note that if you close all the displayed forms, you no longer have a UI affordance with which to terminate the application.
For example, in a variation of the previous example, a handler for the Click event on rForm1 forces a return from the Application:Run( ) method, which also closes any other displayed non-modal forms:
USING System.Windows.Forms.* FROM ASSEMBLY.

DEFINE VARIABLE rForm1 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm2 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm3 AS CLASS Progress.Windows.Form NO-UNDO.
DEFINE VARIABLE rForm4 AS CLASS Progress.Windows.Form NO-UNDO.

rForm1 = NEW Progress.Windows.Form( ).
rForm2 = NEW Progress.Windows.Form( ).
rForm3 = NEW Progress.Windows.Form( ).
rForm4 = NEW Progress.Windows.Form( ).

rForm1:Text = "Form1".
rForm1:Size = NEW System.Drawing.Size(300, 300).
rForm2:Text = "Form2".
rForm2:Size = NEW System.Drawing.Size(300, 300).
rForm3:Text = "Form3".
rForm3:Size = NEW System.Drawing.Size(300, 300).
rForm4:Text = "Form4".
rForm4:Size = NEW System.Drawing.Size (300, 300).

rForm1:Click:Subscribe( "Form1_Click" ).
rForm1:Show( ).
rForm2:Show( ).
rForm3:Show( ).
rForm4:Show( ).

WAIT-FOR Application:Run( ).

MESSAGE "End of Application" VIEW-AS ALERT-BOX INFORMATION.

PROCEDURE Form1_Click:
  
  DEFINE INPUT PARAMETER sender AS CLASS System.Object NO-UNDO.
  DEFINE INPUT PARAMETER e AS CLASS System.EventArgs NO-UNDO.
  
  Application:Exit( ).  

END PROCEDURE.
Note again in this example, if you close the form displayed for rForm1 while the WAIT-FOR statement is blocking, there is no remaining UI affordance with which to exit the application (unless you had similar event handlers on rForm2, rForm3, and rForm4). The only way to terminate the application is to press CTRL+BREAK. So, if you call the Application:Run( ) method without specifying a main form, you need to ensure that your application always calls Application:Exit( ) based on an appropriate user action. Thus, if your application has a main form (for example, an MDI parent form), using the Application:Run( form-object-ref ) method overloading to specify the main form makes multi-form management much easier.