Make 2 forms able to overlap each other?
Asked Answered
S

2

5

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: Example

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

Thanks!

Serafina answered 22/3, 2011 at 15:30 Comment(4)
+1 to offset anonymous down-vote.Engud
+1 also, this is a most excellent questionReprise
I'm afraid I don't understand what you're struggling with? If you create a brand new application and add a second form, this is exactly what you get. You don't need to do anything special. Perhaps it might help if you explain what your application is doing that you're not happy about.Genous
@Craig: No, you don't get that. Create a new VCL forms application, and make the main window blue. Now, add a new form to the application; make this smaller and red. Finally, create an OnClick handler on the main form and do Form2.Show. You will notice that the new, red, form, will never be displayed behind the main, blue, form. So you really do need to to something special.Gooseneck
R
10

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.

Reprise answered 22/3, 2011 at 15:35 Comment(21)
Thanks for this, +1! Is there a way to only have 1 icon on the taskbar (without that being a hidden window, because then Windows 7 Thumb Preview is blank, in my experience)?Serafina
@Serafina The main form typically is the one one the taskbar. That's the one you want the Aero Peek preview for. Other popups will be owned windows and so always on top of the main window. Isn't that what you want?Reprise
@David - we are getting closer! :) When I minimize ImgBurn's MainForm, the log is minimized, too! That will then be the full solution :)Serafina
@Serafina you'll have to do that yourself. Detect that the main form is being minimized and call Minimize on the others. You'd want to do the opposite when the window is restored. This is what you get for free when you make the popups owned windows.Reprise
@Serafina there is code in TApplication to deal with this sort of issue when the Application hidden window is the taskbar window. Actually you might want to hide the popups rather than minimize them since if you do the latter, their minimised windows will appear above the taskbar.Reprise
@Serafina this might get a little tricky to do well and cover all the cases. If you have trouble please do post another Q!Reprise
@David - I will try this and report back :) - first I gotta fix a more important issue, I posted a Q about that already ;) Boy you guys like it when people post questions huh? Thats great cause I got a lot of em! :PSerafina
@Serafina I think my very latest update shows that there is no need for another Q. I can get exactly what you describe just by making the popup window be owned (Windows sense) by Application hidden window.Reprise
@David - This is funny - when I do the Aero Peek, while my Main Form is in focus, I see the Popup form. When I have the Popup Form in focus, I see the main form?Serafina
@Serafina that's as expected. Aero Peek shows the window that is represented on the task bar, and that's the main form no matter which has the focus.Reprise
@David - "that's as expected. Aero Peek shows the window that is represented on the task bar, and that's the main form no matter which has the focus" - Well, I said this: "while my Main Form is in focus, I see the Popup form", so apparently not. Else, its just me who did something wrong, which is rather likely :PSerafina
@Serafina weird, not what I would expect!Reprise
@David - Well, I can assure you it does not in mine.Serafina
@Serafina I don't doubt you. We must be doing something different.Reprise
@David - I had MainFormOnTaskBar = False, but when I set it to True, the CreateParams dont seem to be effectiveSerafina
@Serafina Have you got the CreateParams on the right form? It needs to go on the popup form.Reprise
@David yes, its on the popup form.Serafina
@David - Another Dropbox user, sweet! Your example works perfectly! Could it be because I am not doing Form.Show in the Project source?Serafina
@Serafina Dropbox user for 20 minutes now. No idea why your version doesn't work. But you have conclusive proof that the principle is sound.Reprise
@David - Dropbox has saved me many times, like when I wanted to add a feature back which I removed a month ago, I could get back my pas file! Anyways, yeah, I see that it works :) Thanks!Serafina
@David - Yeah, I was like ".. Hey, I know that dude!" :PSerafina
M
-1

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

Maneating answered 22/3, 2011 at 15:45 Comment(5)
This is surely possible without making the window top most.Reprise
Maybe setting the childform to HWND_BOTTOMManeating
-1 Setting the style as fsStayOnTop will have other effects in the application and outside it you do not mention in your answer.Stepdaughter
@Stepdaughter was that a virtual -1?Reprise
@David, hahahaha... not now. :)Stepdaughter

© 2022 - 2024 — McMap. All rights reserved.