Hiding Main Window but not child

766 views
Skip to first unread message

Network Admin

unread,
Jul 22, 2001, 2:10:05 AM7/22/01
to
Hi All,
Ok, what's the trick? I would like to be able to minimize the main window
of an application but not any child windows it may have open. I've tried
all kinds of window types and MyForm := TMyForm.Create verses
Application.CreateForm(TMyForm, MyForm), but can't seem to figure it out.
Anytime I minimize the main application windows any other windows minimize
as well. I'm sure it's something simple (always is....) Any help
appreciated!

Thanks!
- Brent

Peter Below (TeamB)

unread,
Jul 22, 2001, 6:38:33 AM7/22/01
to

Well, you need to know some internal details about how the VCL handles stuff
when you minimize the main form. There is special code in
Tcustomform.WMSyscommand that handles the main form differently than other
forms. When a minimize request (WM_SYSCOMMAND with wparam = SC_MINIMIZE)
comes in for the main form it is not passed on the the inherited message
handler, instead the form hides and the Application window is minimized
through a call to Application.Minimize. Since all other forms in the
application have the Application window as owner (in the API sense, not the
VCL sense) Windows automatically hides them all. The default taskbar button
belongs to the Application window (a zero-size API window, not a Delphi form,
by the way), not to the main form.

If you want to be able to minimize all forms in your application
independently from each other you have three options. The first would be to
remove the special caseing code for WM_SYSCOMMAND. For that you would add a
handler for that message to the main form like this:

private // form declaration
Procedure WMSyscommand(Var msg: TWmSysCommand);
message WM_SYSCOMMAND;

Procedure TForm1.WMSyscommand(Var msg: TWmSysCommand);
Begin
Case (msg.cmdtype and $FFF0) of
SC_MINIMIZE: Begin
ShowWindow( handle, SW_MINIMIZE );
msg.result := 0;
End;
SC_RESTORE: Begin
ShowWindow( handle, SW_RESTORE );
msg.result := 0;
End;
Else
inherited;
End;
End;

Like all other forms the main form will now minimize to the desktop, the
taskbar button cannot be used to restore it. This is the easiest solution if
you do not want each form to have its own taskbar button instead of
minimizing to the desktop.

If you want to have that there is more work to do (option 2). The first task
is to get rid of the default taskbar button for the Application window. Do
this in the main forms OnCreate event:

ShowWindow( Application.handle, SW_HIDE );
SetWindowLong( Application.handle,
GWL_EXSTYLE,
GetWindowLong( application.handle, GWL_EXSTYLE ) and
not WS_EX_APPWINDOW or WS_EX_TOOLWINDOW);
ShowWindow( Application.handle, SW_SHOW );

To get a task bar button for each form and have it minimize to the taskbar
instead of to the desktop, override the CreateParams method of the main form
and also of all the secondary forms like this:

// in form declaration
Procedure CreateParams( Var params: TCreateParams ); override;


Procedure TFormXYZ.CreateParams( Var params: TCreateParams );
begin
inherited CreateParams( params );
params.ExStyle := params.ExStyle or WS_EX_APPWINDOW;
end;

One work of warning: if, in this setup, you *ever* call Application.Minimize
the app will vanish (for the user) into Nirwana, since all forms and their
taskbar buttons will be hidden! So you need to restore the Applications
taskbar button before you do that, or the user has no means to ever restore
the app!

I mentioned an option 3. This is to make the secondary forms owned by the
desktop, not the Application window (owned in the API sense again). For that
you leave the main form and the Application window alone and override
CreateParams for all secondary forms:

procedure TForm2.CreateParams(Var params: TCreateParams);
begin
inherited CreateParams( params );
params.ExStyle := params.ExStyle or WS_EX_APPWINDOW;
params.WndParent := GetDesktopwindow;
end;

Note that this can cause some problems with modal forms shown from
secondary forms. If the user switches away from the app while a modal
form is up and then back to the form that showed it the modal form may
hide beneath the form. It is possible to deal with this by making sure
the modal form is parented to the form that showed it (using
params.WndParent as above) but this is not possible with the standard
dialogs from the Dialogs unit and exceptions, which need more effort to
get them to work right (basically handling Application.OnActivate,
looking for modal forms parented to Application via GetLastActivepopup
and bringing them to the top of the Z-order via SetWindowPos).

Peter Below (TeamB) 10011...@compuserve.com)
No e-mail responses, please, unless explicitly requested!
Note: I'm unable to visit the newsgroups every day at the moment,
so be patient if you don't get a reply immediately.

Network Admin

unread,
Jul 22, 2001, 12:57:00 PM7/22/01
to
Thanks Peter! That is perfect. Also thanks for the different methods you
presented.

- Brent

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.0000753...@antispam.compuserve.com...

Peter Below (TeamB)

unread,
Jul 22, 2001, 3:04:28 PM7/22/01
to
In article <3b5b060b_1@dnews>, Network Admin wrote:
> Thanks Peter! That is perfect. Also thanks for the different methods you
> presented.
>

Good to know that it helped, but was it really necessary to quote the whole
lengthy post? Please clip your quotes to the absolute minimum, as per the
newsgroup guidelines (see http://www.borland.com/newsgroups/ )

Sterling Bates

unread,
Aug 6, 2001, 7:54:42 PM8/6/01
to
For an expansion of #2:

http://www.openinfo.se/martin/texterdelphi/miniex.htm

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.0000753...@antispam.compuserve.com...

Reply all
Reply to author
Forward
0 new messages