CSystem Tray

CMDCO2다이어트COMCOM 인터페이스CRegistry CSystemTray

codeguru : Adding Icons to the System Tray
download : @SystemTray.zip (5.62 KB)
Chris Maunder (view profile)
February 6, 2000



1 Construction

CSystemTray();
CSystemTray(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip, HICON icon, UINT uID);
BOOL Create(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip, HICON icon, UINT uID);

Note that the destructor automatically removes the icon from the tray.

pWnd Window where notification messages will be sent. May be NULL
uCallbackMessage The notification messages that will be sent to the parent window
szToolTip Tooltip for the tray icon
icon Handle to the icon to be displayed
uID Tray icon

If the pWnd parameter is NULL then the function CSystemTray::OnTrayNotification will be called whenever the icon sends a notification message. See Default message handling for more details.


2 Operations

LRESULT OnTrayNotification(WPARAM wID, LPARAM lEvent) 
Discussed below

void    MoveToRight() 
Moves the icon to the far right of the tray,
so it is immediately to the left of the clock

void    RemoveIcon()
Removes the icon from the tray (icon can nolonger be manipulated)

void    HideIcon()
Hides but does not totally remove the icon from the tray.

void    ShowIcon() 
Redisplays a previously hidden icon

BOOL    SetTooltipText(LPCTSTR pszTip) 
Set Tooltip text

BOOL    SetTooltipText(UINT nID) 
Set tooltip from text resource ID

CString GetTooltipText() const 
Retrieve tool tip text

BOOL    SetNotificationWnd(CWnd* pWnd) 
Self explanatory

CWnd*   GetNotificationWnd() const 

HICON   GetIcon() const 
Get current tray icon

BOOL    SetIcon(HICON hIcon) 
Change tray icon. Returns FALSE if unsuccessful

BOOL    SetIcon(LPCTSTR lpszIconName) 
Same, using name of the icon resource

BOOL    SetIcon(UINT nIDResource) 
Same, using icon resource ID

BOOL    SetStandardIcon(LPCTSTR lpIconName) 
Load icon from the current application.

BOOL    SetStandardIcon(UINT nIDResource) 


BOOL    SetIconList(UINT uFirstIconID, UINT uLastIconID); 
Set list of icons for animation

BOOL    SetIconList(HICON* pHIconList, UINT nNumIcons); 


BOOL    Animate(UINT nDelayMilliSeconds, int nNumSeconds = -1); 
Start animation

BOOL    StepAnimation(); 
Step to next icon

BOOL    StopAnimation();  
Stop animation

BOOL SetMenuDefaultItem(UINT uItem, BOOL bByPos); 
Set default menu item

void GetMenuDefaultItem(UINT& uItem, BOOL& bByPos); 
Get default menu item


SetStandardIcon can also take any of the following values:
nIDResource             Description                                         
IDI_APPLICATION         Default application icon.
IDI_ASTERISK            Asterisk (used in informative messages).
IDI_EXCLAMATION         Exclamation point (used in warning messages).
IDI_HAND                Hand-shaped icon (used in serious warning messages).
IDI_QUESTION            Question mark (used in prompting messages).
IDI_WINLOGO             Windows logo      
The default CSystemTray message notification handler searches and displays the menu with the same ID as the tray icon. If you use this default handler then you can set the default menu item using SetMenuDefaultItem. The parameters uItem and bByPos are the same as those used in ::SetMenuDefaultItem.

The default menu item code was contributed by Enrico Lelina.

Icon animation

Icon animation can be achieved by specifying a list of icons using SetIconList(...), with either a range of icon resource IDs, or an array of HICONS and the size of the array. Use "Animate(UINT nDelayMilliSeconds, int nNumSeconds)" to start the animation. The first parameter is the delay in milliseconds between displaying each icon in the list, and the second is the number of seconds for which to animate the icons. If -1 is specified then animation will continue until StopAnimation() is called.

