Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

fsStayOnTop from a modal form

Status
Not open for further replies.

rcloutie

Programmer
May 26, 2005
164
CA
Hi all,

I have a modal form from which I call a detailed form with StayOnTop flag. All works fine but one thing: my form always stays over all other applications. I want it to be topmost but only within my app (if the caller is not modal, everythings ok)

I tried:
Setting FormStyle := fsStayOnTop
and
SetWindowPos(frm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW or SWP_NOACTIVATE);

The only solution I found yet, is to define the caller as a non-modal form. But I need it to be modal beacuse it returns the user's selection... pitfall...

Thanks in advance,

RC
 
I'm not sure I understand what you're looking to do.

Would SetForegroundWindow help?
 
1. form1.showmodal
2. form2.show (fsStayOnTop=True)
3. switch app
4. (form2 stays over the other app)

I don't like number 4.
I would like form2 to stay with my app (minimized).

Thanks
 
I don't understand why this would not work:

1. form1.showmodal
2. form1.hide
3. form2.showModal
4. form1.show

- Switch app
- form1 or form2 won't stay over the other app
- form2 still returns the user's selection

If form1 needs to be visible at the same time as form2, then skip 2 and 4.


Roo
Delphi Rules!
 
okay, so the issue is that form2 disappears if the app is switched? I played around and notice that form2 acts independently of form1 (the main form). I can minimize, maximize, etc, form2 and nothing happens, and if I switch to an app and back, it's gone. So basically you're wanting form2 to act as form1 does? I'm still not sure I understand.
 
