Home

SDI and MDI Applications

 

Fundamentals of a Single Document Interface

 

Introduction

A single-document interface, SDI, is an application primarily made of a form equipped with a menu. An example is Notepad:

Notepad

In some cases, an SDI can also have a toolbar and/or a status bar. Here is an example from Microsoft Works Spreadsheet:

Microsoft Works

 

All these features are left to the programmer to add and configure.

Although Notepad is text-based, an SDI can be any type of application, text, graphics, spreadsheet, anything. Therefore, to create an SDI, start from a normal form, add a menu to it, and configure it to do what you want.

To create a document using an SDI, the user launches the application. The SDI then presents a rectangular window with one frame and the inside is the document the user will use. In most cases, the application itself creates the document. The user can work on it and do whatever the application allows. To create another document of the same type, the user must open another instance of the application.

Creating a Single Document

There is no magic with creating a single document interface. All you have to do is

  • Create a VCL Forms Application
  • Not change the main form into a dialog box
  • Add a main menu and optional resources to the application

Then configure the application to behave the way you want.

Embarcadero provides a fast means of creating an SDI. To use it, display the New Items dialog box, select SDI Application and click OK

Practical LearningPractical Learning: Introducing MDI Applications

  1. Start Embarcadero RAD Studio
  2. To create a new application, on the main menu, click File -> New Other...
  3. In the left list, click C++Builder Projects
  4. In the right list, click SDI Application
     
    New Items
  5. Click OK
  6. In the Browse For Folder dialog box, replace the string in the Folder edit box with Notes
     
    New Items
  7. Click OK
     
    Single Document Interface
  8. To execute, press F9
  9. After viewing the application, click the form and return to your programming environment

Fundamentals of a Multiple Document Interface

 

Introduction

A multiple-document interface, MDI, is an application that primarily has a form and a menu. Some, if not most MDIs also have one or more toolbars and/or a status bar. Here is an example:

Multiple-Document Interface

Like a normal application, to use an MDI, the user must launch it. In some cases, when the application starts, it is empty; that is, no document is created and the title bar displays a caption, usually the name of the application.

Usually, there are steps the user must follow to create a document. In some other cases, when the application is launched, it automatically creates a document. A document resides inside the parent frame of the application. That is, a child document can use only the area reserved for it. The child document has its own system icon, its own title bar, and its system buttons (Minimize, Maximize/Restore, and Close).

To use the whole area, the user can maximize the child document. When this is done, the child merges its title bar with the parent's. The new caption of the title bar becomes made of the text of the parent, followed by -, and followed by the caption the child window was using. The system buttons of the child document display under those of the parent frame:

Multiple Document Interface

Once a document has been created, the user can use it. Normalement, the application must give the user the ability to create other documents while still using the application. If many documents have been created, all of them are confined in the frame of the application:

Multiple Document Interface

The user can maximize the child forms. If so, the document that was in front occupies the whole area devoted to child documents. The other child forms stay in the back but become invisible.

One of the differences between an SDI and an MDI is that, because the document and the application don't share a frame, the user can close the document and keep the application open.

Practical LearningPractical Learning: Introducing MDI Applications

  1. Start Embarcadero RAD Studio
  2. To create a new application, on the main menu, click File -> New -> VCL Forms Application - C++Builder
  3. In the Object Inspector, click Caption and type Notice
  4. Click Name, type frmMainFrame and press Enter
  5. In the Tool Palette, click Dialogs
  6. Click the OpenFileDialog button OpenFileDialog and click the form
  7. In the Object Inspector, change its characteristics as follows:
    (Name): dlgFileOpen
    DefaultExt: rtf
    Filter: Rich Text Format (*.rtf)|*.rtf|Text Files (*.txt)|*.txt|All Files|
    Multiselect: True
    Title: Open File
  8. In the Tool Palette, click Standard
  9. Click the TMainMenu button OpenFileDialog and click the form
  10. On the form, right-click MainMenu1 and click Menu Designer...
  11. Right-click somewhere in the Menu Designer and click Insert From Template...
  12. In the Insert Template dialog box, click MDI Frame Menu
     
    Insert Template
  13. Click OK

Creating an MDI Application

As mentioned already, there is nothing magical with creating an SDI. You start with a form, add a menu to it, and specify what the application should allow a user to do with a document. As we will see, an MDI requires more steps.

You start an MDI application with a normal form. You can create a VCL Forms Application using RAD Studio or derive a class from TForm. The primary form of an MDI application is referred to as the parent or MDI container. It provides the frame inside of which the documents will reside. To provide this functionality, the TForm class is equipped with a property named FormStyle. To create an MDI, set the FormStyle property to fsMDIForm. You can do this in the Object Inspector if you are visually creating your application, or programmatically. This would produce:

