Discussion:
Locking a form to stay on top of another form
(too old to reply)
TG
2011-01-11 03:25:09 UTC
Permalink
I have been struggling with this for a while and have not found a
reliable solution. Here is the idea;

1. Mainform From1 is created when app starts
2. Form1 can become fullscreen (ie set border to none and maximize).
3. From2 has various buttons (like a toolbar) that needs to always be
on top of Form1 but not other apps.
4. I want Form2 to always stay on top of Form1.

After trying various StayOnTop etc code and much trial and error I
cannot get it to work as expected.

Bugs;

1. Form2 sometimes (no logic to the steps) goes behind Form1 so the
user has no buttons.
2. Form2 sometimes goes in front of all other Windows apps. So you
click to Windows Explorer and Form2 is in front. Clicking back and
forth a few times resolves the Z-Order.

Does anyone really know how to lock a form to another form in the
Delphi app alone? This is not for a system-wide stay on top form,
just for the single app. When form2 is visible it always must be
higher in the Z-Order than form1.

Thanks for any help. This is driving me mad.

TG
a***@aol.com
2011-01-11 07:45:39 UTC
Permalink
Post by TG
I have been struggling with this for a while and have not found a
reliable solution.  Here is the idea;
1. Mainform From1 is created when app starts
2. Form1 can become fullscreen (ie set border to none and maximize).
3. From2 has various buttons (like a toolbar) that needs to always be
on top of Form1 but not other apps.
4. I want Form2 to always stay on top of Form1.
After trying various StayOnTop etc code and much trial and error I
cannot get it to work as expected.
Bugs;
1. Form2 sometimes (no logic to the steps) goes behind Form1 so the
user has no buttons.
2. Form2 sometimes goes in front of all other Windows apps.  So you
click to Windows Explorer and Form2 is in front.  Clicking back and
forth a few times resolves the Z-Order.
Does anyone really know how to lock a form to another form in the
Delphi app alone?  This is not for a system-wide stay on top form,
just for the single app.  When form2 is visible it always must be
higher in the Z-Order than form1.
Have you investigated using Win API call to SetWindowPos() to set the
z-positions of the windows when you work within or away from the
application.

Also Application.NormalizeTopmosts/NormalizeAllTopmosts/
RestoreTopmosts may enable you to control the topmosticity of a form.

Alan Lloyd
a***@aol.com
2011-01-11 08:04:55 UTC
Permalink
Post by a***@aol.com
Have you investigated using Win API call to SetWindowPos() to set the
z-positions of the windows when you work within or away from the
application.
Also Application.NormalizeTopmosts/NormalizeAllTopmosts/
RestoreTopmosts may enable you to control the topmosticity of a form.
Look at the code for the above methods of TApplication in Forms.pas &
also of GetTopmostWindows() (in Delphi VCL) to find out how to
manipulate windows z-order.

Alan Lloyd
Hans-Peter Diettrich
2011-01-11 08:41:14 UTC
Permalink
Post by TG
Does anyone really know how to lock a form to another form in the
Delphi app alone?
From Win3.1 I know about child windows, which always stay on top of
their parents. If that window type is still available, it requires some
low level code to use it during form creation.

DoDi
Maarten Wiltink
2011-01-11 10:14:59 UTC
Permalink
Post by Hans-Peter Diettrich
Post by TG
Does anyone really know how to lock a form to another form in the
Delphi app alone?
From Win3.1 I know about child windows, which always stay on top of
their parents. If that window type is still available, it requires
some low level code to use it during form creation.
Wasn't that as simple as setting some Parent property during CreateParams?

Groetjes,
Maarten Wiltink
Hans-Peter Diettrich
2011-01-11 22:21:13 UTC
Permalink
Post by Maarten Wiltink
Post by Hans-Peter Diettrich
Post by TG
Does anyone really know how to lock a form to another form in the
Delphi app alone?
From Win3.1 I know about child windows, which always stay on top of
their parents. If that window type is still available, it requires
some low level code to use it during form creation.
Wasn't that as simple as setting some Parent property during CreateParams?
A correction: I meant *popup* windows, not child windows.

I'm not sure about "Parent" here; most probably it specifies the owner
of the window (hWndParent), with the wanted effect that a window always
sits on top of its owner. But there exist more implications.

Apart from that property the WNDCLASS styles distinguish between
WS_OVERLAPPED, WS_POPUP and WS_CHILD windows, what I had in mind.

DoDi
Mikey
2011-01-12 14:36:51 UTC
Permalink
Post by TG
I have been struggling with this for a while and have not found a
reliable solution. Here is the idea;
1. Mainform From1 is created when app starts
2. Form1 can become fullscreen (ie set border to none and maximize).
3. From2 has various buttons (like a toolbar) that needs to always be
on top of Form1 but not other apps.
4. I want Form2 to always stay on top of Form1.
After trying various StayOnTop etc code and much trial and error I
cannot get it to work as expected.
Bugs;
1. Form2 sometimes (no logic to the steps) goes behind Form1 so the
user has no buttons.
2. Form2 sometimes goes in front of all other Windows apps. So you
click to Windows Explorer and Form2 is in front. Clicking back and
forth a few times resolves the Z-Order.
Does anyone really know how to lock a form to another form in the
Delphi app alone? This is not for a system-wide stay on top form,
just for the single app. When form2 is visible it always must be
higher in the Z-Order than form1.
Thanks for any help. This is driving me mad.
TG
If I understand what you're trying to do, I think you need to rethink your design. It
sounds to me like a homegrown MDI.

