harveykane
asked on
Delphi: Keeping a Form on top
I have an application that has a main form, and several other forms that are triggered (form.show) by buttons on the main form.
The main form runs more or less full screen (either maximised or as a window taking most of the desktop area).
Any pop up forms need to stay on top. You can have one or more pop-up forms open at any given time, and be able to work with either pop-up form.
The main form's FormStyle is set to fsNormal and all popup forms are set to fsStayOnTop. The popup forms can't be called by ShowModal because you may be working with several popup forms at any given time.
The following problem occurs intermittantly, on some computers more often than others.
The pop-up windows tend to disappear behind the main form, either immediately after calling form.show or after 5 or 10 seconds. The only way to get them back is to move the main form out of the way and click to regain focus, or to call the form.show method again from the main form (both unsatisfactory).
I want the pop-up forms to stay on top of the main form no matter what., I thought this is what the fsStayOnTop setting was for, but it does not work as expected.
There is a TTimer component on the main form which updates the main form every 2 mins, but the pop-up forms dissappearing do not appear to be linked to this.
Any thoughts on this would be appreciated.
The main form runs more or less full screen (either maximised or as a window taking most of the desktop area).
Any pop up forms need to stay on top. You can have one or more pop-up forms open at any given time, and be able to work with either pop-up form.
The main form's FormStyle is set to fsNormal and all popup forms are set to fsStayOnTop. The popup forms can't be called by ShowModal because you may be working with several popup forms at any given time.
The following problem occurs intermittantly, on some computers more often than others.
The pop-up windows tend to disappear behind the main form, either immediately after calling form.show or after 5 or 10 seconds. The only way to get them back is to move the main form out of the way and click to regain focus, or to call the form.show method again from the main form (both unsatisfactory).
I want the pop-up forms to stay on top of the main form no matter what., I thought this is what the fsStayOnTop setting was for, but it does not work as expected.
There is a TTimer component on the main form which updates the main form every 2 mins, but the pop-up forms dissappearing do not appear to be linked to this.
Any thoughts on this would be appreciated.
what about this code for the pop-up form:
unit Unit2_Q_21151827;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm2 = class(TForm)
Edit: TEdit;
private { Private declarations }
procedure CreateParams(var Params: TCreateParams); override;
public { Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited;
with Params do
ExStyle := ExStyle or WS_EX_TOPMOST;
end;
end.
unit Unit2_Q_21151827;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm2 = class(TForm)
Edit: TEdit;
private { Private declarations }
procedure CreateParams(var Params: TCreateParams); override;
public { Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited;
with Params do
ExStyle := ExStyle or WS_EX_TOPMOST;
end;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure OnShowWindow(var Msg: TWMShowWindow); message WM_SHOWWINDOW;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.FormStyle := fsStayOnTop;
end;
procedure TForm1.OnShowWindow(var Msg: TWMShowWindow);
begin
if not Msg.Show then
Msg.Result := 0
else
inherited;
end;
end.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure OnShowWindow(var Msg: TWMShowWindow); message WM_SHOWWINDOW;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.FormStyle := fsStayOnTop;
end;
procedure TForm1.OnShowWindow(var Msg: TWMShowWindow);
begin
if not Msg.Show then
Msg.Result := 0
else
inherited;
end;
end.
Take a look here: https://www.experts-exchange.com/questions/20668766/I-want-my-window-to-stay-on-top-of-all-other-windows.html
It worked for me.
It worked for me.
hello harveykane, I am guessing from your description, that your Pop-Up Forms, are some sort of "Tool window" functional forms used only with your program, if so, the fsStayOnTop may not be what you want to use, for secondary forms Form2, this fsStayOnTop seems not to go correctly sometimes? I have programs with small Pop-Up tool windows, that were Always ontop of the main Form, (but NOT on top of ALL windows, just main form), by using this code -
code for "Tool" form -
type
TForm2 = class(TForm)
Button1: TButton;
private
{ Private declarations }
protected
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.DFM}
uses GrafEdit1; // main form
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
//Params.Style := (Params.Style and not WS_CHILD) or WS_POPUP;
Params.WndParent := Form1.Handle;
// Params.WndParent will make it always on top of that form
end;
= = == = = = = = = = = = = = = = = = = = = = = = =
code for main form -
implementation
{$R *.DFM}
uses toolForm;
procedure TForm1.but_ShowToolClick(S ender: TObject);
begin // button click
if not assigned(Form2) then
Application.CreateForm(TFo rm2, Form2);
Form2.Show;
end;
- - - - - - - - - - - - - - - - - - - - - - - - - --
ask questions if you need more information
code for "Tool" form -
type
TForm2 = class(TForm)
Button1: TButton;
private
{ Private declarations }
protected
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.DFM}
uses GrafEdit1; // main form
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
//Params.Style := (Params.Style and not WS_CHILD) or WS_POPUP;
Params.WndParent := Form1.Handle;
// Params.WndParent will make it always on top of that form
end;
= = == = = = = = = = = = = = = = = = = = = = = = =
code for main form -
implementation
{$R *.DFM}
uses toolForm;
procedure TForm1.but_ShowToolClick(S
begin // button click
if not assigned(Form2) then
Application.CreateForm(TFo
Form2.Show;
end;
- - - - - - - - - - - - - - - - - - - - - - - - - --
ask questions if you need more information
using the formstyle property fsStayOntop can cause some strange behaviour, I also advise using the SetWindowPos call to put (and keep) your forms on top, without them disappearing to the background when clicking somewhere else.
The line of code needed :
SetWindowPos(YourForm.Hand le, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE+SWP_NOSIZE);
I had the same annoying problem, and this solved it for me...
Good luck!
The line of code needed :
SetWindowPos(YourForm.Hand
I had the same annoying problem, and this solved it for me...
Good luck!
Set Main form FormStyle to fsMDIForm leave rest as it is and that's it.
Čula
Čula
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Panel1: TPanel;
Edit1: TEdit;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Unit2, Unit3, Unit4;
{$R *.dfm}
procedure TForm1.Button1Click(Sender : TObject);
begin
Form2.Show;
end;
procedure TForm1.Button2Click(Sender : TObject);
begin
Form3.Show;
end;
procedure TForm1.Button3Click(Sender : TObject);
begin
Form4.Show;
end;
end.
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm2 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
end.
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm3 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
end.
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm4 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
end.
object Form1: TForm1
Left = 195
Top = 107
Width = 870
Height = 640
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsMDIForm
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 16
Top = 32
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 96
Top = 32
Width = 75
Height = 25
Caption = 'Button3'
TabOrder = 1
OnClick = Button2Click
end
object Button3: TButton
Left = 176
Top = 32
Width = 75
Height = 25
Caption = 'Button4'
TabOrder = 2
OnClick = Button3Click
end
object Panel1: TPanel
Left = 16
Top = 88
Width = 817
Height = 481
Caption = 'Panel1'
TabOrder = 3
object Label1: TLabel
Left = 16
Top = 8
Width = 32
Height = 13
Caption = 'Label1'
end
object Edit1: TEdit
Left = 16
Top = 24
Width = 121
Height = 21
TabOrder = 0
Text = 'Edit1'
end
end
end
object Form2: TForm2
Left = 89
Top = 232
Width = 306
Height = 267
Caption = 'Form2'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
end
object Form3: TForm3
Left = 950
Top = 168
Width = 223
Height = 730
Caption = 'Form3'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
end
object Form4: TForm4
Left = 122
Top = 761
Width = 945
Height = 193
Caption = 'Form4'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
end
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Panel1: TPanel;
Edit1: TEdit;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Unit2, Unit3, Unit4;
{$R *.dfm}
procedure TForm1.Button1Click(Sender
begin
Form2.Show;
end;
procedure TForm1.Button2Click(Sender
begin
Form3.Show;
end;
procedure TForm1.Button3Click(Sender
begin
Form4.Show;
end;
end.
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm2 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
end.
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm3 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
end.
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm4 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
end.
object Form1: TForm1
Left = 195
Top = 107
Width = 870
Height = 640
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsMDIForm
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 16
Top = 32
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 96
Top = 32
Width = 75
Height = 25
Caption = 'Button3'
TabOrder = 1
OnClick = Button2Click
end
object Button3: TButton
Left = 176
Top = 32
Width = 75
Height = 25
Caption = 'Button4'
TabOrder = 2
OnClick = Button3Click
end
object Panel1: TPanel
Left = 16
Top = 88
Width = 817
Height = 481
Caption = 'Panel1'
TabOrder = 3
object Label1: TLabel
Left = 16
Top = 8
Width = 32
Height = 13
Caption = 'Label1'
end
object Edit1: TEdit
Left = 16
Top = 24
Width = 121
Height = 21
TabOrder = 0
Text = 'Edit1'
end
end
end
object Form2: TForm2
Left = 89
Top = 232
Width = 306
Height = 267
Caption = 'Form2'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
end
object Form3: TForm3
Left = 950
Top = 168
Width = 223
Height = 730
Caption = 'Form3'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
end
object Form4: TForm4
Left = 122
Top = 761
Width = 945
Height = 193
Caption = 'Form4'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
end
hey harveycane, just use this in the child form's show method:
SetWindowPos(Handle,HWND_T OPMOST,Lef t,Top,Widt h,Height,0 );
SetForegroundWindow(Handle );
SetWindowPos(Handle,HWND_T
SetForegroundWindow(Handle
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
stayOnTop must work as expected