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 MDI form

Sample ABL-derived .NET MDI form

MDIForm is a sample ABL-derived non-modal MDI form class. This form displays an MDI window as in the following figure, with standard menus, a toolbar, and status bar.
Figure 8. MDI form displayed for MDIForm.cls
Some of the menu functions have associated behavior. For example, when you click the File > New menu item (or its toolbar button) this opens a child non-modal form in the client area of the parent MDI form, and you can open as many child forms this way as you want. You can then manipulate the child forms within the MDI client area in the typical manner of a multiple document interface. When you click the File > Open menu item (or its toolbar button), this opens the standard .NET open file dialog box. The sample implementation allows you to select a file and click the Open button, which closes the dialog box, but does not actually open the specified file. Other menu functions (not documented here) have no behavior or varying types of sample behavior similar to the New and Open functions.
Note: In Progress Developer Studio for OpenEdge, you can create ABL-derived non-modal MDI forms to design in Visual Designer. You can initiate creation of a new non-modal MDI form by clicking on File > New > ABL MDI Form.
The MDIForm.cls file also has an MDIForm.resx resource file associated with it, which provides the icon images used in the form. For more information on accessing resource files, see Accessing resource files for .NET forms.
You can launch this sample MDI form using the sample procedure, MDIFormDriver.p. For information on locating and running these samples, see Example procedures.
The MDIForm class contains a relatively large amount of sample code. So, the following description focuses on the code for the previously described New and Open menu functions. In general, the basic initialization of a standard MDI form includes a hierarchy of control containers and controls, starting with the MDI parent form, and continuing with a container for the menus, a separate container for the menu items of each menu, and a container for the buttons in each toolbar.
Thus, this description provides an overview of the entire MDIForm class, with a focus on the form menu container (a System.Windows.Forms.MenuStrip), the File menu container (a System.Windows.Forms.ToolStripMenuItem), and the New and Open menu items (also a System.Windows.Forms.ToolStripMenuItem). So, each menu and its menu items represents a hierarchy of System.Windows.Forms.ToolStripMenuItem instances. (The related toolbar is contained by a System.Windows.Forms.ToolStrip not described, here.)
This is the initial section of code for the ABL MDIForm class, where the class private data is defined.
USING System.ComponentModel.* FROM ASSEMBLY.
USING System.Windows.Forms.* FROM ASSEMBLY.
USING Progress.Windows.* FROM ASSEMBLY.

CLASS MDIForm INHERITS Progress.Windows.Form:

  DEFINE PRIVATE VARIABLE components AS System.ComponentModel.IContainer
  DEFINE PRIVATE VARIABLE resources AS System.Resources.ResXResourceSet
                          System.Windows.Forms.OpenFileDialog NO-UNDO.
                          System.Windows.Forms.SaveFileDialog NO-UNDO.
  DEFINE PRIVATE VARIABLE menuStrip AS System.Windows.Forms.MenuStrip
  DEFINE PRIVATE VARIABLE toolStrip AS System.Windows.Forms.ToolStrip
  DEFINE PRIVATE VARIABLE statusStrip AS System.Windows.Forms.StatusStrip
                          System.Windows.Forms.ToolStripMenuItem NO-UNDO.
. . .
  DEFINE PRIVATE VARIABLE printPreviewToolStripButton AS
                          System.Windows.Forms.ToolStripButton NO-UNDO.
                          System.Windows.Forms.ToolStripButton NO-UNDO.
  DEFINE PRIVATE VARIABLE toolTip AS System.Windows.Forms.ToolTip NO-UNDO.
The private data includes definitions for all the object references used by the form. Note especially the resources object reference defined to reference the contents of the MDIForm.resx file, the openFileDialog object reference defined to reference the open file dialog box that is launched using the Open menu item, the menuStrip object reference defined to reference the menu container, and the fileMenu object reference defined to reference the File menu container. The childFormNumber is used to provide an incremental number displayed in the title bar of each child form opened using the New menu function.
After its private data, MDIForm defines its public members.
    WAIT-FOR System.Windows.Forms.Application:Run (THIS-OBJECT).

    InitializeComponent ( ).
