Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Locking a form to stay on top of another form

712 views
Skip to first unread message

TG

unread,
Jan 10, 2011, 10:25:09 PM1/10/11
to
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

alang...@aol.com

unread,
Jan 11, 2011, 2:45:39 AM1/11/11
to

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

alang...@aol.com

unread,
Jan 11, 2011, 3:04:55 AM1/11/11
to

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

unread,
Jan 11, 2011, 3:41:14 AM1/11/11
to
TG schrieb:

> 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

unread,
Jan 11, 2011, 5:14:59 AM1/11/11
to
"Hans-Peter Diettrich" <DrDiet...@aol.com> wrote in message
news:8p2jhj...@mid.individual.net...
> TG schrieb:

Wasn't that as simple as setting some Parent property during CreateParams?

Groetjes,
Maarten Wiltink

Hans-Peter Diettrich

unread,
Jan 11, 2011, 5:21:13 PM1/11/11
to
Maarten Wiltink schrieb:

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

unread,
Jan 12, 2011, 9:36:51 AM1/12/11
to

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

unread,
Jan 12, 2011, 7:59:03 PM1/12/11
to
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.

Jamie

unread,
Jan 12, 2011, 8:30:10 PM1/12/11
to
JJ wrote:

> 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

unread,
Jan 13, 2011, 4:02:35 AM1/13/11
to
"Jamie" <jamie_ka1lpa_not_v...@charter.net> wrote in message
news:MmsXo.32977$My1....@newsfe16.iad...
> JJ wrote:

>> [...] 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'?


>> Override your Form2 CreateParams method like below.

[...]


>> 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;

[...]


> 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


alang...@aol.com

unread,
Jan 13, 2011, 4:35:41 AM1/13/11
to
On Jan 13, 9:02 am, "Maarten Wiltink" <maar...@kittensandcats.net>
wrote:
> "Jamie" <jamie_ka1lpa_not_valid_after_ka1l...@charter.net> wrote in message

>
> news:MmsXo.32977$My1....@newsfe16.iad...
>
> > JJ wrote:
> >> [...] 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

unread,
Jan 13, 2011, 6:50:03 AM1/13/11
to
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.

JJ

unread,
Jan 13, 2011, 6:55:52 AM1/13/11
to
Maarten Wiltink wrote:
>>> [...] 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.


>> 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.

Jamie

unread,
Jan 13, 2011, 8:53:27 PM1/13/11
to
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

0 new messages