I will not call this an article but rather a comment to all projects that are dealing with balloon tool tips and taskbar notification area (system tray).
I want to show the easiest way to use these controls because "everybody" is complaining about the lack of information on this issue. What is true is that MSDN is not excelling in explaining how to use a balloon tool tip or how to load your application into the tray.
Using the code
My "EasyApp" application on run will display its icon into the system tray with a balloon tool tip associated just like "Local Area Connection Status" standard application. On application icon double click the main dialog will be shown and with mouse over the dialog controls we can see balloon tool tips. By clicking on "Minimize" button the application will be "minimized" into the tray where now we have a regular tool tip. The "magic" is happening inside the
CEasyAppDlg object. First the
_ToolTipCtrl member, which is a simple
CToolTipCtrl MFC object, is initialized using
Create( . ):
// the ToolTip control's style
TTS_NOPREFIX | // prevents the system from
// stripping the ampersand (&)
// character from a string
TTS_BALLOON | // the ToolTip control has the appearance of
// 0x40 // a cartoon "balloon," with rounded corners
// and a stem pointing to the item.
TTS_ALWAYSTIP // the ToolTip will appear when the
// cursor is on a tool, regardless of
// whether the ToolTip control's owner
// window is active or inactive
is not part of the
SetIconAndTitleForBalloonTip( . ) local member is using
TTM_SETTITLE message to add a STANDARD ICON and title string to the tool tip:
CToolTipCtrl *pToolTipCtrl, int tti_ICON, CString title )
return ::SendMessage( (HWND) pToolTipCtrl->m_hWnd,
(UINT) TTM_SETTITLE, // adds a standard icon and
// title string to a ToolTip
// TTI_NONE = 0 - no icon
// TTI_INFO = 1 - information icon
// TTI_WARNING = 2 - warning icon
// TTI_ERROR = 3 - error icon
(LPARAM) (LPCTSTR) title );
The only thing left is to pass the mouse message to the tool tip control for processing using
RelayEvent( . )
BOOL CEasyAppDlg::PreTranslateMessage(MSG* pMsg)
if( pMsg->message == WM_MOUSEMOVE )
_ToolTipCtrl.RelayEvent( pMsg );
It is done with the MS Windows balloon tool tip. Over :-)
To "load" the application into the system tray I have a local member
LoadToTray( . ) that is using
NOTIFYICONDATA structure, which contains information that the system needs to process taskbar status area messages,
Shell_NotifyIcon( . ) to add or delete to the taskbar's status area and
WM_TRAY_NOTIFY user defined message used for callback:
void CEasyAppDlg::LoadToTray( CWnd *pWnd,
CString sInfoTitle, // title for a balloon ToolTip.
// This title appears in boldface above the text
// It can have a maximum of 63 characters
CString sInfo, // the text for a balloon ToolTip, it can have
// a maximum of 255 characters
CString sTip, // the text for a standard ToolTip.
// It can have a maximum of 128 characters,
// including the terminating NULL.
int uTimeout, // in sec.
HICON icon )
ZeroMemory( &_tnd, sizeof( NOTIFYICONDATA ) );
_tnd.cbSize = sizeof( NOTIFYICONDATA );
_tnd.hWnd = pWnd->GetSafeHwnd();
_tnd.uID = 0;
_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
// Flag Description:
// - NIF_ICON The hIcon member is valid.
// - NIF_MESSAGE The uCallbackMessage member is valid.
// - NIF_TIP The szTip member is valid.
// - NIF_STATE The dwState and dwStateMask members are valid.
// - NIF_INFO Use a balloon ToolTip instead of a standard ToolTip.
// The szInfo, uTimeout, szInfoTitle, and
// dwInfoFlags members are valid.
// - NIF_GUID Reserved
_tnd.dwInfoFlags = NIIF_INFO;
// add an icon to a balloon ToolTip
// Flag Description
// - NIIF_ERROR An error icon.
// - NIIF_INFO An information icon.
// - NIIF_NONE No icon.
// - NIIF_WARNING A warning icon.
// - NIIF_ICON_MASK Version 6.0. Reserved.
// - NIIF_NOSOUND Version 6.0. Do not play the
// associated sound. Applies only to balloon ToolTips
_tnd.uCallbackMessage = uCallbackMessage;
_tnd.uTimeout = uTimeout * 1000;
_tnd.hIcon = icon;
strcpy( _tnd.szInfoTitle,sInfoTitle );
strcpy( _tnd.szInfo, sInfo );
strcpy( _tnd.szTip, sTip );
Shell_NotifyIcon( NIM_ADD, &_tnd );
We just call this into
. On callback function the main dialog is "restored" to the screen. Into the destructor (or on exit) we have to use
Shell_NotifyIcon( NIM_DELETE, &_tnd )
to delete from the status area. That’s it. Was not that bad wasn’t it? I know that I plagiarize MSDN and I apologize :-) Good luck! Liviu Birjega