Home | Articles | Links | Contact
 
Title ActiveMDIChild versus merging the main form menu and the child window menus in a mdi application
Description The obvious way to access a child window is to call its public methods from the main form. The other is to merge its main menu with the application main menu.
Date 10/23/2000
Last revision
Related articles

Basic MDI ( Multiple Document Interface) programming with Delphi 5
Tile, cascade, arrange and list mdi child windows


For basic skills on mdi applications, please have a look at "Basic MDI ( Multiple Document Interface) programming with Delphi 5" and "Tile, cascade, arrange and list mdi child windows".

The obvious way to access a child window is to call its public methods from the main form. To do so we use the ActiveMDIChild property of the main form. This property points to the child window that has the focus in the main form, that's the window the user is currently using. This property could be set to nil if there is no active mdi child window, which could happen if we haven't created any mdi child window, so before we use ActiveMDIChild we have to check it's assigned to something. Another drawback of this first method appears when we have an application with different types of documents. Imagine we have a program that can work with text documents and pictures at the same time. In this environment we cannot use ActiveMDIChild without checking its type because we don't know if the active window is going to be a text or a graphic.

To avoid all these problems we can use the second method: merging menus. With this system we define a menu in the main form and a main menu for each child window type we create in the application, then we decide the way they are going to be merged by the application when the user selects a child window.

ActiveMDIChild hits first
Merging menus strikes back
Who won?

ActiveMDIChild hits first

As we said, the first method to access a mdi child window is the ActiveMDIChild property. This property is defined by the TCustomForm class, available for all forms it only has sense when talking about a form with the FormStyle property set to fsMDIForm this property returns a reference to the child window that has the focus. This property could be nil, so we will always have to check it's assigned before using it or we will probably cause some memory problems:

if Assigned( ActiveMDIChild) then
  ActiveMDIChild.Close

In this case we are using a method defined in TCustomForm, so we can make a call to it directly. Let's assume that we have defined a window class called TfDocument and this class defines a public method called Save. We cannot make a direct call to Save using ActiveMDIChild because its class is TCustomForm and the method Save it's not defined for TCustomForm. However, we know ActiveMDIChild really points to a TfDocument window, which has that method available. To reach this method we have to use the as operator to perform a typecast and transform ActiveMDIChild into a TfDocument:

if Assigned( ActiveMDIChild) then
  ( ActiveMDIChild as TfDocument).Save

What happens if we don't know if ActiveMDIChild points to a TfDocument window? Maybe the method Save it's only defined for this kind of window, but we could have many different classes of mdi child windows running in our application. To check if the mdi child window that has the focus belongs to a certain kind of window we may use the is operator:

if Assigned( ActiveMDIChild) and ( ActiveMDIChild is TfDocument) then
  ( ActiveMDIChild as TfDocument).Save

Now that we have our code finished and completely protected, let's think about other alternatives...


Merging menus strikes back

All the checking we have performed in the previous section are needed because we are accessing the child window from the main form of the application. For this reason we have to check first if the window really exists and if it belongs to a certain type of window. What would happen if we could access the form from the same form? We wouldn't have to do any checking at all. Let's try it.