Make 2 forms able to overlap each other?

2020-02-14 03:11发布

问题:

I would like to have a seperate form that shows "along" with my main form, so it does not overlap the main form.

Here's an example:

Notice how the main program, overlaps the log? I can't figure out how to do that in Delphi.

Thanks!

回答1:

The answers to this question lie in the very useful Window Features MSDN topic.

The pertinent information is:

An overlapped or pop-up window can be owned by another overlapped or pop-up window. Being owned places several constraints on a window.

  • An owned window is always above its owner in the z-order.
  • The system automatically destroys an owned window when its owner is destroyed.
  • An owned window is hidden when its owner is minimized.

The main form in your app is the owner (in Windows terminology rather than Delphi terminology) of the other popup windows. The first bullet point above implies that the owned windows always appear above the main form (the owner).

Try creating an app with 3 forms and show them all. The .dpr would look like this:

program OwnedWindows;

uses
  Forms,
  Main in 'Main.pas' {MainForm},
  Popup1 in 'Popup1.pas' {PopupForm1},
  Popup2 in 'Popup2.pas' {PopupForm2};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainForm, Main);
  Application.CreateForm(TPopupForm1, PopupForm1);
  Application.CreateForm(TPopupForm2, PopupForm2);
  PopupForm1.Show;
  PopupForm2.Show;
  Application.Run;
end.

You will see that the main form is always underneath the other two forms, but these other owned forms can be above or below each other. When you minimize the main form they all disappear.

You could if you want make all of your forms top-level unowned windows:

procedure TPopupForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := 0;
end;

And like wise for TPopupForm2 in my example. This would result in all 3 windows having taskbar buttons.

One other approach is to revert to the pre-Vista way of things and make the Application's hidden window be the top-level owner window. You do this by making sure that Application.MainFormOnTaskbar is False. Skip all the CreateParams code and you'll now have a single window on the taskbar and any of your windows can be above any other because the top-level owner window is the hidden window Application.Handle. Of course the downside is that you lose your Aero Peek.

So, I guess what you need to do is to make the main form appear on the taskbar as usual, but ensure that the other forms are not owned (in the Windows sense) by the main form. But they need to be owned to avoid having them in the taskbar. So you can make the hidden application window be the owner using the CreateParams method, like so:

procedure TOverlappedPopupForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := Application.Handle;
end;

Although you state otherwise in the comments, when I do this I find that the popup form is indeed hidden when I minimize the main form. And it is shown again when the main form is restored. Thus I think this does solve your problem completely.



回答2:

I haven't got Delphi open now, but would setting

mainform.formstyle := fsStayOnTop 

and show the child form with

childform.show;

work?

or else try using SetWindowPos() and setting the hWndInsertAfter property to something like HWND_TOPMOST on the main form