Well, sorry for my poor english, nobody understands me...:(

> If form1 needs to be visible at the same time as form2, then skip 2 and 4.

form2 IS NOT a MODAL form.
It has the FLAG fsStayOnTop set.
It can be called from 2 different places:

1-form1 (MODAL form): user has to make a selection before coming back, but can open form2 for more information.
2-form3 (NON MODAL form): user can open form2 for more information.

> okay, so the issue is that form2 disappears if the app is switched?

No.
1- When called from form1 (MODAL form), form2 stays on top of all other apps (it's not the behavior I'm looking for).
2- When called from form3 (NON MODAL form), form2 stays on top within my app only (that's the behavior I want).

Thanks for trying to understand my problem...

Rej Cloutier
 
Your english is just fine...
form2 IS NOT a MODAL form.
Try it as a modal form just to see what I was suggesting in my prior post.
It has the FLAG fsStayOnTop set.
That's what's telling it to "stay on top of other apps", so dont' do that.
It can be called from 2 different places:
That should make no difference if shown as modal.

Roo
Delphi Rules!
 
Hi Roo,

I don't want to show form2 modally since it only displays additionnal information and FOCUS to form2 IS OPTIONAL.

form1 is modal and depending on a grid's selected row, form2 IS UPDATED ACCORDING TO form1 selection. That is, form1 tells to form2 which information to display.

If I keep form2 opened, then the user could use its arrow keys to move from one row to another within form1 grid. The problem I have is that form1 IS MODAL (if form2 is called from a non modal form all works fine as expected)

I don't use FormStyle=fsStayOnTop (but it has the same result). Here's how I set it actually...
-----------------------------------------------
procedure Tform2.FormShow(Sender: TObject);
begin
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;
------------------------------------------------

Thanks for help,

Rej Cloutier
 
Here's a sample to my problem...
Start a new project add 3 forms
1- unit=FMenu (name=frmMenu)
2- unit=Form1 (name=frmForm1)
3- unit=Form2 (name=frmForm2)
paste following code to each file.

---------------------------------------------------------
unit FMenu;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Form1;

type
TfrmMenu = class(TForm)
Label1: TLabel;
btnModal: TButton;
btnNonModal: TButton;
procedure btnModalClick(Sender: TObject);
procedure btnNonModalClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMenu: TfrmMenu;

implementation

{$R *.dfm}

procedure TfrmMenu.btnModalClick(Sender: TObject);
begin
if frmForm1.Visible then frmForm1.Close;
frmForm1.ShowModal;
end;
procedure TfrmMenu.btnNonModalClick(Sender: TObject);
begin
if frmForm1.Visible then frmForm1.Close;
frmForm1.Show;
end;

end.
-----------------------------------------------------------
unit Form1;

interface

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

type
TfrmForm1 = class(TForm)
Label1: TLabel;
btnform2: TButton;
ListBox1: TListBox;
procedure btnform2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmForm1: TfrmForm1;

implementation

{$R *.dfm}
uses Form2;

procedure TfrmForm1.FormShow(Sender: TObject);
begin
if (fsModal in FormState) then
Label1.Caption := Self.Caption + ' is modal.'
else
Label1.Caption := Self.Caption + ' is non-modal.';
ListBox1.ItemIndex := 0;
end;
procedure TfrmForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if frmForm2.Visible then frmForm2.Close;
end;
procedure TfrmForm1.btnform2Click(Sender: TObject);
begin
frmForm2.Show;
frmForm2.ShowSelection(ListBox1.Items[ListBox1.ItemIndex], (fsModal in FormState));
end;
procedure TfrmForm1.ListBox1Click(Sender: TObject);
begin
if frmForm2.Visible then
btnForm2.Click;
end;

end.
-----------------------------------------------------------
unit Form2;

interface

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

type
TfrmForm2 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Edit1: TEdit;
Label3: TLabel;
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure ShowSelection(sItem: String; bModal: Boolean);
end;

var
frmForm2: TfrmForm2;

implementation

{$R *.dfm}
uses Form1;

procedure TfrmForm2.FormShow(Sender: TObject);
begin
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE OR SWP_NOACTIVATE);
Top := frmForm1.Top;
Left := frmForm1.Left + (frmForm1.Width-Width);
end;
procedure TfrmForm2.ShowSelection(sItem: String; bModal: Boolean);
begin
Edit1.Text := sItem;
if bModal then
begin
Label3.Font.Color := clRed;
Label3.Caption := 'ONTOP OF ALL APPS.'+#13+'If you switch to another app,'+#13+'Form2 will still on top.';
end
else
begin
Label3.Font.Color := clGreen;
Label3.Caption := 'ONTOP OF MY APP ONLY.'+#13+'If you switch to another app,'+#13+'Form2 will still with my app.';
end;
end;

end.
-----------------------------------------------------------
 
Ah ah...
Human brain is smarter that computer CPU !!!

I found a trick to solve my problem: I wrote an event handler for Application.OnActivate and Application.OnDeactivate in which I set / unset the flag TOPMOST of Form2.

Here's the code of frmMenu to make it work properly (Form1 and Form2 are ok):
-----------------------------------------------------------
unit FMenu;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Form1, Form2;

type
TfrmMenu = class(TForm)
Label1: TLabel;
btnModal: TButton;
btnNonModal: TButton;
procedure btnModalClick(Sender: TObject);
procedure btnNonModalClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure AppActivate(Sender: TObject);
procedure AppDeactivate(Sender: TObject);
public
{ Public declarations }
end;

var
frmMenu: TfrmMenu;

implementation

{$R *.dfm}

procedure TfrmMenu.FormCreate(Sender: TObject);
begin
Application.OnActivate := AppActivate;
Application.OnDeactivate := AppDeactivate;
end;
procedure TfrmMenu.AppActivate(Sender: TObject);
begin
if frmForm2.Visible then
SetWindowPos(frmForm2.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;
procedure TfrmMenu.AppDeactivate(Sender: TObject);
begin
if frmForm2.Visible then
SetWindowPos(frmForm2.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;

procedure TfrmMenu.btnModalClick(Sender: TObject);
begin
if frmForm1.Visible then frmForm1.Close;
frmForm1.ShowModal;
end;
procedure TfrmMenu.btnNonModalClick(Sender: TObject);
begin
if frmForm1.Visible then frmForm1.Close;
frmForm1.Show;
end;

end.
-----------------------------------------------------------

Thanks for reading,

Rej CLoutier
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top