If form2 is always going to be on top of form1, then why not just include it all on
one form? Or use a tab control?

Mike
JJ
2011-01-13 00:59:03 UTC
Permalink
This is one basic windowing feature that Delphi VCL is lacking.
What you need is the window ownership feature.
Like Maarteen Wiltink mentioned, you'll have to use CreateParams.
Override your Form2 CreateParams method like below.

TForm2 = class(TForm)
private
protected
procedure CreateParams(var Params: TCreateParams); override;
public
end;

Then for the CreateParams method...

procedure TFormOwned.CreateParams(var Params: TCreateParams);
begin
//let it be initialized like normal
inherited;
//set the parent window. but since Form2 is not a child window,
//then this field means the owner window
Params.WndParent:= Form1.Handle;
end;

Keep in mind that during the Form2 creation, the Form1 must already been
created. Otherwise you'll get exception error.
Post by TG
I have been struggling with this for a while and have not found a
reliable solution. Here is the idea;
1. Mainform From1 is created when app starts
2. Form1 can become fullscreen (ie set border to none and maximize).
3. From2 has various buttons (like a toolbar) that needs to always be
on top of Form1 but not other apps.
4. I want Form2 to always stay on top of Form1.
After trying various StayOnTop etc code and much trial and error I
cannot get it to work as expected.
Bugs;
1. Form2 sometimes (no logic to the steps) goes behind Form1 so the
user has no buttons.
2. Form2 sometimes goes in front of all other Windows apps. So you
click to Windows Explorer and Form2 is in front. Clicking back and
forth a few times resolves the Z-Order.
Does anyone really know how to lock a form to another form in the
Delphi app alone? This is not for a system-wide stay on top form,
just for the single app. When form2 is visible it always must be
higher in the Z-Order than form1.
Thanks for any help. This is driving me mad.
TG
Jamie
2011-01-13 01:30:10 UTC
Permalink
Post by JJ
This is one basic windowing feature that Delphi VCL is lacking.
What you need is the window ownership feature.
Like Maarteen Wiltink mentioned, you'll have to use CreateParams.
Override your Form2 CreateParams method like below.
TForm2 = class(TForm)
private
protected
procedure CreateParams(var Params: TCreateParams); override;
public
end;
Then for the CreateParams method...
procedure TFormOwned.CreateParams(var Params: TCreateParams);
begin
//let it be initialized like normal
inherited;
//set the parent window. but since Form2 is not a child window,
//then this field means the owner window
Params.WndParent:= Form1.Handle;
end;
Keep in mind that during the Form2 creation, the Form1 must already been
created. Otherwise you'll get exception error.
I've just used "SetParent(Form2.Handle,Form1.handle)"

Jamie
Maarten Wiltink
2011-01-13 09:02:35 UTC
Permalink
Post by Jamie
[...] Like Maarteen Wiltink mentioned, ...
I don't mind as much as I used to, but I'd like to _understand_ one of
these days: why do so many people double the 'e'?
Post by Jamie
Override your Form2 CreateParams method like below.
[...]
Post by Jamie
procedure TFormOwned.CreateParams(var Params: TCreateParams);
begin
//let it be initialized like normal
inherited;
//set the parent window. but since Form2 is not a child window,
//then this field means the owner window
Params.WndParent:= Form1.Handle;
end;
[...]
Post by Jamie
I've just used "SetParent(Form2.Handle,Form1.handle)"
That even has a certain elegance to it.

Where exactly do you place that call?

Groetjes,
Maarten Wiltink
a***@aol.com
2011-01-13 09:35:41 UTC
Permalink
Post by Maarten Wiltink
[...] Like Maarteen Wiltink mentioned, ...
I don't mind as much as I used to, but I'd like to _understand_ one of
these days: why do so many people double the 'e'?
It's for the same reason as many people spell my surname LLYOD or
LOYDD. Its called dyselxia <g>.

You _could_ change your name to Maartonly1en <g>.

Alan Lloyd
JJ
2011-01-13 11:55:52 UTC
Permalink
Post by Maarten Wiltink
Post by Jamie
[...] Like Maarteen Wiltink mentioned, ...
I don't mind as much as I used to, but I'd like to _understand_ one of
these days: why do so many people double the 'e'?
Uh, sorry. It's my keyboard having its own mind after accompanying me
for 16 years.
Post by Maarten Wiltink
Post by Jamie
I've just used "SetParent(Form2.Handle,Form1.handle)"
That even has a certain elegance to it.
Where exactly do you place that call?
Been wondering the same.
JJ
2011-01-13 11:50:03 UTC
Permalink
That certainly looks more efficient, but where should I put it?
If I put it in TForm2.FormCreate, Form2 will not be visible.
If I put it in TForm2.CreateParams, I get an exception instead.
Post by Jamie
I've just used "SetParent(Form2.Handle,Form1.handle)"
Jamie
Jamie
2011-01-14 01:53:27 UTC
Permalink
Post by JJ
That certainly looks more efficient, but where should I put it?
If I put it in TForm2.FormCreate, Form2 will not be visible.
If I put it in TForm2.CreateParams, I get an exception instead.
Post by Jamie
I've just used "SetParent(Form2.Handle,Form1.handle)"
Jamie
I just let the form be created in the invisible state, then
change the parent, then show it.


The form has to be valid before you can do that, of course.

Jamie

Loading...