Tuesday, February 17, 2009

[VC++] Adding icon to system tray

Here is how to create a tray icon for your application and showing system tray menu. For this you need to add an icon to the system tray using Shell_NotifyIcon() and you need to handle the tray message for the added icon. Below is the code for adding tray icon and showing a menu saying Test Tray Icon on clicking the tray icon.
Modify dialog class header creating a member variable for system tray menu and adding declaration of shell tray icon message handler.

protected:
...
afx_msg HRESULT OnSystemTrayIconClick( WPARAM wParam_i, LPARAM lParam_i );

private:
...
CMenu m_TrayMenu;

Modify dialog class Cpp file adding global constants for tray icon message handling and tray icon id

const UINT SHELL_TRAY_ICON = 2001; // Shell Tray icon ID
const UINT SHELL_TRAY_MSG = (WM_APP+2000); // Message name for tray icon messages
const UINT SHELL_TRAY_TEST_ID = 2100; // ID of shell tray menuitem

Modify dialog class Cpp file adding tray icon adding code in OnInitdialog

void CSampleDlg::OnInitDialog()
{
...
NOTIFYICONDATA stNotifyIconData;
stNotifyIconData.cbSize = sizeof( NOTIFYICONDATA );
stNotifyIconData.hWnd = GetSafeHwnd();
stNotifyIconData.uID = SHELL_TRAY_ICON;
stNotifyIconData.uFlags = NIF_MESSAGE NIF_ICON NIF_TIP;
stNotifyIconData.uCallbackMessage = SHELL_TRAY_MSG;
stNotifyIconData.hIcon = AfxGetApp()->LoadIcon( IDR_MAINFRAME );
strncpy( stNotifyIconData.szTip, "TestShellTrayIcon",sizeof"TestShellTrayIcon"));
Shell_NotifyIcon( NIM_ADD, &stNotifyIconData );
m_TrayMenu.CreatePopupMenu();
m_TrayMenu.InsertMenu( 0, MF_BYCOMMAND|MF_POPUP,SHELL_TRAY_TEST_ID, "Test Tray Icon" );
return TRUE;
}

Add entry to message map for mapping tray icon message

BEGIN_MESSAGE_MAP( CSampleDlg, CDialog )
...
ON_MESSAGE ( SHELL_TRAY_MSG, OnSystemTrayIconClick )
END_MESSAGE_MAP()

Now implement the tray icon message handler which will handle mouse LButton and RButton down by showing a menu

HRESULT CSampleDlg::OnSystemTrayIconClick( WPARAM wParam_i, LPARAM lParam_i )
{
switch( wParam_i )
{
case SHELL_TRAY_ICON:
{
switch( lParam_i )
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
{
POINT CurPos ;
GetCursorPos( &CurPos );
SetForegroundWindow();
TrackPopupMenu( m_TrayMenu, TPM_LEFTBUTTON, CurPos.x, CurPos.y, 0, GetSafeHwnd(), 0 );
PostMessage( WM_NULL, 0, 0 );
}
break ;
}
}
break ;
default:
OutputDebugString ("invalid icon id from tray\n");
break ;
}
return TRUE ;
}

No comments: