Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

Easy Animated Tray Icon

, 4 Feb 2002
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).
ss_trayicon_demo.zip
SS_TrayIcon.dsp
SS_TrayIcon.dsw
SS_TrayIcon.gif
SS_TrayIcon.opt
SS_TrayIcon2.gif
Demo
Debug
res
icon1.ico
icon2.ico
icon3.ico
icon4.ico
icon5.ico
icon6.ico
testMFC.ico
TestSSTrayIcon.dsp
ss_trayicon_src.zip
SS_TrayIcon.gif
SS_TrayIcon.lib
SS_TrayIcon2.gif
SS_TrayIconD.lib
// TestSSTrayIconDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TestSSTrayIcon.h"
#include "TestSSTrayIconDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// globals

// this is a global pointer to our main dialog class.  We set this in the
// InitDialog function.  It is necessary if we want to access class
// variable when the tray icon generates Windows messages.
CTestSSTrayIconDlg* g_pTheDlg;


// these next 4 functions are callback functions that are called when the 
// tray icon generates Windows messages.  We map these functions by calling 
// SS_TrayIcon::MapMessageToFunction 4 times (one for each of these 4 messages)
// in the InitDialog function.  The functions are only used if you do *not*
// supply an hWnd in the SS_TrayIcon constructor.

// callback function for the WM_MOUSEMOVE message
LRESULT CALLBACK OnMouseMoveTI(WPARAM wParam, LPARAM lParam)
{
    // do whatever you want here...
    return 0;
}

// callback function for the WM_LBUTTONDOWN message
LRESULT CALLBACK OnMouseClickTI(WPARAM wParam, LPARAM lParam)
{
    g_pTheDlg->m_pTrayIcon->ShowMenuAtMouse(IDR_MENU1, g_pTheDlg->m_hWnd);
    return 0;
}

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

// callback function for the WM_RBUTTONUP message
LRESULT CALLBACK OnMouseRightClickTI(WPARAM wParam, LPARAM lParam)
{
    ::MessageBox(NULL, _T("Right-clicked!!"), _T("Test"), MB_OK|MB_ICONINFORMATION);
    return 0;
}


// here we will define 3 icons... this is not necessary, but it is 
// nice to use names instead of the numbers 0, 1, 2 for the icons
typedef enum TrayIconNames
{
    TI_ANIMATED,
    TI_BLINKING,
    TI_STILL
    
} TRAYICON_NAMES;


/////////////////////////////////////////////////////////////////////////////
// CTestSSTrayIconDlg dialog

// constructor
CTestSSTrayIconDlg::CTestSSTrayIconDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTestSSTrayIconDlg::IDD, pParent)
{
}

// destructor
CTestSSTrayIconDlg::~CTestSSTrayIconDlg()
{
    delete m_pTrayIcon;
}


BEGIN_MESSAGE_MAP(CTestSSTrayIconDlg, CDialog)
	//{{AFX_MSG_MAP(CTestSSTrayIconDlg)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
	ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
	ON_BN_CLICKED(IDC_BUTTON4, OnButton4)
	ON_COMMAND(IDM_SUBMENU5, OnSubmenu5)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTestSSTrayIconDlg message handlers

