Avoiding MDI: Making a form a child of another form

Question:
How do I make a form a child of another form without having to resort to the overhead of MDI?

Answer:

MDI provides an easy and well-established way for developers to create applications in which one form can contain several forms in a Parent-Child relationship. But because MDI is so well-defined, it takes up a lot of resources. Especially in the case where you want to create a child form for the express purpose of being a tool bar of sorts, carrying the MDI along for just this purpose can be a bit of a waste of resources. But there is a work-around for it.

All Delphi forms inherit a very useful method from TWinControl called CreateParams. You can override this method to achieve various behaviors in the way a form diplays when it’s created. Without going into a lot of esoteric Windows API lingo, CreateParams initializes a TCreateParams structure that contains generic base values defining a window’s appearance. The record structure is listed below:

type    TCreateParams = record    Caption: PChar;    Style: Longint;    ExStyle: Longint;    X, Y: Integer;    Width, Height: Integer;    WndParent: HWND;    Param: Pointer    WindowClass: TWndClass;    WinClassName: array[0..63] of Char;  end;

We won’t go into any detail about this structure because it’s beyond the scope of this discussion. I’ll leave it up to you to peruse the online help for a detailed discussion of the topic. However, note that there are several things you can change in the structure itself. With respect to our current discussion, to achieve our desired result of having a form be the child of another form, we’ll manipulate this structure within our CreateParams method.

It’s actually a fairly trivial thing to make a form act as a child form. All we have to do is the following:

  1. Create the form with a Child window style
  2. Notify Windows that the form has a new parent
  3. Notify Delphi that the form has a new parent

It couldn’t get easier than this. Here’s the code for the method that accomplishes the steps above:

unit child;interfaceuses  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;type  TChildForm = class(TForm)    procedure FormClose(Sender: TObject; var Action: TCloseAction);    procedure Button1Click(Sender: TObject);  private    procedure CreateParams(var Params : TCreateParams); override;  public    { Public declarations }  end;var  ChildForm: TChildForm;implementation{$R *.DFM}procedure TChildForm.CreateParams(var Params : TCreateParams);begin  inherited CreateParams(Params);  with Params do begin    {Set the Child’s style to WS_CHILD}    Style := (Style OR WS_CHILD) AND NOT WS_POPUP;    X := 50;    Y := 50;    Width := 200;    Height := 150;    {Let Windows know about the relationship}    WndParent := Application.MainForm.Handle;  end;  {Let Delphi know about the relationship}  Parent := Application.MainForm;end;procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction);begin  Action := caFree;end;procedure TChildForm.Button1Click(Sender: TObject);begin  ShowMessage(‘Hello world!!!’);end;end.

Nothing really complex about that, right? All I did with the TCreateParams structure was to set the window style to WS_CHILD so the window is created a child, then set the parent-child relationship with a couple of assignment lines. With this sample, I simply embedded a TButton on the form to display the obligatory test message Hello world!!! But you can make the form do practically anything you want. Also, note the FormClose method: I’ve set it so that the form is destroyed when it is closed. However, you can substitute the Action := caFree; with Action := caMinimize to mimic the behavior of an MDIChild form.

Since this is a fairly simple tip, I didn’t include a sample application. However, if you want to create a test application to test this concept out, do the following:

  1. Create a new application in Delphi.
  2. Name the main form something like ParentForm to differentiate it from other forms.
  3. Using either the tool bar or File|New Form, create a new form.
  4. Insert the code above in the Child form as above.
  5. Insert a uses statement in the implementation of your MainForm and declare your child form’s unit name.

Create a child form like this as you would normally create any other form. Here’s some sample code from the main form of my test application:

procedure TForm1.Button1Click(Sender: TObject);var  ChildFrm : TChildForm;begin  ChildFrm := TChildForm.Create(Application);  ChildFrm.Show;end;

This is plain vanilla form creation, so there’s nothing here that you don’t already know how to do. In fact, if you look at all the code above, there’s really nothing so complex that you couldn’t have figured it out sooner or later by yourself.

You might be asking Of what use is this methodology? Well, besides toolbars, I use this technique for creating wizard-like programs. I also use it instead of using notebooks because sometimes my pages can get fairly complex. So to reduce resource utilization, I instead create a bunch of child forms that don’t have any caption bars or borders and are maximized in the client area of the main form. As the user goes from page to page, the components embedded on the pages are created and destroyed on the fly. This may be a bit slower in comparison to having a notebook, but this technique is far less resource-intensive than using a notebook, which would load up all the components at run time.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

homes in the real estate industry

Exploring the Latest Tech Trends Impacting the Real Estate Industry

The real estate industry is changing thanks to the newest technological advancements. These new developments — from blockchain and AI to virtual reality and 3D printing — are poised to change how we buy and sell homes. Real estate brokers, buyers, sellers, wholesale real estate professionals, fix and flippers, and beyond may

man on floor with data

DevX Quick Guide to Data Ingestion

One of the biggest trends of the 21st century is the massive surge in internet usage. With major innovations such as smart technology, social media, and online shopping sites, the internet has become an essential part of everyday life for a large portion of the population. Due to this internet

payment via phone

7 Ways Technology Has Changed Traditional Payments

In today’s digital world, technology has changed how we make payments. From contactless cards to mobile wallets, it’s now easier to pay for goods and services without carrying cash or using a checkbook. This article will look at seven of the most significant ways technology has transformed traditional payment methods.