Icon animation suggested by Joerg Koenig.


3 Default message handling

The parent window, on receiving a notification message, can redirect this message back to the tray icon for handling by calling CSystemTray::OnTrayNotification(...). Alternatively, if the CSystemTray object was created with a NULL parent, then this function will be called whenever the icon sends a notification. The default implementation tries to find a menu with the same resource ID as the tray icon. If it finds a menu and the event received was a right mouse button up, then the submenu is displayed as a context menu. If a double click was received, then the message ID of default item in the submenu (set using SetMenuDefaultItem) is sent back to the parent window. If SetMenuDefaultItem has not been called then the default menu item will be the first item in the menu


4 Example of use

A good place to declare the tray icon is in your CFrameWnd derived class.
eg.

#define WM_ICON_NOTIFY  WM_USER+10
CSystemTray m_TrayIcon


Add a message map entry for the tray icon notification:

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	...
	ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
END_MESSAGE_MAP()

Create the icon (maybe in your OnCreate):

if (!m_TrayIcon.Create(this, WM_ICON_NOTIFY, strToolTip, hIcon, IDR_POPUP_MENU))
	return -1;

where IDR_POPUP_MENU is the ID of a popup menu to display for the icon. You then need a handler for the tray icon notification message:

LRESULT CMainFrame::OnTrayNotification(WPARAM wParam, LPARAM lParam)
{
	// Delegate all the work back to the default implementation in CSystemTray.
	return m_TrayIcon.OnTrayNotification(wParam, lParam);
}

The menu used (IDR_POPUP_MENU) looks like the following:

IDR_POPUP_MENU MENU PRELOAD DISCARDABLE
BEGIN
	POPUP "POPUP_MENU"
	BEGIN
		MENUITEM "&About...",      ID_APP_ABOUT
		MENUITEM SEPARATOR
		MENUITEM "&Options...",    ID_APP_OPTIONS
		MENUITEM SEPARATOR
		MENUITEM "E&xit",          ID_APP_EXIT
	END
END

5 NOTE on TrackPopupMenu

Many people have had troubles using TrackPopupMenu. They have reported that the popup menu will often not disappear once the mouse is clicked outside of the menu, even though they have set the last parameter of TrackPopupMenu() as NULL. This is a Microsoft "feature", and is by design. The mind boggles, doesn't it?

Anyway - to workaround this "feature", one must set the current window as the foreground window before calling TrackPopupMenu. This then causes a second problem - namely that the next time the menu is displayed it displays then immediately disappears. To fix this problem, you must make the currernt application active after the menu disappears. This can be done by sending a benign message such as WM_NULL to the current window.

So - what should have been a simple:

TrackPopupMenu(hSubMenu, TPM_RIGHTBUTTON, pt.x,pt.y, 0, hDlg, NULL);
becomes

SetForegroundWindow(hDlg);
TrackPopupMenu(hSubMenu, TPM_RIGHTBUTTON, pt.x,pt.y, 0, hDlg, NULL);
PostMessage(hDlg, WM_NULL, 0, 0);

Refer to KB article "PRB: Menus for Notification Icons Don't Work Correctly" for more info.



ID
Password
Join





- 전 이런 놈입니다.

격언> 문제를 해결하는 첫걸음은 그것을 누군가에게 털어놓는 것이다. (존 피터 플린)

Recent Changes

D  Echoes Of War(The... @ 2012-05-18 [03:44 pm] by windlesszone
D  Diablo3 @ 2012-05-15 [04:49 pm] by windlesszone
D  Diablo3/story/wizard @ 2012-05-15 [04:48 pm] by windlesszone 4 changes
D  Diablo3/story/wit... @ 2012-05-15 [04:16 pm] by windlesszone
D  Diablo3/story/monk @ 2012-05-15 [04:14 pm] by windlesszone





Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2006-04-03 13:14:17
Processing time 0.0782 sec