Page 1 of 1

Multiple HWND_TOPMOST forms get clipt

PostPosted: October 21st, 2011, 10:12 am
by Stefan
Hi,

I have an application with a mainform and two other forms.
The MainForm has a button, which when clicked does:

Code: Select all
procedure TMainForm.Button1Click(Sender: TObject);
begin
  Form1 := TForm1.Create(self);
  Form1.Show;
end;


Form1's Position property is set to poScreenCenter.
Form1's Activate procedure is overridden with:

Code: Select all
procedure TForm1.Activate;
begin
  SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  inherited;
end;


It also has a button with OnClick:

Code: Select all
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(nil);
  Form2.Show;
end;


The Activate procedure is overridden in Form2 as well, with:

Code: Select all
procedure TForm2.Activate;
begin
  SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  inherited;
end;


Form2's Position is also set to poScreenCenter.

So, both Form1 and Form2 are in the center of the screen.
Also, Form2 is slightly smaller than Form1, so when Form2 is created (by Form1) it is completely (important!) overlapped by Form1, were it not for the call to SetWindowPos with HWND_TOPMOST which puts in on Top of the list of TOPMOST forms (is my guess).

Form2 is put on top of the list and is shown on top of Form2 and the MainForm. This works well with one minor problem:
When Form2 is shown it is not drawn correctly (or at all actually). The frame of the Form is drawn correctly, but the contents are not, the entire canvas is just a white plain.
The control (a single TEdit) is not drawn untill the mouse cursor moves over it. Any controls that do not have handles (labels, etc) are not drawn at all.

I think the problem is an optimization gone wrong. For some reason Windows thinks it can exclude Form2 from drawing since it is overlapped by Form1. Which is valid, were it not for the fact that Form2 is now the TOPMOST of all TOPMOST forms.

How do I tell the form/Windows that Form2 should be drawn?

Thanks.

Stefan

Re: Multiple HWND_TOPMOST forms get clipt

PostPosted: October 21st, 2011, 2:00 pm
by taazz2
have you tried Form2.invalidate or Form2.paint?

What you are describing here does not make sense why would you want to use the topmost windows in the first place. As I see it you are trying to hard to avoid modal dialogs for some reason and I would like to know why maybe there is a better solution.

Re: Multiple HWND_TOPMOST forms get clipt

PostPosted: October 23rd, 2011, 6:40 pm
by Kambiz
I do suggest to override WM_WINDOWPOSITIONCHANGING and force the second form to be always after the first form. Set AlwaysOnTop flag of the first form at design-time.

Re: Multiple HWND_TOPMOST forms get clipt

PostPosted: October 25th, 2011, 8:44 am
by Stefan
This was a piece of legacy code that I assumed to have worked in some circumstances.
As always the assumption is the mother of all f*** ups.

Calling SetWindowPos() in the constructor or just using plain old VCL fsStayOnTop apparently gives the desired result.

Thanks for your help and good work on SimpleGraph, the both of you :)

Stefan