Link to home
Start Free TrialLog in
Avatar of harveykane
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.
Avatar of vadim_ti
vadim_ti

it is like some side effect in your application
stayOnTop must work as expected
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 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.
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(Sender: TObject);
begin // button click
if not assigned(Form2) then
  Application.CreateForm(TForm2, Form2);
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.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE+SWP_NOSIZE);

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
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
hey harveycane, just use this in the child form's show method:

SetWindowPos(Handle,HWND_TOPMOST,Left,Top,Width,Height,0);
SetForegroundWindow(Handle);
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial