Introduction
This is a class (
SS_TrayIcon
) that creates a tray icon in the system tray,
allowing easy integration into any project, whether or not you use MFC. Some
of the features include:
- Create multiple icons, animated icons, blinking icons, or still icons
- Easily define a message map for routing Windows messages generated by
the tray icon to user defined functions...
-or-
Let MFC handle the message mapping by sending all messages to the
CWnd::WindowProc
function.
- Easily add a popup window (context menu) to the icon when the user
clicks on it.
- Avoid processing the
WM_LBUTTONDOWN
Windows message before a user
double-clicks. This is a common problem... when the user double-clicks,
programs often process a single-click before processing the double-click.
This class will wait to send the single-click message until it is sure that the
user won't double-click. (note: this feature does not work if you let
MFC handle the message routing.)
This class is similar to Chris Maunder's class in Adding
Icons to the System Tray except that it allows you to specify the mode (SSTI_MODE_SHOWNORMAL
,
SSTI_MODE_HIDE
, SSTI_MODE_BLINK
, SSTI_MODE_ANIMATE
)
A simple demo project is included:
Integration Into Your Project
You will need to include the 2 header files into your project (SS_TrayIcon.h and SS_Wnd.h),
add the SS_TrayIconD.lib file to your debug project, and the SS_TrayIcon.lib file to
your release project. (or you can skip the lib files and add the two *.cpp files instead.)
To create a tray icon, you only need 3 lines of code:
SS_TrayIcon* m_pTrayIcon = new SS_TrayIcon( m_hInstance, 1, 1 );
m_pTrayIcon->LoadIcon( 0, 0, IDI_SOME_ICON_RESOURCE );
m_pTrayIcon->ShowIcon( 0 );
Some other options include:
m_pTrayIcon->Mode( 0, SSTI_MODE_BLINK );
m_pTrayIcon->SetAnimateSpeed( 0, 400 );
m_pTrayIcon->ToolTip( 0, _T("This is a blinking icon...") );
m_pTrayIcon->ShowMenuAtMouse( nMenuResourceID, hWnd );
m_pTrayIcon->HideIcon();
Most of the functions that alter the icon require an integer as the first parameter
(
nIconSet
). Because you can have multiple icons, this integer specifies which icon
you want to alter. Then when you show the icon, you specify which icon you want
to show. From here on out, we will refer to each one of these icons as an
IconSet
...
here's why: each
IconSet
can contain multiple "sub-icons", which we will refer to
as "frames". So each
IconSet
makes up an animation that is composed of some number
of frames. You can load icon resources into the frames of your
IconSets
as in the
following code, which creates 3
IconSets
, one with 8 frames, and two with only 1 frame:
m_pTrayIcon = new SS_TrayIcon( AfxGetInstanceHandle(), 3, 8 );
m_pTrayIcon->LoadIcon( 0, 0, IDI_ICON1 );
m_pTrayIcon->LoadIcon( 0, 1, IDI_ICON2 );
m_pTrayIcon->LoadIcon( 0, 2, IDI_ICON3 );
m_pTrayIcon->LoadIcon( 0, 3, IDI_ICON4 );
m_pTrayIcon->LoadIcon( 0, 4, IDI_ICON5 );
m_pTrayIcon->LoadIcon( 0, 5, IDI_ICON4 );
m_pTrayIcon->LoadIcon( 0, 6, IDI_ICON3 );
m_pTrayIcon->LoadIcon( 0, 7, IDI_ICON2 );
m_pTrayIcon->Mode( 0, SSTI_MODE_ANIMATE );
m_pTrayIcon->SetAnimateSpeed( 0, 150 );
m_pTrayIcon->ToolTip( 0, _T("This is an animated icon...") );
m_pTrayIcon->LoadIcon( 1, 0, IDR_MAINFRAME );
m_pTrayIcon->Mode( 1, SSTI_MODE_BLINK );
m_pTrayIcon->SetAnimateSpeed( 0, 450 );
m_pTrayIcon->ToolTip( 1, _T("This is a blinking icon...") );
m_pTrayIcon->LoadIcon( 2, 0, IDI_ICON6 );
m_pTrayIcon->Mode( 2, SSTI_MODE_SHOWNORMAL );
m_pTrayIcon->ToolTip( 2, _T("This is a non-animated icon...") );
m_pTrayIcon->ShowIcon( 0 );
The last thing you need to know is about the message map. For each message you
want to respond to, you need the call the
m_pTrayIcon->MapMessageToFunction
function. You need to supply the function with a pointer to your global callback
function so it can call that function when the message is generated, as so:
LRESULT CALLBACK OnMouseDblClickTI(WPARAM wParam, LPARAM lParam)
{
::MessageBox(NULL, _T("Double-clicked!!"), _T("Test"), MB_OK|MB_ICONINFORMATION);
return 0;
}
CYourClass::InitObject()
{
...
m_pTrayIcon = new SS_TrayIcon( AfxGetInstanceHandle(), 3, 8 );
m_pTrayIcon->MapMessageToFunction(WM_LBUTTONDBLCLK, ::OnMouseDblClickTI);
...
}
Now whenever the user double-clicks on the tray icon (no matter which one you have showing),
your
OnMouseDblClickTI()
function will be called. You can do anything
you want from there. If you want to respond differently depending on which icon you
have showing, you will have to keep track of which icon is showing and use a switch
in the callback function to determine what action is appropriate.
Notes
There are LOTS of comments in the demo code explaining how to use the
SS_TrayIcon
class, and
there are also lots of comments in the
SS_TrayIcon
code explaining how the code works, so
please read through those comments for a much more detailed explanation of the inner workings
of this project.