Minimize-to-SysTray for Dialog-Based Applications
Another article here at CodeGuru by Dominik Filipp explains one way to implement this. That technique uses the "make your main window owned by an invisible window" trick, and also involves messing with the WS_EX_APPWINDOW style bit. This comes straight out of the MSDN docs, so you'd think it'd work right. Heh.
A minor problem with Filipp's article is that the code relies on CWnd::PreCreateWindow() being called to set up a critical window ownership relation, but this doesn't get called for CDialog-based windows. You can set this relation up another way, but then you hit another problem: when you minimize, the taskbar button disappears, but then you get an MDI-like "minimized window" icon on your desktop just above the taskbar.
I have no doubt that Filipp's code works fine if your main window is derived from CWnd, but it fails for CDialog-based windows. Small utility apps are the most likely to use this idiom, and such apps are usually easiest to build as a dialog-based program. You could use CFormView, as it is derived from CWnd yet lets you use a dialog template. But, that's a lot harder than a true dialog-based app. What we need instead is a technique that works with CDialog-based apps without a lot of trickery.
My technique works with dialog-based applications, and presumably also with regular CWnd-based apps, though I haven't tested it. Instead of all that trickery with invisible "owner" windows and twiddling style bits, we just hide the main dialog when we get minimized. Windows sees that we're invisible and minimized, so it removes our button from the taskbar. We show the window again when we get restored.
The code accompanying this article also illustrates how to integrate this technique with a systray icon. It follows the usual pattern: you minimize the main window, it disappears from the taskbar and puts an icon in the systray. Then when you double-click on the systray icon, the icon disappears and the main dialog window is restored.
The sample project (16 KB) is a basic AppWizard-generated dialog-based app with a few modifications. This list will tell you what you need to cut-and-paste out of the sample project to add this feature to your own apps:
- Add a handler for WM_SYSCOMMAND, for handling the "you're being
minimized" event. You
may just be able to copy CTBHideDlg's OnSysCommand() handler
and the SetupTaskBarButton() and SetupTrayIcon()
functions into your CDialog class.
- I use Chris Maunder's
CSystemTray
class (included in the zip file) to handle the systray icon. You may
need to #include <afxdisp.h> in your stdafx.h file in
order to get CSystemTray to compile. Alternatively, you can yank out
all the animated icon stuff, which is what I do in my own projects.
(I can't distribute that version, though, due to the license
CSystemTray is distributed under.)
- Create a simple popup menu for attaching to the systray icon, and add
command handlers for the menu items. (E.g. Restore, About, Exit, etc.)
- Override DestroyWindow(). In it, manually get rid
of the systray icon since Windows won't do it for you.
- You may want to add code to handle the case where the user
wants to start the app minimized. MFC won't handle this case for
CDialog-based apps, so you have to do it yourself. Note that this
only works right if the dialog you want to minimize has the WS_VISIBLE
style set when you create it. If not, Windows ignores you when you
say ShowWindow(SW_HIDE) in the minimize handler, and you get a
systray icon and a taskbar button.

Comments
Works also with regular CWnd-based apps
Posted by paolor on 01/30/2005 12:20amI've used it on an SDI application. Thanks!
ReplyWin2000 doubleclick problem
Posted by Legacy on 06/12/2001 12:00amOriginally posted by: Jay Prall
This works great, except for one small problem in windows 2000. If you have a dialup networking connection, which is also a systray icon, and you double click your icon in the systray, it will restore the application as well as bring up the properties for the dialup networking session.
I have produced this problem in the project I added the class to as well as the sample project.
If I find a solution I will let you know.
Jay
ReplyOne question???
Posted by Legacy on 03/19/2001 12:00amOriginally posted by: Vivek
I've one main window which Im not showing and I have one dialog box which is the child window of main window. Since Im not showing main window, so Im not able to see any window in task bar. I want to show my window in taskbar as well as I don't want to show my main window also. any help?
Vivek
-
Replyanswer to "One question???"
Posted by Cloud Lee on 12/20/2004 03:00amIf you create child dialog from the main window, the main window must be showed too. But if you create it from systray menu, it will be displayed alone.
Reply