STAY ON TOP - no matter what.

I need my form to stay on top of everything.  Setting the stay on top property to true is not enough, because when I start another program which also is stay on top, it covers my form.

A good example would be the windows NT/2000/XP task manager.  I want my form to be able to cover it and any other windows/forms that may come along.

I know this is possible because I saw a program that could lock any windows workstation, even XP and 2K.
When you pressed the ctrl-shift-esc key to try to open the task-manager, it was like the program immediately got focus again and covered the task-manager even before I was able to see it.

200 points for a good solution and maybe even more.  This is pretty urgent.
What is a good way to do this?  I'd preferably not use any 3rd-party components though.

Thanks in advance,
Hagur
LVL 3
hagurAsked:
Who is Participating?
 
SteveWaiteConnect With a Mentor Commented:
hi, just interested :)
0
 
tongaliteConnect With a Mentor Commented:
Hi,
I had this in my tips bin... It might be of some help to you. Good luck
T.
...........................................
How to force a window 'always on top' without interference with other programs
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure SetStayOnTop(OnTop: Boolean);
    procedure WinMsg(var Msg: TMsg; var Handled: Boolean);
  public
    property StayOnTop: boolean read FStayOnTop write SetStayOnTop;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const
  WM_ALWAYSONTOP = 99;

procedure TForm1.FormCreate(Sender: TObject);
begin
  inherited Create(AOwner);
  Application.OnMessage := WinMsg;
  AppendMenu(GetSystemMenu(Handle, False), MF_SEPARATOR, 0, '');
  AppendMenu(GetSystemMenu(Handle, False), MF_BYPOSITION, WM_ALWAYSONTOP,
'Always on &Top');
end;

procedure TForm1.WinMsg (var Msg: TMsg; var Handled: Boolean);
begin
  if Msg.message = WM_SYSCOMMAND then
    if Msg.WPARAM = WM_ALWAYSONTOP then
      StayOnTop := not StayOnTop;
end;

procedure TForm1.SetStayOnTop(OnTop: Boolean);
begin
  FStayOnTop := OnTop;

  if FStayOnTop then begin
    SetWindowPos(handle, HWND_TOPMOST, Left, Top, Width, Height, 0);
    CheckMenuItem(GetSystemMenu(Handle, False), WM_ALWAYSONTOP, MF_CHECKED);
  end
  else begin
    SetWindowPos(handle, HWND_NOTOPMOST, Left, Top, Width, Height, 0);
    CheckMenuItem(GetSystemMenu(Handle, False), WM_ALWAYSONTOP,
MF_UNCHECKED);
  end;
end;
end.
.................................................
0
 
GwenaCommented:
listening :-)
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
geobulConnect With a Mentor Commented:
Hi,
Try this one:

type
  TForm1 = class(TForm)
    procedure OnTop(SendeR: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.OnTop(SendeR: TObject);
begin
  SetWindowPos(form1.handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOACTIVATE or SWP_NOSIZE);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnDeactivate := OnTop;
end;

Regards, Geo
0
 
ginsonicCommented:
listening ... for moment
0
 
hagurAuthor Commented:
Thanks guys.

Tongalite: When I try to run your code, I always get an error in this line:
property StayOnTop: boolean read FStayOnTop write SetStayOnTop;

The error I get is: "Field or method identifier expected"
I'm using Delphi 5.0

Geobul: Your code almost works ... my program can now cover the task-manager, but when I use ALT-TAB to switch to the task manager, it sometimes manages to stay on top of my form, but sometimes not.  Weird!

Any solutions?
0
 
ginsonicConnect With a Mentor Commented:
Set the formStyle to fsStayOnTop and then handle WM_ENABLE and WM_WINDOWPOSCHANGING messages.

procedure WMEnable(var Msg: TWMEnable); message WM_ENABLE;
procedure WMWindowPosChanging(var Msg: TWMWindowPosMsg); message WM_WINDOWPOSCHANGING;
................

procedure TForm1.WMEnable(var Msg: TWMEnable);
begin
 inherited;
 if Visible and not Msg.Enabled then
 begin
   SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0,
     SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
   EnableWindow(Handle, True);
   Application.NormalizeAllTopMosts;
   SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0,
     SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);
 end;
end;

procedure TForm1.WMWindowPosChanging(var Msg: TWMWindowPosMsg);
begin
 inherited;
 if Visible then
   with Msg.WindowPos^ do
   begin
     if (flags and SWP_NOZORDER) = 0 then
       hwndInsertAfter := HWND_TOP;
   end;
end;
0
 
surodimedjoCommented:
put this on formcreate

procedure TForm1.FormCreate(Sender: TObject);
begin
setwindowpos(form1.Handle,hwnd_notopmost,0,0,getsystemmetrics(sm_cxscreen),getsystemmetrics(sm_cyscreen),0);
setwindowpos(form1.Handle,hwnd_topmost,0,0,getsystemmetrics(sm_cxscreen),getsystemmetrics(sm_cyscreen),swp_nomove);
setforegroundwindow(form1.Handle);

SetWindowLongA(Handle,GWL_style,WS_EX_TOOLWINDOW);
end;

don't forget to build back door for your application, i use
  PopupMenu1: TPopupMenu;

and in the exit button
exit1: TMenuItem;

procedure TForm1.exit1Click(Sender: TObject);
begin
   close;
end;

i hope u can enjoy this answer
0
 
ginsonicCommented:
surodimedjo,

I see that you are new expert here at Ex-Ex. We ( the other experts ) have a rule . We just add comments and not give directly answers.

The result of this rule is that we don't block the question and we let the freedom to asker to choice the best solution for her needs .

In same time he can ask more support to improve a comment from list .

Untill your answer will be evaluate ( accepted or rejected ) I doubt that someelse will add comments .

Best regards,
Nick

P.S. Of course you are free to do what you want.
0
 
SteveWaiteCommented:
Hi hagur! I just warn you that those answers suggesting including setwindowpos in form create event will go wrong after user moves your program to another monitor or alters the screen resolution.
Regards,
Steve
0
 
ginsonicCommented:
For this reason I suggest to hook WMWindowPosChanging messages.
0
 
geobulCommented:
Hi,
I think that (SWP_NOMOVE or SWP_NOSIZE) in uFlags means that the function will ignore x,y,cx and cy parameters. So the window changes its Z order only. That's why there won't be any problems altering screen resolution or monitor type. Am I wrong?

Regards, Geo
0
 
hagurAuthor Commented:
surodimedjo:  Read Ginsonic's post to see why I rejected your answer.
0
 
hagurAuthor Commented:
ginsonic:

This isn't working .... the form can not cover other forms that have the "stay on top" form-style.
0
 
ginsonicCommented:
thinking to another way ..........
0
 
xsoftCommented:
listening
0
 
CleanupPingCommented:
hagur:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.