Multiple Document Interface

The primary characteristic of an MDI is that it contains other forms. These forms must be created and made available to the parent. Each form can be created using a predefined form or you can programmatically create one by declaring an object of type TForm.

Practical LearningPractical Learning: Creating an MDI Application

  1. In the background, click the form to give it focus
  2. In the Object Inspector, change the following characteristics:
    FormStyle: fsMDIForm
    Position: poScreenCenter
  3. To add a new form, on the main menu, click File -> New -> Form - C++Builder
  4. In the Object Inspector, change the Name to frmDocument
  5. In the Object Inspector, click Events
  6. Double-click OnClose
  7. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmDocument::FormClose(TObject *Sender, TCloseAction &Action)
    {
    	Action = caFree;
    }
    //---------------------------------------------------------------------------
  8. On top of the Code Editor, click Unit1.cpp to display the first form
  9. On the main menu, click File -> Use Unit...
  10. In the Use Unit dialog box, click Unit2.cpp
  11. Click Header and click OK
  12. In the Menu Designer, under File, double-click New
  13. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::New1Click(TObject *Sender)
    {
    	TfrmDocument *frmChild = new TfrmDocument(Application);
    
    	frmChild->Caption = L"Untitled";
    	frmChild->FormStyle = fsMDIChild;
    }
    //---------------------------------------------------------------------------
  14. To test the application, on the main menu of RAD Studio, click Run -> Run
  15. On the main menu of the application, click File -> New
  16. Click File -> New again
  17. Click File -> New again
  18. To close the current child form, click its system Close button Close, Close, or Close
  19.  Close the main form and return to your programming environment

MDI Characteristics

 

The Active MDI Child

If an MDI application contains more than one child form, only one can be activated at one particular time. The document that is currently active has a bright title bar. To help you get a reference (pointer) to the current active form, the TCustomForm class is equipped with a property named ActiveMDIChild:

__property Forms::TForm * ActiveMDIChild = {read=get_ActiveMDIChild};

As you can see, this property is of type TForm, which means it produces a TForm object.

 

Introduction to the Children of an MDI

When you create an MDI application, you must make sure you provide your users with the ability to create documents. In fact, probably one of your early assignments is to make sure the user can create as many documents as necessary. As the documents are created, you need a way to programmatically keep track of the child forms. For example, you can store the documents in a collection. To assist you with this, the Form class is equipped with a property named MDIChildCount, which is a read-only array:

__property int MDIChildCount = {read=get_MDIChildCount};

The child forms of an MDI are stored in an array named the MDIChildren:

__property Forms::TForm * MDIChildren = {read=get_MDIChildren};

 Therefore, to access a child form of an MDI application, you can pass an index to this property.

Practical LearningPractical Learning: Counting the Children of an MDI

  1. Under the Code Editor, click Unit.h
  2. In the private section, declare a variable as int childCount;
  3. Under the Code Editor, click Design
  4. In the Menu Designer, click the box under Exit
  5. In the Objects Inspector, change the following properties:
    Caption: &Close
    Enabled: False
    Name: mnuFileClose
  6. Click the box under the Close menu item
  7. In the Object Inspector, click Caption, type - and press Enter
  8. Click the box under the new separator
  9. Type - and press Enter
  10. Move the Close menu item, and the separator to position them under Save As...
     
    Menu Designer
  11. Double-click the Close menu item
  12. Change the document as follows:
    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TfrmMainFrame *frmMainFrame;
    //---------------------------------------------------------------------------
    __fastcall TfrmMainFrame::TfrmMainFrame(TComponent* Owner)
    	: TForm(Owner)
    {
    	childCount = 0;
    }
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::New1Click(TObject *Sender)
    {
    	childCount++;
    	TfrmDocument *frmChild = new TfrmDocument(Application);
    
    	frmChild->Caption = L"Untitled";
    	frmChild->FormStyle = fsMDIChild;
    
    	mnuFileClose->Enabled = True;
    }
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::mnuFileCloseClick(TObject *Sender)
    {
    	// If there is at least one child document, close it
    	if( MDIChildCount > 0 )
    		ActiveMDIChild->Close();
    
    	// After closing the last document,
    	// check the number of current chil forms.
    	// If there is none, disable the Close menu item
    	if( MDIChildCount == 0 )
    		mnuFileClose->Enabled = False;
    }
    //---------------------------------------------------------------------------
  13. Press F9 to test the application

Cascading the Child Documents

Based on the standards defined in the operating system, as child forms are created in an MDI application, they are positioned each on top of the previous one but below the next one. The arrangement uses a 3-D coordinate system whose origin is on the lower-left corner of the parent's frame just under the title bar (or the menu, if any), with the Z avis moving from the monitor towards you.

To support this arrangement, the TForm class is equipped with a method named Cascade. Its syntax is:

