MDI: A solution for Nilling Child form pointers

From: Kristofer Skaug (ya.ierfgnf_at_thnxf.x)
Date: 10/26/03


Date: Sun, 26 Oct 2003 01:04:43 +0200


A classic problem that has been bothering me for years: In an MDI app,
suppose you have a number of MDIchild windows that are created and
destroyed dynamically, and you need to ensure each child form's form
variable is reset to nil after destruction. Since various of the MDI
windows are created from the same form class (in my case), it is simply
not possible to refer to the default global form variables and set them
to nil in each form's OnDestroy handler, - assuming your programmer's
aesthetics could "stomach" such an ungodly technique in the first place,
that is <g>. Only the MDI parent form knows the name of the form
variables, how many there are for each class/type, etc. - and this is as
it should be.

Anyway, my solution to this (so far) has been to equip each child form
with a custom OnDestroying event (a TNotifyEvent) which is assigned by
the parent form on startup, and invoked from within the child form's own
OnDestroy handler, and then propagated to the MDI main form as follows:

procedure TMainForm.MDIchildDestroying(Sender:TObject);
begin
  if Sender = ChildForm1 then ChildForm1:=nil
  else if Sender = ChildForm2 then ChildForm2:=nil
  else if Sender = Ch... aaarrrrrgh!
end;

where ChildForm1, ChildForm2, etc. are form variables (for mercy's sake
implemented as fields of the main form, not as bleeping globals).

Now imagine how much fun it is to maintain this in an app with, say,
20-30 distinct child forms, several of which share the same class. OK it
works, but I hate the sight of any if-then statement with more than one
or two else's.

So... after about 6 years of this private maintenance hell, I finally
told myself, 'enough of this!', and set out for a better solution:
Specifically, to eliminate the need for the OnDestroying event and a
mile-long if-then-else-if statement. I came to the following solution,
which does require a special field and a method for each child form -
but this can be shared by inheritance in many cases:

TChildForm = class(TForm)
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    FMyFormPointer:pointer;
  public
    procedure SetFormPointer(APointer:pointer);
  end;

implementation

procedure TChildForm.SetFormPointer(Apointer:pointer);
begin
  FMyFormPointer:=Apointer;
end;

procedure TChildForm.FormDestroy(Sender: TObject);
begin
  LongWord(FMyFormPointer^):=0;
end;

procedure TChildForm.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
  Action:=caFree;
end;

So how does this work? In the Main form:

  ChildForm:=TChildForm.Create(Self);
  ChildForm.SetFormPointer(@ChildForm);

that's all! when the user closes the child form, its internal reference
FMyFormPointer will allow the form instance to go out and set the form
variable itself to nil, even though it cannot 'see' its own form pointer
or what its name is in the main form.

Well, perhaps you all knew how to do this already, in that case please
tell me I'm an idiot since it took me 6 years to figure this out (well,
I did solve some other problems in the meantime <g>).

-- 
Kristofer


Relevant Pages

  • RE: Mdi Icon Position in MenuStrip
    ... you'd like to show the icon of a maximized MDI ... child form immediately left of the control box buttons(Minimize, Maximize, ... Maximize/Resore menu item ... Microsoft Online Community Support ...
    (microsoft.public.dotnet.languages.vb)
  • Re: My.Application.OpenForms
    ... Sorry you're missing the VB6 IDE; ... Have you solved the problem of sizing a child form to fit the MDI ... 'enable application framework' checkbox is unchecked. ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Issues with displaying a .Net Form as Child of a MDI Form in VB6 Application
    ... You'll probably fail miserably VB6 MDI Parents refuse to adopt children. ... SetParent won't give you the MDI Child form functionality. ...
    (microsoft.public.vb.winapi)
  • Re: Clicking a button and pressing Enter key act different in MDI
    ... This event "Occurs when a multiple document interface (MDI) child form is ... child form visibility in Button click event, not in MdiChildActivate event. ...
    (microsoft.public.dotnet.framework.windowsforms)