The public members include the DoWait( ) method to run the form's WAIT-FOR statement and the MDIForm class constructor. Note that in DoWait( ), THIS-OBJECT is passed as a parameter to the Applicaton:Run( ) method. This allows the MDI form to function as the main form of the application, allowing the MDI form and its child form objects to be managed more tightly as a unit, for example, so they are more easily closed together (shown further on in the sample code).
Also as is typical of ABL form container classes, the constructor calls an InitilizeComponent( ) method to create and initialize most of the objects used for the form. This includes all the controls and control containers for the form.
The following shows code sections from the beginning of the InitializeComponent( ) method. This starts by creating the objects for the MDI parent form, including the menu container (menuStrip), the File menu (fileMenu), and continues (not shown) for all the remaining control and control container objects used by the form. This code also loads the image resources from the MDIForm.resx file into a new resource object (resources). For performance reasons, the initialization code then suspends layout events for each of the control containers, including the MDI parent form, itself (THIS-OBJECT).
  METHOD PRIVATE VOID InitializeComponent ( ):

    resources = ResourceHelper:Load("MDIForm.resx", PROPATH).
    components = NEW System.ComponentModel.Container( ).
    menuStrip = NEW System.Windows.Forms.MenuStrip( ).
    fileMenu = NEW System.Windows.Forms.ToolStripMenuItem( ).
    . . .
    menuStrip:SuspendLayout( ).
    toolStrip:SuspendLayout( ).
    statusStrip:SuspendLayout( ).
    THIS-OBJECT:SuspendLayout( ).

    /* menuStrip */
    DEFINE VARIABLE arrayvar1 as System.Array no-undo.
    arrayvar1 = System.Array:CreateInstance
      (TypeHelper:GetType("System.Windows.Forms.ToolStripItem"), 6).
    arrayvar1:SetValue(fileMenu, 0).
    arrayvar1:SetValue(editMenu, 1).
    arrayvar1:SetValue(viewMenu, 2).
    arrayvar1:SetValue(toolsMenu, 3).
    arrayvar1:SetValue(windowsMenu, 4).
    arrayvar1:SetValue(helpMenu, 5).
    menuStrip:Items:AddRange( CAST (arrayvar1,
                              "System.Windows.Forms.ToolStripItem[]") ).
    menuStrip:Location = NEW System.Drawing.Point(0, 0).
    menuStrip:MdiWindowListItem = windowsMenu.
    menuStrip:Name = "menuStrip".
    menuStrip:Size = NEW System.Drawing.Size(632, 24).
    menuStrip:TabIndex = 0.
    menuStrip:Text = "MenuStrip".

    /* fileMenu */
    DEFINE VARIABLE arrayvar2 as System.Array no-undo.
    arrayvar2 = System.Array:CreateInstance
      (TypeHelper:GetType("System.Windows.Forms.ToolStripItem"), 11).
    arrayvar2:SetValue(newToolStripMenuItem, 0).
    arrayvar2:SetValue(openToolStripMenuItem, 1).
    . . .
    arrayvar2:SetValue(exitToolStripMenuItem, 10).
    fileMenu:DropDownItems:AddRange( CAST (arrayvar2,
                                  "System.Windows.Forms.ToolStripItem[]") ).
      = System.Drawing.SystemColors:ActiveBorder.
    fileMenu:Name = "fileMenu".
    fileMenu:Size = NEW System.Drawing.Size(35, 20).
    fileMenu:Text = "&File".
