Click here to Skip to main content
15,884,099 members
Articles / Programming Languages / C++

Easy Animated Tray Icon

Rate me:
Please Sign up or sign in to vote.
4.64/5 (12 votes)
4 Feb 20023 min read 214.4K   5.8K   69  
This is a class (SS_TrayIcon) that allows for the easy addition of a tray icon into any project (whether you use MFC or not).
<!--------------------------------------------------------------------------->
<!--                           INTRODUCTION

 The Code Project article submission template (HTML version)

Using this template will help us post your article sooner. To use, just
follow the 3 easy steps below:

     1. Fill in the article description details
     2. Add links to your images and downloads
     3. Include the main article text

That's all there is to it! All formatting will be done by our submission
scripts and style sheets.

-->
<!--------------------------------------------------------------------------->
<!--                        IGNORE THIS SECTION                            -->
<html>
<head>
<title>The Code Project</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<Style>
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono;
      WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
</style>
</head>
<body bgcolor="#FFFFFF" color=#000000>
<!--------------------------------------------------------------------------->


<!-------------------------------     STEP 1      --------------------------->
<!--  Fill in the details (CodeProject will reformat this section for you) -->

<pre>
Title:       Easy Animated Tray Icon
Author:      Steve Schaneville
Email:       z_web_master@yahoo.com
Environment: VC++ 6.0, Win2000, (not tested on other Windows platforms)
Keywords:    tray icon, trayicon, system tray, tray, icon, animate, animated, blink, blinking
Level:       Intermediate"
Description: This is a class (SS_TrayIcon) that allows for the easy addition of a tray icon into any project (whether you use MFC or not).
Section      Miscellaneous Controls
SubSection   General
</pre>

<hr width=100% noshade>

<!-------------------------------     STEP 2      --------------------------->
<!--  Include download and sample image information.                       -->

<ul class=download>
<li><a href="ss_trayicon_demo.zip">Download demo project - XXX Kb </a></li>
<li><a href="ss_trayicon_src.zip">Download source - XXX Kb</a></li>
</ul>

<p><img src="ss_trayicon.gif" alt="Sample Image" ></p>


<!-------------------------------     STEP 3      --------------------------->
<!--  Add the article text. Please use simple formatting (<h2>, <p> etc)   -->

<p>
<h2>Introduction</h2>
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:

<ul>
	<li>Create multiple icons, animated icons, blinking icons, or still icons</li>
	<li>Easily define a message map for routing Windows messages generated by
		the tray icon to user defined functions...<br>
		-or-<br>
	    Let MFC handle the message mapping by sending all messages to the
		CWnd::WindowProc function.</li>
	<li>Easily add a popup window (context menu) to the icon when the user
		clicks on it.</li>
	<li>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.)</li>
</ul>
<br>
</p>

<p>
A simple demo project is included:<br>
<br>
<img src="ss_trayicon2.gif" alt="Sample Image" >
<br>
</p>

<p>
<h2>Integration Into Your Project</h2>
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.)
<br>
<br>
To create a tray icon, you only need 3 lines of code:

<pre>
SS_TrayIcon* m_pTrayIcon = new SS_TrayIcon( m_hInstance, 1, 1 );  // create the instance
m_pTrayIcon->LoadIcon( 0, 0, IDI_SOME_ICON_RESOURCE );            // load an icon resource
m_pTrayIcon->ShowIcon( 0 );                                       // show it!
</pre>

Some other options include:

<pre>
m_pTrayIcon->Mode( 0, SSTI_MODE_BLINK );                      // make it blink
m_pTrayIcon->SetAnimateSpeed( 0, 400 );                       // 400 is milliseconds
m_pTrayIcon->ToolTip( 0, _T("This is a blinking icon...") );  // add a tool tip
m_pTrayIcon->ShowMenuAtMouse( nMenuResourceID, hWnd );        // show a popup menu

m_pTrayIcon->HideIcon();                                      // hide it!
</pre>

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:

<pre>
                                        //             How many icons (IconSets)?
                                        //             |  How many icons per set (frames)?
                                        //             |  |
m_pTrayIcon = new SS_TrayIcon( AfxGetInstanceHandle(), 3, 8 );


// prep IconSet 1 (animated with 8 frames)
//
//                     This is which IconSet to load into...
//                     |  This is the frame number...
//                     |  |
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...") );


// prep IconSet 2 (blinking)
//
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...") );


// prep IconSet 3 (standing still)
//
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...") );


// Now show the first (animated) icon
//
m_pTrayIcon->ShowIcon( 0 ); // or '1' for the second, or '2' for the third

</pre>

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 <code>m_pTrayIcon->MapMessageToFunction</code>
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:

<pre>
// *global* callback function for the WM_LBUTTONDBLCLK message
LRESULT CALLBACK OnMouseDblClickTI(WPARAM wParam, LPARAM lParam)
{
    ::MessageBox(NULL, _T("Double-clicked!!"), _T("Test"), MB_OK|MB_ICONINFORMATION);
    return 0;
}

// in your initialization routine
CYourClass::InitObject()
{
	...

	m_pTrayIcon = new SS_TrayIcon( AfxGetInstanceHandle(), 3, 8 );

	m_pTrayIcon->MapMessageToFunction(WM_LBUTTONDBLCLK, ::OnMouseDblClickTI);

	...
}
</pre>

Now whenever the user double-clicks on the tray icon (no matter which one you have showing),
your <code>OnMouseDblClickTI()</code> 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.
</p>

<p>
<h2>Notes</h2>
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.
</p>

<p>
<h2>Contact Information</h2>
<b>Author:</b> Steve Schaneville<br>
<b>Email:</b> z_web_master@yahoo.com<br>
<br>
Please feel free to ask questions, make comments/suggestion, etc.
</p>


<!-------------------------------    That's it!   --------------------------->
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Amedisys
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions