tags:

views:

1079

answers:

3

This will sound against the nature of MDI.. I need to show a MDI form (FormStyle=fsMdiChild) as modal sometimes. And I also need to access the part between Application.CreateForm and OnShow event of another MDI form, i.e.

Application.CreateForm(Form2,TForm2); // but don't set form2's visible property true.
Form2.caption:='not working example'; 
Form2.SomeMagicToSetVisibleTrue;

Any ideas?

+2  A: 

For your first problem: Add another constructor, for example CreateAsMDI, like this:

constructor TModalAndMDIForm.CreateAsMDI(AOwner: TComponent); 
begin 
  f_blChild := true; 
  GlobalNameSpace.BeginWrite; 
  try 
    inherited CreateNew(AOwner); 
    if(not(csDesigning in ComponentState)) then begin 
      Include(FFormState, fsCreating); 
      try 
        FormStyle := fsMDIChild; 
        if(not(InitInheritedComponent(self, TForm))) then 
          raise Exception.CreateFmt('Can't create %s as MDI child', [ClassName]); 
      finally 
        Exclude(FFormState, fsCreating); 
      end; 
    end; 
  finally 
    GlobalNameSpace.EndWrite; 
  end; 
end;

In the normal constructor just set the variable f_blChild to false and call the inherited create.

You need two more things, rather self explaining:

procedure TModalAndMDIForm.Loaded; 
begin 
  inherited; 
  if(f_blChild) then 
    Position := poDefault 
  else begin 
    Position := poOwnerFormCenter; 
    BorderStyle := bsDialog; 
  end; 
end; 
//----------------------------------------------------------------------------- 
procedure TModalAndMDIForm.DoClose(var Action: TCloseAction); 
begin 
  if(f_blChild) then 
    Action := caFree; 
  inherited DoClose(Action); 
end;

Now you can call the form modal, if created with the standard constructor, and as MDI child, if created with CreateAsMDI.

If you include this in your form's declaration

property IsChild: boolean read f_blChild;

you can even do things depending on whether the form is an MDI child or not, just interrogating the isChild property.

As for your second problem: do not use Application.CreateForm, but create your form yourself:

Here the two creations for modal and MDI:

//Modal 
frmDialog := TMyForm.Create(self); 
// Your Code
frmDialog.ShowModal; 
frmDialog.Release; 

//MDI-Child 
frmDialog := TMyForm.CreateChild(self); 
// Your code
frmDialog.Show;

I have translated this answer form an article on the site DelphiPraxis.

Ralph Rickenbach
+1  A: 

At least for Delphi 2007 and 2009 creating the MDI child form invisible is easy. For the early Delphi versions (where it was impossible to set Visible to False in the property inspector) you just have to provide a handler for the OnCreate event and access a protected field of the class:

procedure TMDIChild.FormCreate(Sender: TObject);
begin
  FFormState := FFormState - [fsVisible];
end;

This will disable the automatic showing of the MDI child. After you are done with your other initialisations you can simply Show it or set Visible to True.

I will not try to answer your question about modal MDI child forms, as this violates the conventions of the Windows platform.

mghie
+2  A: 

The simplest method is to create a trivial subclass of the form, and set

FormStyle = fsMDIChild

AND

Form.Visible = False

in the property inspector. This is tried and tested!

Gerry
There were Delphi versions were it wasn't possible to set this combination of properties in the property inspector. It works in Delphi 2009, but I don't know since which version. It's such a trivial thing to do though that I assumed the OP is using a Delphi version where that's not an option.
mghie
I think the project that I first done this on was in Delphi 6 at the time. From memory, the important thing is to set the properties in the correct order - unless I edited the DFM directly (too long ago to remember)
Gerry