Solved

Delphi: Keeping a Form on top

Posted on 2004-09-30
12
359 Views
Last Modified: 2010-04-05
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.
0
Comment
Question by:harveykane
12 Comments
 
LVL 6

Expert Comment

by:vadim_ti
ID: 12196180
it is like some side effect in your application
stayOnTop must work as expected
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12197138
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.
0
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 12197430
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.
0
Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

 
LVL 1

Expert Comment

by:ZaSz
ID: 12202468
0
 
LVL 34

Expert Comment

by:Slick812
ID: 12203101
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
0
 
LVL 1

Expert Comment

by:Binsky
ID: 12235067
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!
0
 
LVL 2

Expert Comment

by:cula99
ID: 12247937
Set Main form FormStyle to fsMDIForm leave rest as it is and that's it.

Čula
0
 
LVL 2

Expert Comment

by:cula99
ID: 12247956
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
0
 
LVL 1

Expert Comment

by:fidel83
ID: 12859768
hey harveycane, just use this in the child form's show method:

SetWindowPos(Handle,HWND_TOPMOST,Left,Top,Width,Height,0);
SetForegroundWindow(Handle);
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 13442911
PAQed with no points refunded (of 100)

modulo
Community Support Moderator
0

Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question