BOOL CTestSSTrayIconDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

    // We set the global pointer to our dialog so we can get back
    // to this class's variables in the tray icon's callback functions
    g_pTheDlg = this;
      
    
    // Here we will set up 3 icons (IconSets actually) that will be displayed 
    // in the system tray:
    //
    // 1. an animated icon with 8 frames
    // 2. a blinking icon
    // 3. a still icon
    //
    //
    // The variable below (bUseThisWnd) is not necessary... it is just to  
    // demonstrate the two different ways of handling Windows messages generated 
    // by the tray icon.  Set this variable to TRUE if you want the CTestSSTrayIconDlg
    // class (this class) to handle the messages, or FALSE if you want 
    // the SS_TrayIcon class to take care of the messaging.  
    //
    // If the SS_TrayIcon class handles the messages, you will need to create
    // global callback functions and map them to messages with the
    // SS_TrayIcon::MapMessageToFunction function.  
    //
    // If the CTestSSTrayIconDlg class handles the messages, you will need to
    // override the class' OnTimer and WindowProc functions.  In the OnTimer
    // function, call the SS_TrayIcon::OnTimer function.  In the WindowProc
    // function, check to see if the message is a SSTI_CALLBACK_MESSAGE...
    // If so, it is from the tray icon, so process as you wish.
    BOOL bUseThisWnd = FALSE;

                                                //             How many icons (IconSets)?
                                                //             |  How many icons per set (frames for animated icons)?
                                                //             |  |  the hWnd that will receive Windows Messages
    if( bUseThisWnd )                           //             |  |  |             generated by the tray icon.
        m_pTrayIcon = new SS_TrayIcon( AfxGetInstanceHandle(), 3, 8, m_hWnd );   
    else
        m_pTrayIcon = new SS_TrayIcon( AfxGetInstanceHandle(), 3, 8, NULL);
                                                //                   |
                                                //                   Because no hWnd is specified here, the
                                                //                   SS_TrayIcon class will handle the Windows Messages
                                                //                   generated by the tray icon.

    // prep icon 1 (animated with 8 frames)
    //
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 0, IDI_ICON1 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 1, IDI_ICON2 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 2, IDI_ICON3 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 3, IDI_ICON4 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 4, IDI_ICON5 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 5, IDI_ICON4 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 6, IDI_ICON3 );
    m_pTrayIcon->LoadIcon( TI_ANIMATED, 7, IDI_ICON2 );

    m_pTrayIcon->Mode( TI_ANIMATED, SSTI_MODE_ANIMATE );
    m_pTrayIcon->SetAnimateSpeed( TI_ANIMATED, 150 );
    m_pTrayIcon->ToolTip( TI_ANIMATED, _T("This is an animated icon...") );

    // prep icon 2 (blinking)
    //
    m_pTrayIcon->LoadIcon( TI_BLINKING, 0, IDR_MAINFRAME );
    m_pTrayIcon->Mode( TI_BLINKING, SSTI_MODE_BLINK );
    m_pTrayIcon->ToolTip( TI_BLINKING, _T("This is a blinking icon...") );

    // prep icon 3 (standing still)
    //
    m_pTrayIcon->LoadIcon( TI_STILL, 0, IDI_ICON6 );
    m_pTrayIcon->Mode( TI_STILL, SSTI_MODE_SHOWNORMAL );
    m_pTrayIcon->ToolTip( TI_STILL, _T("This is a non-animated icon...") );


    // now, if we are letting the SS_TrayIcon class handle the Windows messages,
    // call the MapMessageToFunction function for each message we want to map.
    if( !bUseThisWnd )
    {
        m_pTrayIcon->MapMessageToFunction(WM_MOUSEMOVE, ::OnMouseMoveTI);
        m_pTrayIcon->MapMessageToFunction(WM_LBUTTONDOWN, ::OnMouseClickTI);
        m_pTrayIcon->MapMessageToFunction(WM_LBUTTONDBLCLK, ::OnMouseDblClickTI);
        m_pTrayIcon->MapMessageToFunction(WM_RBUTTONUP, ::OnMouseRightClickTI);
    }
    
    // show the first icon.
    m_pTrayIcon->ShowIcon(TI_ANIMATED);

    
	return TRUE;  // return TRUE  unless you set the focus to a control
}


    
// 
// The next 4 functions handle what do we do when the main window's buttons 
// are pressed...
//

void CTestSSTrayIconDlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
    m_pTrayIcon->ShowIcon(TI_ANIMATED);
}

void CTestSSTrayIconDlg::OnButton2() 
{
	// TODO: Add your control notification handler code here
    m_pTrayIcon->ShowIcon(TI_BLINKING);
}

void CTestSSTrayIconDlg::OnButton3() 
{
	// TODO: Add your control notification handler code here
    m_pTrayIcon->ShowIcon(TI_STILL);
}

void CTestSSTrayIconDlg::OnButton4() 
{
    // TODO: Add your control notification handler code here
    m_pTrayIcon->HideIcon();
}



// 
// The next function handles what we do when the popup menu's first menu-item 
// is pressed...
//

void CTestSSTrayIconDlg::OnSubmenu5() 
{
	// TODO: Add your command handler code here
    ::MessageBox(NULL, _T("Menu 'something' clicked!!"), _T("Test"), MB_OK|MB_ICONINFORMATION);
}



// 
// This code (to the end) is only necessary if you supplied an hWnd in the 
// constructor of your SS_TrayIcon.
//

LRESULT CTestSSTrayIconDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
    // add the switch and look for the SSTI_CALLBACK_MESSAGE message, as
    // these messages were generated by the tray icon...
    //
    switch( message )
    {
    case SSTI_CALLBACK_MESSAGE:
        {
            // all messages here were generated by the tray icon, so 
            // process whichever message types you'd like.
            //
            switch( (UINT)lParam )
            {
            case WM_LBUTTONDOWN:
                // do whatever you want here
                m_pTrayIcon->ShowMenuAtMouse(IDR_MENU1, m_hWnd);
                break;

            case WM_RBUTTONDOWN:
                // do whatever you want here
                break;

            case WM_LBUTTONDBLCLK:
                // do whatever you want here
                break;
            }
        }
        break;

    default:
        break;
    }    
	
	return CDialog::WindowProc(message, wParam, lParam);
}

void CTestSSTrayIconDlg::OnTimer(UINT nIDEvent) 
{
    // make sure that you override the OnTimer function (this function)
    // and call the TrayIcon's OnTimer function... this is necessary
    // to make the icons animate or blink.
    //
    m_pTrayIcon->OnTimer(nIDEvent);
    
	CDialog::OnTimer(nIDEvent);
}

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

Share

About the Author

Steve Schaneville
Architect
United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 5 Feb 2002
Article Copyright 2002 by Steve Schaneville
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid