Try OpenEdge Now
skip to main content
GUI for .NET Programming
Creating and Using Forms and Controls : Creating custom .NET forms and controls : Sample ABL-derived .NET non-modal form
 

Sample ABL-derived .NET non-modal form

CurrentTimeForm is a sample ABL-derived non-modal form class that displays as in the following figure.
Figure 5. Non-modal form displayed for CurrentTimeForm.cls
This form displays the current date and time every time you click the Time button and closes when you click the Close button. For information on locating and running this sample, see Example procedures.
Note: In Progress Developer Studio for OpenEdge, you can create ABL-derived non-modal forms to design in Visual Designer. You can initiate creation of a new non-modal form by clicking on File > New > ABL Form.
This is the initial section of code where the class private data and public members are defined.
USING Infragistics.Win.Misc.* FROM ASSEMBLY.
USING System.Windows.Forms.* FROM ASSEMBLY.
CLASS CurrentTimeForm INHERITS Progress.Windows.Form:

  /* Variables for controls on form */
  DEFINE PRIVATE VARIABLE rTimeButton AS CLASS UltraButton NO-UNDO.
  DEFINE PRIVATE VARIABLE rCloseButton AS CLASS UltraButton NO-UNDO.
  DEFINE PRIVATE VARIABLE rDateField AS CLASS UltraLabel NO-UNDO.
  DEFINE PRIVATE VARIABLE dtNow AS DATETIME NO-UNDO.
  
  /* Public properties and methods */
  METHOD PUBLIC VOID DoWait( ):
    WAIT-FOR Application:Run( THIS-OBJECT ).
  END METHOD.

  /* Constructor */
  CONSTRUCTOR PUBLIC CurrentTimeForm( ):
    InitializeComponent( ).
  END CONSTRUCTOR.
This section of code defines object references to the three controls from the Ultra Controls for .NET provided with OpenEdge (see OpenEdge Installed .NET Controls). The public members include the DoWait( ) method, the CurrentTimeForm class constructor.
The DoWait( ) method encapsulates execution of the WAIT-FOR statement to make THIS-OBJECT the main form of the application (see Blocking on non-modal forms). Therefore, if the application that invokes DoWait( ) contains other .NET forms, they are all displayed and their events are processed in the context of this WAIT-FOR statement.
The constructor invokes the private InitializeComponent( ) method to create and initialize the form and its controls.
This section of code is the beginning of the InitializeComponent( ) method.
  /* Private form initialization method */
  METHOD PRIVATE VOID InitializeComponent( ):
  
    /* Creates base form class and all components */
    rTimeButton = NEW UltraButton( ).
    rCloseButton = NEW UltraButton( ).
    rDateField = NEW UltraLabel( ).
    
    THIS-OBJECT:SuspendLayout( ).
    
    /* Initialize current date/time field */
    dtNow = NOW.    rDateField:Text = STRING(dtNow).
    rDateField:Size = TextRenderer:MeasureText( rDateField:Text,
                                                rDateField:Font ).
    rDateField:Top = 20.
    
    /* Initialize the Time button */
    rTimeButton:Text = "Time".
    rTimeButton:Size = TextRenderer:MeasureText( rTimeButton:Text,
                                                 rTimeButton:Font ).
    rTimeButton:Height = rTimeButton:Height * 2.
    rTimeButton:Width = rTimeButton:Width + 12.
    rTimeButton:Top = rDateField:Top + rDateField:Height + 10.
    rTimeButton:Click:Subscribe( TimeButton_Click ).
    
    /* Initialize the Close button */
    rCloseButton:Text = "Close".
    rCloseButton:Size = TextRenderer:MeasureText( rCloseButton:Text,
                                                  rCloseButton:Font ).
    rCloseButton:Height = rTimeButton:Height.
    rCloseButton:Width = rCloseButton:Width + 12.
    rCloseButton:Top = rTimeButton:Top.
    rCloseButton:Click:Subscribe( CloseButton_Click ).
