AncientDreamer
asked on
Issues with putting a form behind everything else on the desktop
Hello.
I'm hoping someone can clarify an issue for me, and suggest a solution.
I need to display a form containing data collected, when it arrives, but I
want the form to appear behind whatever other windows are showing on the user's
desktop, so as not to disturb whatever they may be doing at the moment.
(By the way, the application's main window is not displayed, either, but
rather "minimized to the icon tray")
As long as I let Delphi auto-create the form for me, the following worked
fine:
if PopUnder then
begin
ShowWindow(frmNewMail.Hand le, SW_SHOWNOACTIVATE);
frmNewMail.Visible := true;
end
The form does not receive focus AND it appears behind everything else on the
desktop. The form was removed from view using a standard Close, when the
user clicked a button.
Now, I wish to create this form at run-time, and it has been removed
from Delphi's auto-create list. Instead I use:
if not VNewMailWinExists then
begin
VNewMailWinExists := true;
vNewMailWin := TfrmVNewMail.Create;
end;
......
if PopUnder then
begin
vNewMailWin.SendToBack;
ShowWindow(vNewMailWin.Han dle, SW_SHOWNOACTIVATE);
vNewMailWin.Visible := true;
end
And the form is set to caFree when asked to Close.
With this scheme, the Form behaves as expected the first time it is
displayed, but on subsequent runs of the above code lines, the form appears
in front of everything else (but unfocused, as expected).
(The forms Create method has been overridden, and the Owner is set to Nil,
rather than Application. Setting Owner to Application (as a test) did not
seem to have any effect, though)
So, the question is, can someone please explain why this is happening, i.e.
why does it appear behind on the first run, and on top after that?
And why is a run time created form behaving differently from a Delphi
created one?
A suggestion for a good way to do this will be appreciated.
FYI, adding:
SetWindowPos(vNewMailWin.H andle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE
or SWP_NOSIZE or SWP_NOACTIVATE);
works, but seems to have the undesireable effect that the user must click
the top, form bar to bring the form into view, instead of just clicking
anywhere on the form.
I'm hoping someone can clarify an issue for me, and suggest a solution.
I need to display a form containing data collected, when it arrives, but I
want the form to appear behind whatever other windows are showing on the user's
desktop, so as not to disturb whatever they may be doing at the moment.
(By the way, the application's main window is not displayed, either, but
rather "minimized to the icon tray")
As long as I let Delphi auto-create the form for me, the following worked
fine:
if PopUnder then
begin
ShowWindow(frmNewMail.Hand
frmNewMail.Visible := true;
end
The form does not receive focus AND it appears behind everything else on the
desktop. The form was removed from view using a standard Close, when the
user clicked a button.
Now, I wish to create this form at run-time, and it has been removed
from Delphi's auto-create list. Instead I use:
if not VNewMailWinExists then
begin
VNewMailWinExists := true;
vNewMailWin := TfrmVNewMail.Create;
end;
......
if PopUnder then
begin
vNewMailWin.SendToBack;
ShowWindow(vNewMailWin.Han
vNewMailWin.Visible := true;
end
And the form is set to caFree when asked to Close.
With this scheme, the Form behaves as expected the first time it is
displayed, but on subsequent runs of the above code lines, the form appears
in front of everything else (but unfocused, as expected).
(The forms Create method has been overridden, and the Owner is set to Nil,
rather than Application. Setting Owner to Application (as a test) did not
seem to have any effect, though)
So, the question is, can someone please explain why this is happening, i.e.
why does it appear behind on the first run, and on top after that?
And why is a run time created form behaving differently from a Delphi
created one?
A suggestion for a good way to do this will be appreciated.
FYI, adding:
SetWindowPos(vNewMailWin.H
or SWP_NOSIZE or SWP_NOACTIVATE);
works, but seems to have the undesireable effect that the user must click
the top, form bar to bring the form into view, instead of just clicking
anywhere on the form.
vadim_ti , that's exactly what i was thinking of writing! - great minds think alike
You may also want
application.sendtoback; //different from form1.sendtoback - moves whole app to back
Regards,
Hypoviax
You may also want
application.sendtoback; //different from form1.sendtoback - moves whole app to back
Regards,
Hypoviax
and... you may want to remove the timer1.Enabled:= false; in order to keep the form continually to the back. If i am wrong ignore this :-)
if i remove
timer1.Enabled:= false
will be very difficult to see a form :-)
it is from author post
==========================
FYI, adding:
SetWindowPos(vNewMailWin.H andle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE
or SWP_NOSIZE or SWP_NOACTIVATE);
works, but seems to have the undesireable effect that the user must click
the top, form bar to bring the form into view, instead of just clicking
anywhere on the form.
========================== =======
timer1.Enabled:= false
will be very difficult to see a form :-)
it is from author post
==========================
FYI, adding:
SetWindowPos(vNewMailWin.H
or SWP_NOSIZE or SWP_NOACTIVATE);
works, but seems to have the undesireable effect that the user must click
the top, form bar to bring the form into view, instead of just clicking
anywhere on the form.
==========================
Ok, fair enough
Hypoviax
Hypoviax
at vNewMailWin's OnClose, perhaps you would like to put a
Action := caFree;
statement, so that you will recreate the window everytime you need it?
Action := caFree;
statement, so that you will recreate the window everytime you need it?
You seen my Speed post (the one with Workshop_Alex) yet DragonSlayer? - Ill challenge you guys to a speed comp with sorting early november
Nah, I'm not really good in all these speed challenges ;-)
Haha,you're better than me though. It'll be interesting.
Back to the question:
Would having OnClick events help in terms of the problem with the user clicking anywhere on the form?
Regards,
Hypoviax
Back to the question:
Would having OnClick events help in terms of the problem with the user clicking anywhere on the form?
Regards,
Hypoviax
ASKER
Thank you all for your responses, but we're not quite there yet.
A few comments to your answers:
DragonSlayer:
Yes, I do free the form with Action := caFree;
Hypoviax:
Application.SendToBack is not quite it, because sometimes the main window wil be open, and we would not want that sent to the back along with the data form.
The OnClicks would have to be implemented for all parts of the form, I'm thinking, because you never know where the user might happen to point his cursor?
I will test vadim_ti's initial suggestion to see what happens.
However, I'm still very curious as to why the initial approach worked perfectly when Delphi created the form, while I now get a different result. I.e. in waht ways is my run time created form different from what Delphi created with the Application.CreateForm(..) statement?
Cheers,
AD
A few comments to your answers:
DragonSlayer:
Yes, I do free the form with Action := caFree;
Hypoviax:
Application.SendToBack is not quite it, because sometimes the main window wil be open, and we would not want that sent to the back along with the data form.
The OnClicks would have to be implemented for all parts of the form, I'm thinking, because you never know where the user might happen to point his cursor?
I will test vadim_ti's initial suggestion to see what happens.
However, I'm still very curious as to why the initial approach worked perfectly when Delphi created the form, while I now get a different result. I.e. in waht ways is my run time created form different from what Delphi created with the Application.CreateForm(..)
Cheers,
AD
>>>The OnClicks would have to be implemented for all parts of the form, I'm thinking
That's what i was thinking.
regards,
Hypoviax
That's what i was thinking.
regards,
Hypoviax
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Like:
vNewMailWin := Application.CreateForm(Tfr mVNewMail) ;
Havn't tested - just an idea
Hypoviax
vNewMailWin := Application.CreateForm(Tfr
Havn't tested - just an idea
Hypoviax
ASKER
More information:
I have now tried using SendToBack in the data form, but the results were discouraging.
With a bit of fiddling, I could (again) make it work perfectly the first time the data form is created and shown (It "pops under" and does not grab focus), but after it has been destroyed, all subsequent appearances of the form behave differently; In some versions it appears on top, with focus, or alternatively it "pops under", but still grabs focus.
The third variant had it appear in front, then quickly go to the back, but this causes an annoying "flicker" on the screen.
So, as a follow up to the question about why Delphi created forms and run time created forms behave differently, I would like to know why a run time created form behaves as expected the first time, but not subsequently.
(As far as I can tell from using break points, the same code is executed each time)
I have now tried using SendToBack in the data form, but the results were discouraging.
With a bit of fiddling, I could (again) make it work perfectly the first time the data form is created and shown (It "pops under" and does not grab focus), but after it has been destroyed, all subsequent appearances of the form behave differently; In some versions it appears on top, with focus, or alternatively it "pops under", but still grabs focus.
The third variant had it appear in front, then quickly go to the back, but this causes an annoying "flicker" on the screen.
So, as a follow up to the question about why Delphi created forms and run time created forms behave differently, I would like to know why a run time created form behaves as expected the first time, but not subsequently.
(As far as I can tell from using break points, the same code is executed each time)
ASKER
Hypoviax:
I believe I did try vNewMailWin := Application.CreateForm(Tfr mVNewMail) ; at one point, but ended up not using it. I'll try that again now.
I believe I did try vNewMailWin := Application.CreateForm(Tfr
if you use my example you need in design time to define
Timer1.enabled := false;
timer1.interval := 1
so all must be fine
Timer1.enabled := false;
timer1.interval := 1
so all must be fine
if you do not want form2 grab focus
add to timer handle event
form1.SetFocus
add to timer handle event
form1.SetFocus
ASKER
This is the solution that appears to work the way I want:
if not VNewMailWinExists then
begin
VNewMailWinExists := true;
Application.CreateForm(Tfr mVNewMail, vNewMailWin);
vNewMailWin.Visible := false;
end;
........ more code ....
if not vNewMailWin.Visible then
begin
if PopUnder then
begin
SetWindowPos(vNewMailWin.H andle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
ShowWindow(vNewMailWin.Han dle, SW_SHOWNOACTIVATE);
vNewMailWin.Visible := true;
end
else
begin
ShowWindow(vNewMailWin.Han dle, SW_SHOW);
vNewMailWin.Visible := true;
Application.BringToFront;
end;
end;
As regards the solution, Hypoviax was the closest and will get the points, unless someone manages to answer my questions about exactly what's going on. I hate applying a fix and not knowing why it works.
I'm leaving this open for another 1-2 days, in the hope that the questions will be answered.
(Btw. is it now possible to split points between contributors? I know many asked for that in the past)
if not VNewMailWinExists then
begin
VNewMailWinExists := true;
Application.CreateForm(Tfr
vNewMailWin.Visible := false;
end;
........ more code ....
if not vNewMailWin.Visible then
begin
if PopUnder then
begin
SetWindowPos(vNewMailWin.H
ShowWindow(vNewMailWin.Han
vNewMailWin.Visible := true;
end
else
begin
ShowWindow(vNewMailWin.Han
vNewMailWin.Visible := true;
Application.BringToFront;
end;
end;
As regards the solution, Hypoviax was the closest and will get the points, unless someone manages to answer my questions about exactly what's going on. I hate applying a fix and not knowing why it works.
I'm leaving this open for another 1-2 days, in the hope that the questions will be answered.
(Btw. is it now possible to split points between contributors? I know many asked for that in the past)
You should be able to split points, although some people have had trouble for some reason.
>> exactly what's going on
Not completely sure myself, but it may be because when you create that form (using the other method) it is local to that procedure. With the application.createform(..) it is global and so thus will continue to work after the first time.
If this is correct then if you declare your vNewMailWin in the private or public delaration section it should be global and will work as expected. You can but try, but i think this may be the reason
Regards,
Hypoviax
>> exactly what's going on
Not completely sure myself, but it may be because when you create that form (using the other method) it is local to that procedure. With the application.createform(..)
If this is correct then if you declare your vNewMailWin in the private or public delaration section it should be global and will work as expected. You can but try, but i think this may be the reason
Regards,
Hypoviax
Thanks
Main form:
=======
procedure TForm1.Button1Click(Sender
begin
TForm2.Create(self).Show
end;
form2:
====
procedure TForm2.FormShow(Sender: TObject);
begin
timer1.Enabled:= true;
end;
procedure TForm2.Timer1Timer(Sender:
begin
SendToBack;
timer1.Enabled:= false;
end;