tags:

views:

215

answers:

2

Hello.

I have created MDI application in Delphi. Lets assume that I have a bunch of MDIChild forms in my application which are visible on the screen. I would like to perform a loop on those forms and check in what order each of the forms is displayed on the screen.

For example if I have 3 MDICHild forms:

FormA, FormB, FormC

and

FormB partly overlaps FormA and FormC partly overlaps FormB

I want to mark their Z property (deepth) as follows:

FormB.Z = 2 // that form is between FormA and FormC
FormA.Z = 3 // that form's distance is longest from user, form is overlapped by FormB and 
FormC.Z = 1 // that form is at the top of all forms in my application

Thanks for your time.

+1  A: 

Use the Screen.Forms property to iterate though the forms in your application. It returns them in Z order, exactly as you want.

e.g. Create an application with 1 MDIForm and 3 MDIChild forms.

In a menu option on the main form, enter:

procedure TForm1.mnuFormOrder2Click(Sender: TObject);
var
  i: Integer;
  s: String;
begin
  s := '';
  for i := 0 to Pred(Screen.FormCount) do
  begin
    s := s + Screen.Forms[i].Caption+#13;
  end;

  MessageBox(Self.Handle, PChar(s),
    PChar(Self.Caption), MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
end;

This will show a message listing the names of the forms in their Z-sequence. It will also list your main form but you can code this out. If you make a different child form the active one, then click the menu option again, you will see the order of the forms has changed.

_J_
Thanks _J_ this is exactly what I wanted. But!;) If you test your code under new MDI Application created from the wizzard, it will show you also the About form which is not visible on the screen. But I guess that can be easly filtered out. Thanks again.
Wodzu
+2  A: 

J's answer loops through Screen.Forms. This contains all forms in the application, including non-MDI ones, as I see you found from your comment. You can filter your main form and About box manually, but that's messy, and you'll also need to do the same thing for other forms. I really don't like having to do that because it seems rather error-prone.

Your question says you only want to know the z-order of MDI child forms within the parent, and in this case there's a much better solution.

MDI children are listed in z-sorted order in the MDI parent form's MDIChildren property. The code to find the Z depth would look something like this (untested):

function FindChildDepth(Child : TForm) : Integer;
var
  i : Integer;
begin
  Result := -1; // Form not found
  for i := 0 to MDIChildCount-1 do
  begin
    if (MDIChildren[i] == Child) then
    begin
      Result := i;
      Exit;
    end;
  end;
end;

That should return the depth of a child between 0 and n-1, where 0 is top, and -1 if the form is not found in the MDIChildren array. If you want "1" to mean top instead of 0, simply set Result to i+1 instead.

David M
Quite right, I use MDIChildren all the time but hadn't realised it returned the forms in Z order.
_J_
Thank you David M. Since it is cleaner solution I'll mark it as a correct answer. Hope that _J_ will not feel offended ;-)
Wodzu
Ouch. Fair enough.
_J_