It first instantiates, then initializes all the objects for the form. For example, it assigns an initial current date and time to the Text property of an Infragistics.Win.Misc.UltraLabel control. As part of the initialization, it also sizes the form controls based on their Text and Font settings, and sets initial positions for the controls on the form based on these sizes.
Note: The calculations for control sizes and positions in CurrentTimeForm.cls are convenient for hand coding. The Visual Designer generates hard values that result from the actions you take to design a form visually on the screen.
The initialization for each button also includes a subscription to a corresponding PRIVATE event handler that responds to the Click event on each button (the TimeButton_Click( ) and CloseButton_Click( ) methods, described in a following paragraph).
As a performance enhancement, the method also suspends the publishing of layout events as the form and its control objects are laid out. Applications do not typically handle layout events during form initialization, if at all. So, the SuspendLayout( ) method is often called before initializing any layout logic, especially for forms and control containers that might have many controls laid out within them.
This section of code is the end of the InitializeComponent( ) method.
    /* Initialize the form with its field and buttons */
    THIS-OBJECT:Text = "Current Date and Time".
    THIS-OBJECT:FormBorderStyle = FormBorderStyle:FixedSingle.
    THIS-OBJECT:MaximizeBox = FALSE.
    THIS-OBJECT:Controls:Add( rDateField ).
    THIS-OBJECT:Controls:Add( rTimeButton ).
    THIS-OBJECT:Controls:Add( rCloseButton ).
    THIS-OBJECT:AcceptButton = rTimeButton.
    
    /* Adjust form size and the location for field and button */
    THIS-OBJECT:Width = rDateField:Width * 2.
    THIS-OBJECT:Height = rCloseButton:Top + rCloseButton:Height
                         + rDateField:Height + 40.
    rDateField:Left = ( THIS-OBJECT:Width - rDateField:Width ) / 2.
    rTimeButton:Left = ( THIS-OBJECT:Width - ( rTimeButton:Width + 10
                                               + rCloseButton:Width ) ) / 2.
    rCloseButton:Left = rTimeButton:Left + rTimeButton:Width + 10.

    THIS-OBJECT:ResumeLayout( FALSE ).
  
  END METHOD.
This code initializes the form itself, adds the controls to its control collection, and adjusts the size of the form and the locations of its controls based on the control sizes. Setting the AcceptButton property to the rTimeButton object reference means that pressing the ENTER key clicks the Time button. Finally, the method resumes generation of layout events by calling ResumeLayout( ) on the form, which allows the form layout to take effect.
Concluding the ABL class definition are the PRIVATE event handlers for the form.
  /* Private form event handlers */
  METHOD PRIVATE VOID TimeButton_Click( sender AS System.Object,
                                        e AS System.EventArgs ):
    dtNow = NOW.
    rDateField:Text = STRING(dtNow).
  END METHOD.

  METHOD PRIVATE VOID CloseButton_Click( sender AS System.Object,
                                         e AS System.EventArgs ):
    THIS-OBJECT:Close( ).
  END METHOD.

END CLASS.
The TimeButton_Click( ) event handler method responds to a Click event on rTimeButton by updating the Text property on the UltraLabel control (rDateField) with the most recent date and time. The CloseButton_Click( ) event handler responds to a Click event on rCloseButton by invoking the Close( ) method of the form. This both closes the form and also closes the application because it blocks on THIS-OBJECT as the main form in the application using the DoWait( ) method. (If the form was not displayed as a main form, the application would have to call Application:Exit( ) to terminate the application.)
CurrentTimeFromDriver.p is the sample driver procedure (application) for the CurrentTimeForm sample class.
DEFINE VARIABLE rTimeForm AS CLASS CurrentTimeForm.

rTimeForm = NEW CurrentTimeForm().
rTimeForm:DoWait( ).
After instantiating the sample CurrentTimeForm class, the application simply invokes its public DoWait( ) method to do all the work. While this is a simple example, it shows how an application can be simplified by encapsulating the processing for a .NET form within the ABL-derived form object itself.