The first control container to be initialized is the menu container (menuStrip), a MenuStrip object. This follows a typical pattern for all control containers in the form. First, it creates an object array to hold instances of the control type used in the control container, in this case for six (6) instances of System.Windows.Forms.ToolStripItem., representing the six menus on the MDI form menu bar. It then loads the array with the previously created menu objects, starting with the File menu (fileMenu) and ending with the Help menu (helpMenu). It adds this array of ToolStripItem instances to the ToolStripCollection (Items property) of the menuStrip object. It then sets a number of other properties on the menuStrip object, including the MdiWindowListItem property, which is set to the object representing the Windows menu, which lists all of the child forms that are open in the MDI parent client area. Note that the array contents, as reference type objects, remain instantiated when InitializeComponent( ) terminates because they are still referenced in ABL as well as by the menuStrip object to which they are added. The code initializes all of the remaining top-level control containers in the MDI form in a similar manner.
The control container for the File menu (fileMenu) is initialized in a similar manner. In this case, the menu is represented by a ToolStripMenuItem object, which is itself a container for other ToolStripMenuItem objects (File menu items). The code adds these objects to the corresponding object array, starting with the newToolStripMenuItem and openToolStripMenuItem objects, which represent the New and Open menu items. In this case, the object array is added to the ToolStripCollection of the fileMenu object specified by its DropDownItems property. Again, the code sets properties on the fileMenu control container. Note the setting of the Text property, which uses the "&" character to indicate the menu shortcut. The code initializes all of the remaining menus across the menu bar of the MDI form in a similar manner.
The next object to be initialized (shown in the following code section) is the ToolStripMenuItem object (newToolStripMenuItem) that implements the New item in the File menu.
    /* newToolStripMenuItem */
      = CAST( resources:GetObject("newToolStripMenuItem.Image"),
              System.Drawing.Image ).
      = System.Drawing.Color:Black.
    newToolStripMenuItem:Name = "newToolStripMenuItem".
      = CAST( EnumHelper:Or(System.Windows.Forms.Keys:Control,
              System.Windows.Forms.Keys ).
    newToolStripMenuItem:Size = NEW System.Drawing.Size(151, 22).
    newToolStripMenuItem:Text = "&New".
    . . .
    . . .
    /* MDIForm */
    THIS-OBJECT:Text = "<Put title here>".
    THIS-OBJECT:AutoScaleDimensions = NEW System.Drawing.SizeF(6.0, 13.0).
    THIS-OBJECT:AutoScaleMode = System.Windows.Forms.AutoScaleMode:Font.
    THIS-OBJECT:ClientSize = NEW System.Drawing.Size(632, 453).
    THIS-OBJECT:IsMdiContainer = TRUE.
    THIS-OBJECT:MainMenuStrip = menuStrip.
    THIS-OBJECT:Name = "MDIForm".
    menuStrip:ResumeLayout( FALSE ).
    menuStrip:PerformLayout( ).
    toolStrip:ResumeLayout( FALSE ).
    toolStrip:PerformLayout( ).
    statusStrip:ResumeLayout( FALSE ).
    statusStrip:PerformLayout( ).
    THIS-OBJECT:ResumeLayout( FALSE ).
    THIS-OBJECT:PerformLayout( ).

Like several menu items in this MDI form, this one has an icon image that it gets from the resources object. This code also defines a control key sequence as a shortcut (ShortcutKeys property), as well as a menu shortcut (Text property setting). Finally, it subscribes an event handler (ShowNewForm( ) method) to the Click event on the object. The code initializes most of the remaining menu items and toolbar buttons in a similar manner. For example further on, it subscribes the OpenFile( ) event handler to the Click event on the Open menu item object (openToolStripMenuItem).
The initialization code terminates by initializing the MDI parent form, itself, and by resuming layout events and performing left-over layout tasks for all the control containers. Form initialization, itself, is a relatively simple matter of adding the control containers previously initialized to its own control collection, setting its IsMdiContainer property to TRUE (which turns on most of the MDI functionality for the form), and making the menuStrip object its primary menu container.
All of the operational behavior for the MDI parent form occurs in the event handlers subscribed to events of all the menu items and toolbar buttons. Following from the event subscriptions for the New and Open menu items, MDIForm provides ShowNewForm( ) and OpenFile( ) event handlers as shown in the following section of code. Additional event handlers also appear in the same code section, which implement basic behavior for the MDI parent form. All event handlers execute in response to events processed during execution of the MDI form class method, DoWait( ).
  METHOD PRIVATE VOID ShowNewForm(sender AS Object, e AS EventArgs):
    /* Create a NEW instance of the child form. */
    DEFINE VARIABLE childForm AS Progress.Windows.Form NO-UNDO.
    childForm = NEW Progress.Windows.Form( ).
    /* Make it a child of this MDI form before showing it. */
    childForm:MdiParent = THIS-OBJECT.
    childFormNumber = childFormNumber + 1.
    childForm:Text = "Window " + STRING(childFormNumber).
    childForm:Show( ).
  METHOD PRIVATE VOID ExitToolsStripMenuItem_Click(sender AS Object,
                                                   e AS EventArgs):
    THIS-OBJECT:Close( ).
  METHOD PRIVATE VOID OpenFile(sender AS Object, e AS EventArgs):
    openFileDialog = NEW OpenFileDialog( ).
      = System.Environment:GetFolderPath
    openFileDialog:Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*".
    openFileDialog:FileOk:Subscribe(OpenFile_Ok)./* Open clicked */
    WAIT-FOR openFileDialog:ShowDialog( THIS-OBJECT ).
    openFileDialog:Dispose( ).
METHOD PRIVATE VOID OpenFile_Ok(sender AS Object, e AS CancelEventArgs):
    fileName = openFileDialog:FileName.
    /* TODO: Add code here to open the file. */
So if you click the File > New menu item, the ShowNewForm( ) event handler immediately instantiates a non-modal form (childForm) and initializes the new form as a child of the MDI parent form by setting the MdiParent property of childForm to THIS-OBJECT. It also titles the form by incrementing and appending the value of childFormNumber to its Text property character string. It then calls the Show( ) method to display the new child form in the MDI form client area. The event handler thus creates and displays a new child form for each click of the New menu item (or its toolbar button).
If you click the File > Open menu item, the OpenFile( ) event handler instantiates the OpenFileDialog class (openFileDialog), sets some environment properties for opening a file, subscribes the OpenFile_Ok( ) event handler to the object's FileOk event, and executes the WAIT-FOR statement to display and block for input on the dialog box. After selecting a file, clicking Open in the dialog box publishes the FileOk event. The OpenFile_Ok( ) event handler executes to open the selected file (not implemented). When this event handler returns, the WAIT-FOR statement terminates in the OpenFile( ) event handler.
Note: Clicking the Cancel button in the Open dialog box also causes the dialog box to close and the associated WAIT-FOR statement to terminate.