Animating System Tray Icons


This article explains how to animate an icon in the Shell tray and assign dynamically changing tooltips for each icon phase. So the end result will be that your icon can now visually indicate what your application is currently doing along with corresponding tooltip descriptions. User notifications like left click and right click on the icon are also handled. The Windows NT  resource usage indicator on the Shell Tray is a wonderful example of animating icons on the Shell Tray. Let's animate now !.

Step 1: (Setting up the data for the animation)

The first step involves setting up well organized arrays that kind of keep track of the icons lined up for animation along with their tooltip description strings. Also define a user defined notification that will let you know if the user clicked on the animating icon. Swing by at your resource editor and create all the icons that you need and give them the same ids specified in the array.


static int iconResourceArray[NUM_ICONS_IN_ANIMATION] =

static CString strToolTipArray[NUM_ICONS_IN_ANIMATION] = 
 CString("Resource Usage = 20%") ,
 CString("Resource Usage = 40%") ,
 CString("Resource Usage = 60%") ,
 CString("Resource Usage = 80%"),
 CString("Resource Usage = 100%") }; 


Step 2:(Adding an useful helper function)

Take a look at this useful helper function below that wraps up the Shell_NotifyIcon call. The first  parameter indicates to the helper whether you need to add,delete, or modify an icon in the Shell Tray by specifying NIM_ADD, NIM_DELETE, or NIM_MODIFY. The second parameter indicates the index of the icon in the array that you set up in Step 1. The third parameter indicates the tooltip string for the currently displayed icon.

void CShellAnimDlg::InstallAnimatedIcon(DWORD dwMsgType,UINT nIndexOfIcon, CString strToolTip)

	//Load the specified icon from the array
	HICON hIconAtIndex = AfxGetApp()->LoadIcon(iconResourceArray[nIndexOfIcon]);

	///Fill up the NOTIFYICONDATA Structure
	iconData.cbSize		= sizeof(NOTIFYICONDATA);
	iconData.hWnd		= GetSafeHwnd();  //window's handle
	iconData.uID			= 100 ;  //identifier
	iconData.uFlags		= NIF_MESSAGE|NIF_ICON|NIF_TIP; //flags
	iconData.uCallbackMessage	= MYMSG_NOTIFYICON; //notification handler
	iconData.hIcon		= hIconAtIndex;    //icon handle   
	//Fill up tool tip
	LPCTSTR lpszToolTip = strToolTip.GetBuffer(strToolTip.GetLength());
	//Tell the shell what we intend doing
	//Add,Delete,Modify ---> NIM_ADD,NIM_DELETE, NIM_MODIFY in dwMsgType
	Shell_NotifyIcon(dwMsgType, &iconData); 

	//Resources are precious !
	if (hIconAtIndex)


Step 3: (Animating the icon)

Whenever you need to start the animation, begin by adding an icon first on the tray by calling the helper function with NIM_ADD. Subsequently, cycle through the animation by calling NIM_MODIFY. The following code which is a dialog based application adds the first icon in OnInitDialog() and then sets up a timer that cycles through the animation.

BOOL CShellAnimDlg::OnInitDialog()
    ///usual initialization goes here   	
    int nIndexFirstIcon = 0;
    return TRUE; // return TRUE unless you set the focus to a control
void CShellAnimDlg::OnTimer(UINT nIDEvent) 
	// TODO: Add your message handler code here and/or call default
	static int nCounter = 0;
	m_nCounter = nCounter; //Store it here to keep track of the last displayed icon
	nCounter = nCounter%(NUM_ICONS_IN_ANIMATION);


Please Note: You may need to get the last icon off the tray when the application closes. So make sure you get the icon off the tray when your application closes by calling:



Step 4: (Handling notifications)

We now  need to keep track of  user actions on our icon.. Remember the user defined message id MYMSG_NOTIFYICON that we passed for callback notification to the NOTIFYICONDATA structure in the helper function. Well, the icon posts a message whenever the user performs an action on the icon. We are interested only on mouse clicks and so let's handle them. Firstly, go ahead and define a user defined message as shown in step 1. Once you're done with that , map the message handler to a function as shown below.

afx_msg void OnHandleIconNotify(UINT wParam, LONG lParam);                //function to handle notifications

ON_MESSAGE(MYMSG_NOTIFYICON,OnHandleIconNotify)      //message mapped to function

void CShellAnimDlg::OnHandleIconNotify(UINT wParam, LONG lParam)
    CString strTest;
    CString strCurrPosition(strToolTipArray[m_nCounter]);
    switch (lParam)
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_LBUTTONDBLCLK:
            ///Do whatever you need to do when the click occured
            //Current icon animation position is at m_nCounter


You now have your animated icon cycling through it's phases on the Shell Tray with different tool tips depending on the icon position in the cycle order.

Last updated: 17 June 1998


  • Using AVI file

    Posted by Legacy on 05/17/2002 12:00am

    Originally posted by: Naresh

    Should include animation using AVI FILE.

  • This is what I needed

    Posted by Legacy on 02/03/2001 12:00am

    Originally posted by: Mark Benchley

    This stuff is really nice!.
    I needed something like this for my application

  • A Usefull Artical

    Posted by Legacy on 09/22/1999 12:00am

    Originally posted by: Philip Heald

    Thanks I found this artical extreamly usefull, it described exactly how to do something I've been trying to do for a few days !!!!

  • Other implementations

    Posted by Legacy on 04/05/1999 12:00am

    Originally posted by: Scott Seely

    For another implementation of a similar concept, you can go to I wrote an article for the November 98 issue of WDJ that covers the same topic, although with a slightly different angle. All the animation jive is hidden from the user. Anyhow, if you want another implementation, download the above file. The archive within NOV98.ZIP that you want is SEELY.ZIP.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there's simply not enough quality talent to go around. In response, companies often resort to inferior solutions -- hiring substandard developers and engineers, recruiting talent on a part-time or temporary basis, poaching people from competitors, or burdening an already stressed IT staff for more of their labor. Fortunately, there's a better solution. Read this white paper to learn the business value of …

  • On-demand Event Event Date: September 23, 2015 The cloud is not just about a runtime platform for your projects – now, you can do your development in the cloud, too. Check out this webcast to learn how the cloud improves your development experience and team collaboration. Join Dana Singleterry, Principal Product Manager for Oracle Dev Tools, as he discusses how to simplify every aspect of the development lifecycle, including requirements gathering, version management, code reviews, build automation, and …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date