This class encapsulates the Shell_NotifyIcon SDK call. This API is used to
create those nifty little icons such as volume control you see in the tray notification
area on Windows.
The class hides a lot of the drudgery of calling the API
directly and provides a nice clean C++ interface to using it. Overloaded member functions
are provided to set and get the ToolTip text, icon and notification window. The class also
provides a default implementation to bring up a context menu and provides a default menu
item which is executed when you double click the icon. The class also provides auto
cleanup and resurrection of icons if the shell unexpectedly crashes.
The enclosed zip file contains the
CTrayNotifyIcon source code and also includes a VC 2005 workspace to build a small
demonstration app in MFC as well as WTL.
- You are allowed to include the source code in
any product (commercial, shareware, freeware or otherwise) when your product
is released in binary form.
- You are allowed to modify the source code in
any way you want except you cannot modify the copyright details at the top
of each module.
- If you want to distribute source code with
your application, then you are only allowed to distribute versions released
by the author. This is to maintain a single distribution point for the
v1.0 (14 May 1997)
v1.1 (25 November 1997)
- Addition of HideIcon(), ShowIcon() & MoveToExtremeRight()
- Support for animated tray icons
v1.2 (23 June 1998)
- Class now supports the new Taskbar Creation Notification message
which comes with IE 4. This allows the tray icon to be recreated whenever the explorer
V1.3 (22 July 1998)
- Code now compiles cleanly at warning level 4
- Code is now UNICODE enabled + build configurations are provided
- The documentation for the class has been completely revamped
V1.31 (27 January 1999)
- Code now correctly loads up 16*16 icons, previously it allowed
Windows to rescale the icon from 32*32 resulting in slightly blurry images. This has been
accomplished via the new LoadIconResource method.
V1.32 (28 January 1999)
- Removed a number of level 4 warnings which were occurring
V1.33 (9 May 1999)
- Fixed a problem as documented in KB article "PRB:
Menus for Notification Icons Do Not Work Correctly", Article ID:
- Also available is a port of the code to ATL which has
been done by Shaun Wilde. This is
available in this zip file.
10 May 1999
- A new version of Shaun Wilde's port
of CTrayNotifyIcon is now available. The class is now based on v1.33 of
my MFC class
11 May 1999
V1.4 (16 May 1999)
- Modified the sample program to ensure that 16*16 icons
are used when tray icon animation is not being used.
- Now uses the author's hookwnd class. This prevents the
need to create the two hidden windows namely CTrayRessurectionWnd and
CTrayTimerWnd to handle icon animation and tray creation messages.
- Sample project now compiles at warning level 4.
- General code tidy up and rearrangement.
- Added numerous ASSERT's to improve the code's
- Added functions to allow context menu to be customized
26 May 1999
- A new version of Shaun Wilde's port
of CTrayNotifyIcon is now available. The class is now based on v1.4 of
my MFC class
21 May 2000
- Minor update to the documentation.
V1.41 (1 January 2001)
- Now includes copyright message in the source code and
- Fixed problem where the window does not get focus after
double clicking on the tray icon.
- Now fully supports the Windows 2000 balloon style
- Fixed a off by one problem in some of the ASSERT's.
- Fixed problems with Unicode build configurations.
- Provided Win2k specific build configurations.
V1.42 (10 February 2001)
- Now fully supports creation of 2 tray icons at the same
V1.43 (13 June 2001)
- Now removes windows hook upon call to RemoveIcon.
V1.44 (26 August 2001)
- Fixed memory leak in RemoveIcon.
- Fixed GPF in RemoveIcon by removing call to Unhook
V1.45 (28 August 2001)
- Added support for direct access to the System Tray's HDC. This allows you to generate an
icon for the tray on the fly using GDI calls. The idea came from the article by Jeff Heaton in
the April issue of WDJ. Also added are overriden Create methods to allow you to easily costruct
a dynamic tray icon given a BITMAP instead of an ICON.
25 November 2002
- Added a comment to the NTray.h header file about where
to get the HookWnd.h file if the code compile fails.
V1.46 (21 March 2003)
- Fixed icon resource leaks in SetIcon(LPCTSTR lpIconName)
and SetIcon(UINT nIDResource). Thanks to Egor Pervouninski for reporting this.
- Fixed unhooking of the tray icon when the notification
window is being closed.
V1.47 (31 March 2003)
- Now uses V1.05 of my Hookwnd class
V1.48 (2 April 2003)
- Now uses v1.06 of my Hookwnd class
- Fixed a bug in the sample app for this class where the
hooks should have been created as global instances rather than as member
variables of the mainframe window. This ensures that the hooks remain valid
even after calling DefWindowProc on the mainframe.
V1.49 (23 July 2004)
- Minor update to remove unnecessary include of "resource.h"
V1.50 (3 March 2006)
- Updated copyright details.
- Updated the documentation to use the same style as the web site.
- Did a spell check of the documentation.
- Fixed some issues when the code is compiled using /Wp64. Please note
that to support this the code now requires a recentish Platform SDK to be
installed if the code is compiled with Visual C++ 6.
- Replaced all calls to ZeroMemory with memset.
- Fixed an issue where SetBalloonDetails was not setting the cbSize
parameter. Thanks to Enrique Granda for reporting this issue.
- Added support for NIIF_USER and NIIF_NONE flags.
- Now includes support for NIM_NIMSETVERSION via SetVersion. In addition
this is now automatically set in the Create() calls if the Win2k boolean
parameter is set.
- Removed derivation from CObject as it was not really needed.
- Now includes support for NIM_SETFOCUS
- Added support for NIS_HIDDEN via the ShowIcon and HideIcon methods.
- Added support for NIIF_NOSOUND
V1.51 (27 June 2006)
- Code now uses new C++ style casts rather than old style C casts where
- The class framework now requires the Platform SDK if compiled using VC
- Updated the logic of the ASSERTs which validate the various string
- Fixed a bug in CTrayNotifyIcon::SetFocus() where the cbSize value was
not being set correctly.
- CTrayIconHooker class now uses ATL's CWindowImpl class in preference to
the author's CHookWnd class. This does mean that for MFC only client
projects, you will need to add ATL support to your project.
- Optimized CTrayIconHooker constructor code.
- Updated code to compile cleanly using VC 2005. Thanks to "Itamar" for
prompting this update.
- Addition of a CTRAYNOTIFYICON_EXT_CLASS and CTRAYNOTIFYICON_EXT_API
macros which makes the class easier to use in an extension dll.
- Made CTrayNotifyIcon destructor virtual
V1.52 (3 July 2006)
- Fixed a bug where the HideIcon functionality did not work on Windows
2000. This was related to how the cbSize member of the NOTIFYICONDATA
structure was initialized. The code now dynamically determines the correct
size to set at runtime according to the instructions provided by the MSDN
documentation for this structure. As a result of this, all "bWin2k"
parameters which were previously exposed via CTrayNotifyIcon have now been
removed as there is no need for them. Thanks to Edwin Geng for reporting
this important bug. Client code will still need to intelligently make
decisions on what is supported by the OS. For example balloon tray icons are
only supported on Shell v5 (nominally Windows 2000 or later).
CTrayNotifyIcon will ASSERT if for example calls are made to it to create a
balloon tray icon on operating systems with < Shell v5.
V1.53 (5 July 2006)
- Fixed a bug where the menu may pop up a second time after a menu item is
chosen on Windows 2000. The problem was tracked down to the code in
CTrayNotifyIcon::OnTrayNotification. During testing of this bug, I was
unable to get a workable solution using the new shell messages of
WM_CONTEXTMENU, NIN_KEYSELECT & NIN_SELECT on Windows 2000 and Windows XP.
This means that the code in CTrayNotifyIcon::OnTrayNotification uses the old
way of handling notifications (WM_RBUTTDOWN*). This does mean that by
default, client apps which use the CTrayNotifyIcon class will not support
the new keyboard and mouse semantics for tray icons (IMHO this is no big
loss!). Client code is of course free to handle their own notifications. If
you go down this route then I would advise you to thoroughly test your
application on Windows 2000 and Windows XP as my testing has shown that
there is significant differences in how tray icons handle their messaging on
these 2 operating systems. Thanks to Edwin Geng for reporting this issue.
- Class now displays the menu based on the current message's screen
coordinates, rather than the current cursor screen coordinates.
- Fixed bug in sample app where if the about dialog is already up and it
is reactivated from the tray menu, it did not bring itself into the
V1.54 (6 July 2006)
- Reverted the change made for v1.53 where the screen coordinates used to
show the context menu use the current message's screen coordinates. Instead
the pre v1.53 mechanism which uses the current cursor's screen coordinates
is now used. Thanks to Itamar Syn-Hershko for reporting this issue.
V1.55 (19 July 2006)
- The default menu item can now be customized via SetDefaultMenuItem
and GetDefaultMenuItem. Thanks to Mikhail Bykanov for suggesting this
- Optimized CTrayNotifyIcon constructor code
V1.56 (19 August 2006)
- Updated the code to operate independent of MFC if so desired. This
requires WTL which is an open source library extension for ATL to provide UI
support along the lines of MFC. Thanks to zhiguo zhao for providing this
very nice addition.
V1.57 (15 September 2006)
- Fixed a bug where WM_DESTROY messages were not been handled correctly
for the top level window which the CTrayIconHooker class subclasses in order
to handle the tray resurrection message, the animation timers and auto
destroying of the icons when the top level window is destroyed. Thanks to
Edward Livingston for reporting this bug.
- Fixed a bug where the tray icons were not being recreated correctly when
we receive the "TaskbarCreated" message when Explorer is restarted. Thanks to Nuno
Esculcas for reporting this bug.
- Split the functionality of hiding versus deleting and showing versus
creating of the tray icon into 4 separate functions, namely Delete(),
Create(), Hide() and Show(). Note that Hide and Show functionality is only
available on Shell v5 or later.
- Fixed an issue with recreation of tray icons which use a dynamic icon
created from a bitmap (through the use of BitmapToIcon).
- CTrayNotifyIcon::LoadIconResource now loads up an icon as a shared icon
resource using LoadImage. This should avoid resource leaks using this
V1.58 (15 June 2007)
- Updated copyright messages.
- If the code detects that MFC is not included in the project, the code
uses the standard preprocessor define "_CSTRING_NS" to declare the string
class to use rather than explicitly using WTL::CString. Thanks to Krzysztof
Suszka for reporting this issue.
- Updated sample app to compile cleanly on VC 2005.
- Addition of a "BOOL bShow" to all the Create methods. This allows you to
create an icon without actually showing it. This avoids the flicker which
previously occurred if you created the icon and then immediately hid the
icon. Thanks to Krzysztof Suszka for providing this suggestion.
- Demo app now initially creates the first icon as hidden for
- Added support for NIIF_LARGE_ICON. This Vista only feature allows you to
create a large balloon icon.
- Added support for NIF_REALTIME. This Vista only flag allows you to
specify not to bother showing the balloon if it is delayed due to the
presence of an existing balloon.
- Added support for NOTIFYICONDATA::hBalloonIcon. This Vista only feature
allows you to create a user specified balloon icon which is different to the
actual tray icon.
- LoadIconResource method now includes support for loading large icons and
has been renamed to simply LoadIcon. Also two overridden versions of this
method have been provided which allow the hInstance resource ID to be
specified to load the icon from.
- Reworked the internal code to CTrayNotifyIcon which detects the shell
- Updated the tray icon text in the demo app to better demonstrate the
features of the class.
- Updated the WTL sample to be consistent with the MFC sample code
- Updated comments in documentation about usage of the Platform SDK.
V1.59 (13 October 2007)
- Subclassing of the top level window is now not done internally by the
CTrayNotifyIcon class using the CTrayIconHooker class. Instead now a hidden
top level window is created for each tray icon you create and these look
after handling the tray resurrection and animated icon timer messages. This
refactoring of the internals of the class now also fixes a bug where an
application which creates multiples tray icons would only get one icon
recreated when the tray resurrection message was received. Thanks to Steven
Dwyer for prompting this update.
- Updated the MFC sample app to correctly initialize ATL for VC 6
V1.60 (12 March 2008)
- Updated copyright details
- Fixed a bug in SetBalloonDetails where the code did not set the flag
NIF_ICON if a user defined icon was being set. Thanks to "arni" for
reporting this bug.
- Updated the sample app to clean compile on VC 2008
V1.61 (22 June 2008)
- Code now compiles cleanly using Code Analysis (/analyze)
- Updated code to compile correctly using _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
- Removed VC 6 style AppWizard comments from the code.
- The code now only supports VC 2005 or later.
V1.62 (10 April 2010)
- Updated copyright details.
- Updated the project settings to more modern default values.
- Updated the WTL version of LoadIcon to use the more modern ModuleHelper
class from WTL to get the resource instance. Thanks to "Yarp" for reporting
- The class now has support for the Windows 7 "NIIF_RESPECT_QUIET_TIME" flag.
This value can be set via the new "bQuietTime" parameter to the Create method.
- Updated the code which does version detection of the Shell version
V1.63 (10 July 2010)
- Updated the sample app to compile cleanly on VS 2010.
- Fixed a bug in CTrayNotifyIcon::Delete where the code would ASSERT if
the tray notify icon was never actually created. Thanks to "trophim" for
reporting this bug.
V1.64 (6 November 2010)
- Minor update to code in SetTooltipText to code which handles
unreferenced variable compiler warning
- Implemented a GetTooltipMaxSize method which reports the maximum
size which the tooltip can be for a tray icon. Thanks to Geert van Horrik
for this nice addition
- All places which copy text to the underlying NOTIFYICONDATA now
use the _TRUNCATE parameter in their call to the Safe CRT runtime. This
change in behaviour means that client apps will no longer crash if they
supply data larger than this Windows structure can accommodate. Thanks to
Geert van Horrik for prompting this update.
- All calls to sizeof(struct)/sizeof(first element) have been
replaced with _countof
- Fixed a linker error when compiling the WTL sample app in release
V1.65 (26 November 2010)
- Minor update to use DBG_UNREFERENCED_LOCAL_VARIABLE macro. Thanks to
Jukka Ojanen for prompting this update.
V1.66 (27 April 2016)
- Updated copyright details.
- Updated the code to clean compile on VC 2012 - VC 2015.
- Removed support for CTRAYNOTIFYICON_NOWIN2K preprocessor macro
- Removed various redefines of ShellApi.h constants from the code
- Added SAL annotations to all the code.
- Reworked the definition of the string class to now use a typedef
internal to the CTrayNotifyIcon class.
- Updated CTrayNotifyIcon::OnTrayNotification to handle
NOTIFYICON_VERSION_4 style notifications.
- Reworked the internal storage of the animation icons to use