Solved

MDI Child window z-order

Posted on 2003-11-30
4
1,553 Views
Last Modified: 2010-04-05
If I create an MDI form and place, say, a TPanel on it, then open an MDI Child form, the MDI child form appears *behind* the panel.

Is there a way around this, i.e. so that the panel appears behind the MDI child form? I have had a bit of a fiddle with SetWindowPos() but no luck so far.
0
Comment
Question by:PhilipRayment
  • 2
  • 2
4 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 9848615
this is not possible,

mdi-Childs can only showed in the uncovered
client-area of the mdi-mainform

meikl ;-)
0
 
LVL 1

Author Comment

by:PhilipRayment
ID: 9849944
meikl wrote:
>>mdi-Childs can only showed in the uncovered client-area of the mdi-mainform<<

Thanks for responding, but could you please explain/elaborate on this?

I know that MDI Child forms can only be shown on the client area of the MDI main form, but what do you mean by the "uncovered" client area?  I can "cover" part of the MDI main form with a non-windows control (e.g. TLabel) and the MDI Child window will show in front of it.  I can also "cover" part of the MDI main form with a windowed control (e.g. TPanel) and show an MDI Child window there, it's just that the TPanel shows in front of the MDI Child window.

I realise that there is a difference between windowed and non-windowed controls, in that the former have a windows handle.  But so do MDI Child windows, so I would have thought that I could manipulate the relative order of the two.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 100 total points
ID: 9856651
let me explain it as metapher

a mdi-mainform is like a car-truck
(a truck (main) loaded with cars (childs))

usual by this kind of truck the loading area is open
(any people can look and touch the cars on the loading area)

you will now cover this loading area, and you will have
now the problem that no people can
look and touch the cars on the loading area.

and because of this, you will now place the cars on the
cover, which is impossible, because the cars will
fall down from the cover.

so far the matapher, back to the os.

simplified explaination

mdi is a special os-gui, which has defined rules,
and specialized messages to keep care of the
organization of this kind of gui. these special messages
are only sent to the main-window, which dispatches it to the
its childs, if needed.

a panel cannot do this job (it will never receives these messages),
because it is not the main-window of the app.

but well, there is a workaround,
a pseudo mdi-like app
(formstyle is allways fsNormal)

-----  mainform
unit mdi_child_on_panel_main_u;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  mdi_child_on_panel_child_u; //where the child is defined

procedure TForm1.Button1Click(Sender: TObject);
begin
  with tform2.create(self) do
  begin
    parent := panel2;
    show;
    PostMessage(Handle, WM_NCACTIVATE, 1, 0);  //get the caption activated of the child
  end;
end;

end.

------ the child

unit mdi_child_on_panel_child_u;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.CMMouseEnter(var Msg: TMessage);
begin
  PostMessage(Handle, WM_NCACTIVATE, 1, 0);
end;

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

procedure TForm2.Button1Click(Sender: TObject);
begin
  close;
end;

end.

------- end paste

you may notice, that there are some fallbacks by doing so,
which causes in additional codings, to get the original mdi-bahaviour
implemented.


hope this clarifies a bit

meikl ;-)
0
 
LVL 1

Author Comment

by:PhilipRayment
ID: 9888330
Thanks for your help meikl.  I have experimented a bit more, including trying out your workaround.  I might use it, or I might use a non-windowed control and add some functionality to that.

I am now figuring that the problem is that Windows maintains the MDI child window z-order stack to be immediately in front of the MDI form.  That is, the child window behind all other child windows must always have a z-order placing it immediately in front of the MDI form itself.  What I was wanting was a panel to be placed between the MDI form and the MDI child, and it seems Windows just doesn't allow for that.  Non-windowed controls are different in that Delphi simply paints the image of them directly onto the MDI form's canvas; they are not really separate entities, as far as Windows is concerned.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now