Introduction
The system tray icon notification area -- or "systray" or "taskbar notification system area" -- is a section of the taskbars in the Microsoft Windows desktop user interface. This section displays the clock and the icons of certain programs so that a user is continually reminded that they are there and can easily click one of them. Unfortunately, MFC does not contain a class to wrap system tray functionality. So, I decided to write one and put it up for public use.
Background
The system tray is a section located at the one end of the taskbar in Windows 9x, and NT (Family). Icons that are often installed in the system tray include the volume control for sound, anti-virus software, and a system resources indicator. When more icons are installed in the system tray than can fit in the space allotted, the system tray becomes horizontally scrollable or expandable. To interact with a program in the system tray, you select an icon with your mouse and double-click or right-click the icon. When you minimize the program after using it, it shrinks back into the system tray instead of into the main part of the taskbar.
What makes a system tray icon special is that, when installed, it can have a customized message appear when the mouse is hovering over it. The menu that appears when you right-click it can be customized and the action that occurs when you double-click it can also be customized. For example, the double-click action for Internet Explorer could be to launch (start, or open a window for) the program, but the double-click action for a desktop icon could be to "View desktop," i.e. remove the active windows and show the underlying desktop.
An icon can be placed in the system tray when a program is installed by making an entry in the system registry. It can also be placed later by creating a shortcut to a program and dragging the shortcut icon to the system tray. An icon can be removed by deleting the registry entry or by right-clicking it and selecting Delete on the pop-up menu. The clock is removed by deselecting the show clock option in the taskbar Properties.
About CTrayIcon
CTrayIcon lets VC++ developers add icons to the Windows system tray. This quickly makes any VC++ application more attractive and intuitive to Windows users. CTrayIcon can display pop-ups. This allows developers to modify the look and feel and add powerful menu items. |
With CTrayIcon, tray icons can have Tool Tip Text that appears during a mouse-over. In addition, a cool mouse-hover effect is provided.
CTrayIcon class summary
This class is a wrap around the system tray icon notification. It adds a specified set of icon-pairs -- i.e. icons & hover-icons -- and tooltips to the system tray notification area, as well as a callback notification handler for mouse message handling.
CTrayIcon construction
Syntax
// Use if notification messages are to be // sent to the parent window. CTrayIcon(
CWnd *pWnd,
unsigned int uNotificationMessage,
MouseMsgHandlerPtr *pMouseMsgHandler,
unsigned int uHandlersCount,
IconDataPtr *pIconData,
unsigned int uIconsCount,
int nSelectedIconIndex,unsigned int uElapsed
);
// Use if notification messages are to // be sent to the CTrayIcon class.CTrayIcon(
MouseMsgHandlerPtr *pMouseMsgHandler,
unsigned int uHandlersCount,
IconDataPtr *pIconData,
unsigned int uIconsCount,
int nSelectedIconIndex,unsigned int uElapsed
);
Parameters
pWnd: Pointer to the window that receives notification messages associated with an icon in the taskbar status area. If thepWndparameter is not provided, then the functionCTrayIcon::OnNotifyIconwill be called whenever the icon sends a notification message.uNotificationMessage: Message identifier for handling proper mouse notification messages associated with an icon in the taskbar status area. If auNotificationMessageparameter is not provided, then a new window message is registered -- i.e.::RegisterWindowMessage(_T("NotifyIcon")-- and is used as a default notification message identifier.pMouseMsgHandlerPtr: An array of pointers to objects of classes derived fromCTrayIconMouseMsgHandlerto handle mouse messages.uHandlersCount: Indicates the number of handlers in the array pointed to bypMouseMsgHandlerPtr.pIconDataPtr: An array of pointers to objects ofCIconData-- i.e. units of icons, hover icons, and tool tips -- to be added to the taskbar status area.uIconsCount: Indicates the number of icons in the array pointed to byp IconDataPtr.nSelectedIconIndex: Index of the selected icon in the array pointed to byp IconDataPtr.uElapsed: Indicates the elapsed time for the taskbar status area icon animation timer.
CTrayIcon getters and setter
// Sets the notification message target windowvoid SetTargetWnd(CWnd *pWnd);// Sets the notification message identifiervoid SetNotificationMsg(unsigned
int uNotificationMsg);// Sets the selected icon indexvoid SetSelectedIconIndex(int nIconIndex);
// Gets the selected icon indexint GetSelectedIconIndex() const;
// Sets the mouse message handlervoid SetMouseMsgHandler(MouseMsgHandlerPtr *pMouseMsgHandler,
unsigned int uHandlersCount);
// Gets the mouse message handlerMouseMsgHandlerPtr* GetMouseMsgHandler()
const;// Sets timer elapsevoid SetTimerElapse(unsigned int uElapse);
// Gets timer elapseint GetTimerElapse() const;
// Sets icon datavoid SetIconData(IconDataPtr *pIconData, unsigned
int uIconsCount);// Gets icons dataIconDataPtr* GetIconData()
const;// Indicates whether animation is in progressBOOL IsAnimating () const ; CTrayIcon methods
// Dispalys a hidden iconBOOL ShowIcon();
// Hides a visible iconBOOL HideIcon();
// Refreshes iconBOOL RefreshIcon();
// Shows the hover iconBOOL HoverIcon();
// Starts icon animationBOOL StartIconAnimation();
// Stops icon animationBOOL StopIconAnimation();
CTrayIcon events & callbacks
OnTaskBarCreated
This is used to process the
WM_TI_TASKBARCREATED message for verifying taskbar status icon creation.Syntax
// Callback handler for the taskbar created event LRESULT OnTaskBarCreated(
WPARAM wParam,
LPARAM lParam
);
Result
Returns the
LRESULT after verification. OnNotifyIcon
This is used to process the
WM_TI_NOITIFYICON message for proper mouse message handling.Syntax
// Default callback handler for // taskbar notification message event LRESULT OnNotifyIcon(
WPARAM wParam,
LPARAM lParam
);
Result
Returns the
LRESULT after verification.WindowProc
This provides a Windows procedure for a
CTrayIcon object. The WindowProc function is an application-defined function that processes messages sent to a window. Syntax
// Callback handler for the window procedure LRESULT WindowProc(
unsigned int uMsg,
WPARAM wParam,
LPARAM lParam
);
Result
Returns the
LRESULT after verification. OnTimer
This is used to process the
WM_TIMER messages, triggered as soon as the elapsed time has passed.Syntax
// Callback handler for the timer elapsed event void OnTimer( unsigned int uIDEvent
);
CTrayIconMouseMsgHandler class summary
This class stands as an abstract base-class for handling mouse notification messages. Classes derived from
CTrayIconMouseMsgHandler should handle mouse notification messages and must implement the pure-virtual MouseMessageHandler() method.CTrayIconMouseMsgHandler construction
Only a single parameter constructor is available that takes a Window message to be associated with it for receiving other system tray icon notification messages.
Syntax
// Single paramenter constructor, a // mosue message identfier has to be passedCTrayIconMouseMsgHandler(
unsigned int uMouseMsgID
);
Parameters
uMouseMsgID Windows messages that the OS generates when the user performs any action with the mouse over the system tray icon. For example, the pressing or releasing of the mouse buttons, etc. CTrayIconMouseMsgHandler getters and setters
// Gets the mouse message identifier unsigned int GetMouseMsgID() const;
// Sets the mosue message identifier void SetMouseMsgID(unsigned int uMouseMsgID
);
CTrayIconMouseMsgHandler events & callbacks
MouseMsgHandler
This method is a pure-virtual method and must be defined in the derived classes for handling system tray icon mouse notification messages. This event is generated by the
CTrayIcon::OnNotifyIcon() method.Syntax
// Pure-virtual callback mouse message handler, // necessary to be implemented by the derived class, // for handling system tray icon notifications. virtual void MouseMsgHandler() = 0;
CTrayIconMouseMsgHandler synonyms
MouseMsgHandlerPtr
// Synomym for CTrayIconMouseMsgHandler pointer typedef CTrayIconMouseMsgHandler* MouseMsgHandlerPtr;CIconData class summary
This class encapsulates a set of icon-pairs -- i.e. icons & hover-icons -- and tooltips for the system tray notification area. It wraps the basic functionality to switch between icon & hover-icon, as well as between two different
CIconData objects along with their respective tooltips.CIconData construction
For object creation, a quad parameter constructor is available that takes icon-pair (icon & hover-icon) identifiers -- where hover-icon is optional -- a tooptip and an optional handler to an icon.
Syntax
// Quad parameter constructor CIconData(
unsigned int uDefaultIconID,
LPSTR lpToolTip,
unsigned int uHoverIconID = 0,
HICON hIcon = NULL
);
// Copy constructorCIconData(
const CIconData &pIconData);
Parameters
uDefaultIconID: Application-defined identifier of an icon, to be showed in the system tray icon notification area.lpToolTip: Pointer to a null-terminated string with the text for a standard ToolTip. It can have a maximum of 64 characters, including the terminatingNULL.uHoverIconID: Application-defined identifier of an icon, to be showed in the system tray icon notification area during mouse-hover.hIcon: Handle to the icon to be added, modified or deleted. To avoid icon distortion, be aware that notification area icons have different levels of support under different versions of Microsoft Windows. Windows 95, Windows 98, and Microsoft Windows NT 4.0 support icons of up to 4 bits per pixel (BPP). Windows Millennium Edition (Windows Me) and Windows 2000 support icons of a color depth up to the current display mode. Windows XP supports icons of up to 32 BPP.
CIconData getters and setters
// Gets the selected icon's identiferunsigned int GetIconID() const;
// Gets the default icon identfierunsigned int GetDefaultIconID() const;
// Sets the default icon identifiervoid SetDefaultIconID(unsigned int uIconID);
// Gets the hover icon identiferunsigned int GetHoverIconID() const;
// Sets the hover icon identifiervoid SetHoverIconID(unsigned int uIconID);
// Gets the tooltipLPSTR GetToolTip() const;// Sets the tooltipvoid SetToolTip(LPSTR lpToolTip);// Gets the icon handlerHICON GetIconHandler() const;CIconData methods
// Selects and loads the speciifed icon into memorybool LoadIcon(unsigned int uIconID);
CIconData synonyms
IconDataPtr
// Synomym for CIconData pointer typedef CIconData* IconDataPtr;How to use
Let's go step-wise to accomplish our task.
Step 1 - starting
Create an application and add the TrayIcon.h, TrayIcon.cpp, TrayIconMouseMsgHandler.h, IconData.h, Utilities.h and MouseMsgHandlerImpl.h files to the project.
Step 2 - pre-empting reusability
It is always beneficial to set up a global header library of reusable utility methods that can be used anywhere in the project.
// Utilities functions// Shows a windowBOOL ShowWnd(CWnd* pWnd)
{return pWnd->ShowWindow(SW_SHOW);
}
// Hides a windowBOOL HideWnd(CWnd* pWnd)
{return pWnd->ShowWindow(SW_HIDE);
}
// Shows a popup menuvoid ShowPopupMenu(CWnd* pWnd, unsigned int uResourseID, int nSubMenuPos)
{CPoint aPos;
GetCursorPos(&aPos);
CMenu aMenu;
aMenu.LoadMenu(uResourseID);
aMenu.GetSubMenu(nSubMenuPos)->TrackPopupMenu(TPM_RIGHTALIGN | TPM_RIGHTBUTTON,
aPos.x,
aPos.y,
pWnd,
0);
}
Step 3 - setting up mouse message handlers
In this phase, we will set up a few classes derived from
CTrayIconMouseMsgHandler to handle mouse notification messages.Setting up left mouse double click message handler
// Left mouse button double click message handlerclass CLeftMouseDblClickMsgHandler:
public CTrayIconMouseMsgHandler{ public: CLeftMouseDblClickMsgHandler() :
CTrayIconMouseMsgHandler(
WM_LBUTTONDBLCLK){} void MouseMsgHandler() {ShowWnd(AfxGetMainWnd());
}
};
Setting up right mouse click message handler
// Right mouse button click message handlerclass CRightMouseClickMsgHandler: public CTrayIconMouseMsgHandler{ public: CRightMouseClickMsgHandler() :
CTrayIconMouseMsgHandler(
WM_RBUTTONDOWN){} void MouseMsgHandler() {ShowPopupMenu(AfxGetMainWnd(),
IDR_TASKBAR_MENU, 0);}
};
Setting up mouse hover message handler
// Mouse hover message handlerclass CMouseHoverMsgHandler:
public CTrayIconMouseMsgHandler{ public: CMouseHoverMsgHandler(CTrayIcon* pTrayIcon) :
CTrayIconMouseMsgHandler(
WM_MOUSEFIRST)
{m_pTrayIcon = pTrayIcon;
}
void SetTrayIcon(CTrayIcon* pTrayIcon) {m_pTrayIcon = pTrayIcon;
}
void MouseMsgHandler() { m_pTrayIcon->HoverIcon();}
private:CTrayIcon* m_pTrayIcon;
};
Step 4 - declaring
Add a member to your class that points to
CTrayIcon.// Declarying CTrayIcon object pointer for adding // an icon to the system tray notification areaCTrayIcon* m_pTrayIcon;
Step 5 - initialization
In this phase, we will initialize the
CTrayIcon object to add icon to the system tray notification area.// Declare an array of MouseMsgHandlerPtr of size 3, // to handle three types of mouse eventsMouseMsgHandlerPtr *pHandler = new MouseMsgHandlerPtr[3];
// Define an object for handling right mouse button // click eventsMouseMsgHandlerPtr rbcHandler =
new CRightMouseClickMsgHandler();// Define an object for handling left mouse button // double click eventsMouseMsgHandlerPtr lbcHandler = new CLeftMouseDblClickMsgHandler();// Define an object for handling mouse hover eventsMouseMsgHandlerPtr mhHandler =
new CMouseHoverMsgHandler(m_pTrayIcon);pHandler[0] = lbcHandler;pHandler[1] = rbcHandler;pHandler[2] = mhHandler;// Declare an array of IconDataPtr of size 2, // to add two sets of icons. Only one will be // active though.IconDataPtr *pIconData = new IconDataPtr[2];
// Define an object of Blue MFC iconpIconData[0] = new CIconData(IDR_MAINFRAME,
_T("CTrayIcon Blue Demo"), IDR_MAINFRAME_HOVER);
// Define an object of Green MFC iconpIconData[1] = new CIconData(
IDR_MAINFRAME_GREEN,
_T("CTrayIcon Green Demo"), IDR_MAINFRAME_HOVER);
// Define the CTrayIcon objectm_pTrayIcon = new CTrayIcon(pHandler,
3, pIconData, 2,
0, SECOND);
// Refer the CTrayIcon object to the // CMouseHoverMsgHandler object, for handling // mouse events((CMouseHoverMsgHandler*)mhHandler)-> SetTrayIcon(m_pTrayIcon);
Step 6 - setting up functionality
In this phase, we will set up functionality to hide, show and animate the system tray notification icon.
Showing the tray notification icon
void CCTrayIconDemoDlg::OnBnClickedBtnshowicon(){ m_pTrayIcon->ShowIcon();}
Hiding the tray notification icon
void CCTrayIconDemoDlg::OnBnClickedBtnhideicon(){ m_pTrayIcon->HideIcon();}
Starting the tray notification icon animation
void CCTrayIconDemoDlg::OnBnClickedBtnstartani(){ m_pTrayIcon->StartIconAnimation();}
Stopping the tray notification icon animation
void CCTrayIconDemoDlg::OnBnClickedBtnstopani(){ m_pTrayIcon->StopIconAnimation();}
Minimizing the window to the tray notification icon
void CCTrayIconDemoDlg::OnBnClickedBtnminimize(){ m_pTrayIcon->ShowIcon(); HideWnd(this);}
Showing the window from the tray notification icon
void CCTrayIconDemoDlg::OnShow() { ShowWnd(this);}
Step 7 - the finishing touch
Once we are done, we release the resources gracefully.
void CCTrayIconDemoDlg::OnCancel() { delete m_pTrayIcon;CDialog::OnCancel();
}
Alternate step - the other way around
In the above steps, we saw how efficiently we can handle the system tray notification icon messages by using the
CTrayIcon class. What if you want to handle those messages in you own CWnd class? Implement this phase if you'd like to handle the system tray notification icon messages in you CWnd or CDialog class. In this example, that class would be the CCTrayIconDemoDlg class. Go to the header file and register a Window message to be handled once the system tray notification icon is created.const unsigned int WM_TI_NOTIFYICON =
::RegisterWindowMessage(_T("TaskBarCreated"));Go to
AFX_MSG and add the line in bold.//{{AFX_MSG(CCTrayIconDemoDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnNotifyIcon(WPARAM wp, LPARAM lp);//}}AFX_MSGThen go to
AFX_MSG_MAP and add the line in bold.//{{AFX_MSG_MAP(CCTrayIconDemoDlg)ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_REGISTERED_MESSAGE(WM_TI_NOTIFYICON, OnNotifyIcon)
//}}AFX_MSG_MAPReplace the
CTrayIcon object creation with the following code.// Define the CTrayIcon objectm_pTrayIcon = new CTrayIcon( this, WM_TI_NOTIFYICON, pHandler, 3, pIconData, 2, 0, SECOND);
Finally, redirect to the
CTaskIcon method.void CCTrayIconDemoDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{ // TODO m_pTrayIcon->OnNotifyIcon(wParam, lParam);}
History
- 23 August, 2004 -- Original version posted
- 6 June, 2007 -- Article and downloads updated