void __fastcall Cascade(void);

Call this method to overlad the child forms.

Practical LearningPractical Learning: Cascading the Child Documents

  1. In the Menu Designer, click Window and double-click Cascade
  2. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::Cascade1Click(TObject *Sender)
    {
    	Cascade();
    }
    //---------------------------------------------------------------------------
  3. Press F9 to test the application
  4. Create a few documents
  5. Click Window -> Cascade
     
    Cascading
  6. Close the main form and return to your programming environment

Tiling the Child Documents

The operating system allows the user to choose among different arrangements. For example, you can position the documents as vertical columns, as horizontal rows, or as tiles. To support this, the TForm class is equipped with a property named TileMode. Its syntax is:

__property Forms::TTileMode TileMode = {read=FTileMode,write=FTileMode};

The TileMode property gets a value that is a member of the TTileMode enumeration. The members of this enumeration are tbHorizontal and tbVertical. When specifying the value of TileMode, you inform the parent frame about the type of arrangement you want: horizontal or vertical. To actually apply the arrangement, you must call the Tile() method. Its syntax is:

void __fastcall Tile(void);

Practical LearningPractical Learning: Tiling the Child Documents

  1. In the Menu Designer, under Window, click Tile
  2. Press Ctrl and the right arrow key
  3. In the Object Inspector, change the following properties:
    Caption: &Vertically
    Name: mnuTileVertically
  4. In the Menu Designer, click the box under Vertically
  5. In the Object Inspector, change the following properties:
    Caption: &Horizontally
    Name: mnuTileHorizontally
     
    Menu Designer
  6. Double-click Vertically
  7. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::mnuTileVerticallyClick(TObject *Sender)
    {
    	TileMode = tbVertical;
    	Tile();
    }
    //---------------------------------------------------------------------------
  8. In the Menu Designer, double-click Horizontally
  9. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::menuTileHorizontallyClick(TObject *Sender)
    {
    	TileMode = tbHorizontal;
    	Tile();
    }
    //---------------------------------------------------------------------------
  10. Press F9 to test the application
  11. Create a few documents
  12. Click Window -> Tile -> Vertically
     
    Cascading
  13. On the main menu, click Window -> Tile Horizontally
     
    Tiling Vertically
  14. Close the main form and return to your programming environment

Accessing a Child Document

In most MDI applications, a user can create as many documents as necessary. This also means that the application can hold many child forms. To access a child form, the user can click its title bar. You can also provide options on a menu item named Window that would activate a child document. To support this, you have various options.

As mentioned already, the child documents of an MDI are arranged as a collection, having a first, a second, and optional subsequent documents. While the application is displaying one particular document, the collection allows you to access the next or previous child window based on the position of the currently displaying form. To let you access the next document, the TForm class is equipped with a method named Next. Its syntax is:

void __fastcall Next(void);

When you call this method, if the application has no child form or only one form, nothing would happen. If the application has more than one form, it would bring the form that follows the current one to the front. If you want to access the previous child form, the TForm class can assist you with the Previous() method. Its syntax is:

void __fastcall Previous(void);

Arranging the Minimized Child Forms

In an MDI application, if the user doesn't want to display a document but doesn't want to close it, he can minimize the window. In the same way, the user can minimize as many child forms as necessary. When a child form has been minimized, it shows a button in the lower part of the parent. The buttons of the other minimized child forms are usually positioned next to each other:

Minimized Buttons

The user can move the buttons at will:

Minimized Buttons

A user can also close the child form using the Close button of its minimized button. At one time the minimized buttons may display as a "mess". To let you rearrange them, the TForm class provides a method named ArrangeIcons. Its syntax is:

void __fastcall ArrangeIcons(void);

If you can this method, the application will visit each button, if any, that represents a minimized child document, and position them from the left to the right, adjacently.

Practical LearningPractical Learning: Arranging the Minimized Children

  1. In the Menu Designer, under Window, double-click Arrange All
  2. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::ArrangeAll1Click(TObject *Sender)
    {
    	ArrangeIcons();
    }
    //---------------------------------------------------------------------------
  3. Press F9 to execute the application
  4. Using the main menu, create 5 documents
  5. Minimize all 5 child forms
  6. Using their system Close buttons, close the second and the fourth forms
  7. On the main menu, click Window -> Arrange All
  8. Close the main form and return to your programming environment
  9. In the Menu Designer, click File and double-click Exit
  10. Close the Menu Designer
  11. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmMainFrame::Exit1Click(TObject *Sender)
    {
    	this->Close();
    }
    //---------------------------------------------------------------------------
  12. Execute the application
  13. On its main menu, click File -> Exit to return to your programming environment
 
 
 
 

Home Copyright © 2010-2011 FunctionX, Inc.