Minimize your app to systray in 8 easy steps






4.71/5 (21 votes)
Feb 2, 2004
2 min read

165645

5640
Minimize your app to systray in 8 easy steps
Introduction
This article explains the use of Shell_NotifyIcon
to create
and manage System Tray icons with your own application.
The article explains the basics of this procedure and
provides a walk in to create your own 'Minimize To Tray'
applications. The article provides 8 easy steps to follow
and make your app work in system tray and handle your tray notifications.
The source code provided with this article is designed to
work with dialog-based applications.
Tray Icons
To use tray Icons you have to call a shell function :)
BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid );
The dwMessage
specifys the NIM_ADD,NIM_DELETE and NIM_MODIFY
which adds ,delete and modifies an icon in system tray.
PNOTIFYICONDATA
structure contains information that the system needs to process taskbar status area messages.
typedef struct _NOTIFYICONDATA { DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; #if (_WIN32_IE < 0x0500) TCHAR szTip[64]; #else TCHAR szTip[128]; #endif #if (_WIN32_IE >= 0x0500) DWORD dwState; DWORD dwStateMask; TCHAR szInfo[256]; union { UINT uTimeout; UINT uVersion; } DUMMYUNIONNAME; TCHAR szInfoTitle[64]; DWORD dwInfoFlags; #endif #if (_WIN32_IE >= 0x600) GUID guidItem; #endif } NOTIFYICONDATA, *PNOTIFYICONDATA;
*Note: For complete information see MSDN.
Creating the Application
Create a new VC++ dialog based project and call it TrayMin.
Step: 1
Define user message in the TrayMinDlg.h header file.
#define WM_TRAY_MESSAGE (WM_USER + 1)
The WM_USER
constant is used by applications to help define
private messages for use by private window classes,
usually of the form WM_USER+X
, where X is an integer value.
*See MSDN for more details.
Step: 2
Now add the handler for this user function in TrayMinDlg.h
file before the DECLARE_MESSAGE_MAP()
afx_msg void OnTrayNotify(WPARAM wParam, LPARAM lParam);
This is icon's callback message when you add the icon to the
taskbar. The callback message identifier is specified in the
uCallbackMessage
member of the NOTIFYICONDATA
structure
passed with NIM_ADD
(We will see this little later).
When an event occurs, the system sends
the callback message to the window procedure of the window
specified by the hWnd
member. The wParam
parameter of the
message contains the identifier of the taskbar icon in which
the event occurred. The lParam
parameter holds the mouse or
keyboard message associated with the event. For example,
when the mouse pointer moves onto a taskbar icon, lParam
contains WM_MOUSEMOVE
.
Step: 3
Now add the following line in main message map of TrayMinDlg.cpp
ON_MESSAGE(WM_TRAY_ICON_NOTIFY_MESSAGE,OnTrayNotify)
Which should now look like this.
BEGIN_MESSAGE_MAP(CTrayMinDlg, CDialog) //{{AFX_MSG_MAP(CTrayMinDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_TRAY_MESSAGE ,OnTrayNotify) //}}AFX_MSG_MAP END_MESSAGE_MAP()
Step: 4
Now add OnTrayNotify
function's definition in the TrayMinDlg.cpp
don't forget to add afx_msg
before the function.
afx_msg void CTrayMinDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam) { UINT uID; UINT uMsg; uID = (UINT) wParam; uMsg = (UINT) lParam; if (uID != 1) return; CPoint pt; switch (uMsg ) { case WM_LBUTTONDOWN: GetCursorPos(&pt); ClientToScreen(&pt); OnTrayLButtonDown(pt); break; case WM_RBUTTONDOWN: case WM_CONTEXTMENU: GetCursorPos(&pt); OnTrayRButtonDown(pt); break; } return; }
Step: 5
Now add two member functions in the TrayMinDlg
class to
handle the mouse events.
To handle Left Button Down/Click add the following function.
- Function Type:
void
- Function Declaration:
OnTrayLButtonDown(CPoint pt)
To handle Right Button Down/Click add the following function.
- Function Type:
void
- Function Declaration:
OnTrayRButtonDown(CPoint pt)
The Declaration of OnTrayLButtonDown(CPoint pt)
is as following.
void CTrayMinDlg::OnTrayLButtonDown(CPoint pt) { MessageBox("You have clicked Left mouse Button "); }
The Declaration of OnTrayRButtonDown(CPoint pt)
is as following.
void CTrayMinDlg::OnTrayRButtonDown(CPoint pt) { //m_menu is the member of CTrayMinDlg as CMenu m_menu; m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_BOTTOMALIGN| TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this); }
Step: 6
Add two member variable to the CTrayMinDlg
.
- Variable Type:
NOTIFYICONDATA
- Variable Name:
m_TrayData
; - Variable Type:
CMenu
- Variable Name:
m_menu
;
Now add a menu resource.
Step: 7
Now draw a minimize button on the dialog and write the following in it.
void CShellDlg::OnMinimize() { m_TrayData.cbSize = sizeof(NOTIFYICONDATA); //Size of this structure, in bytes. m_TrayData.hWnd = this->m_hWnd; //Handle to the window that receives notification //messages associated with an icon in the taskbar //status area. The Shell uses hWnd and uID to //identify which icon to operate on when //Shell_NotifyIcon is invoked. m_TrayData.uID = 1; //Application-defined identifier of the taskbar icon. //The Shell uses hWnd and uID to identify which icon //to operate on when Shell_NotifyIcon is invoked. You // can have multiple icons associated with a single //hWnd by assigning each a different uID. m_TrayData.uCallbackMessage = WM_TRAY_MESSAGE; //Application-defined message identifier. The system //uses this identifier to send notifications to the //window identified in hWnd. These notifications are //sent when a mouse event occurs in the bounding //rectangle of the icon, or when the icon is selected //or activated with the keyboard. The wParam parameter //of the message contains the identifier of the taskbar //icon in which the event occurred. The lParam parameter //holds the mouse or keyboard message associated with the // event. For example, when the pointer moves over a //taskbar icon, lParam is set to WM_MOUSEMOVE. m_TrayData.hIcon = this->m_hIcon; //Handle to the icon to be added, modified, or deleted strcpy(m_TrayData.szTip,"My Icon"); //Pointer to a null-terminated string with the text //for a standard ToolTip. It can have a maximum of 64 //characters including the terminating NULL. m_TrayData.uFlags = NIF_ICON|NIF_MESSAGE; //Flags that indicate which of the other members contain valid data. BOOL bSuccess = FALSE; BOOL BSus = FALSE; BSus = m_menu.LoadMenu(IDR_MENU1); if(!(BSus)) MessageBox("Unabled to Loa menu"); bSuccess = Shell_NotifyIcon(NIM_ADD,&m_TrayData); if(!(bSuccess)) MessageBox("Unable to Set Tary Icon"); else { this->ShowWindow(SW_MINIMIZE); this->ShowWindow(SW_HIDE); } }
Step: 8
In the exit menu write the following:
Shell_NotifyIcon(NIM_DELETE,&m_TrayData); DestroyWindow();
Now Run the app and Press the minimize button and your app will be minimized to taskbar. Fell free to modify and improve these steps.