Skip to content

Instantly share code, notes, and snippets.

@BojanKomazec
Created October 4, 2017 16:23
Show Gist options
  • Save BojanKomazec/b52c53d2373aed747224f058a8e3d474 to your computer and use it in GitHub Desktop.
Save BojanKomazec/b52c53d2373aed747224f058a8e3d474 to your computer and use it in GitHub Desktop.
MFC: Adding tray icon to the window
#include <stdafx.h>
...
// tray icon ID
#define ID_SYSTEMTRAY 0x1000
// custom message ID
#define WM_TRAYICON_EVENT (WM_APP + 1)
// tray icon resource ID
#define ID_ICON_TRAY_INITIAL 0x2000
class CMyDlg : public CDialog
{
...
protected:
// tray icon data
NOTIFYICONDATA m_NID;
CPoint m_ptMouseHoverEvent;
// adds icon to the system tray
BOOL CreateTrayIcon();
// displays rectangular tip
BOOL SetTrayIconTipText(LPCTSTR pszText);
// displays baloon notification
// unTimeout is in milliseconds
BOOL ShowTrayIconBalloon(LPCTSTR pszTitle, LPCTSTR pszText, UINT unTimeout, DWORD dwInfoFlags);
// sets icon resource
BOOL SetTrayIcon(HICON hIcon);
// sets icon resource
BOOL SetTrayIcon(WORD wIconID);
// removes icon from tray
BOOL DestroyTrayIcon();
...
// WM_INITDIALOG handler
virtual BOOL OnInitDialog();
// WM_DESTROY handler
afx_msg void OnDestroy();
// WM_TRAYICON_EVENT handler
afx_msg LRESULT OnTrayIconEvent(WPARAM wParam, LPARAM lParam);
};
BOOL CMyDlg::CreateTrayIcon()
{
memset(&m_NID, 0 , sizeof(m_NID));
m_NID.cbSize = sizeof(m_NID);
// set tray icon ID
m_NID.uID = ID_SYSTEMTRAY;
// set handle to the window that receives tray icon notifications
ASSERT(::IsWindow(GetSafeHwnd()));
m_NID.hWnd = GetSafeHwnd();
// set message that will be sent from tray icon to the window
m_NID.uCallbackMessage = WM_TRAYICON_EVENT;
// fields that are being set when adding tray icon
m_NID.uFlags = NIF_MESSAGE|NIF_ICON;
// set image
m_NID.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(ID_ICON_TRAY_INITIAL));
if(!m_NID.hIcon)
return FALSE;
m_NID.uVersion = NOTIFYICON_VERSION_4;
if(!Shell_NotifyIcon(NIM_ADD, &m_NID))
return FALSE;
return Shell_NotifyIcon(NIM_SETVERSION, &m_NID);
}
BOOL CMyDlg::DestroyTrayIcon()
{
return Shell_NotifyIcon(NIM_DELETE, &m_NID);
}
BOOL CMyDlg::SetTrayIconTipText(LPCTSTR pszText)
{
if(StringCchCopy(m_NID.szTip, sizeof(m_NID.szTip), pszText) != S_OK)
return FALSE;
m_NID.uFlags |= NIF_TIP;
return Shell_NotifyIcon(NIM_MODIFY, &m_NID);
}
BOOL CMyDlg::ShowTrayIconBalloon(LPCTSTR pszTitle, LPCTSTR pszText, UINT unTimeout, DWORD dwInfoFlags)
{
m_NID.uFlags |= NIF_INFO;
m_NID.uTimeout = unTimeout;
m_NID.dwInfoFlags = dwInfoFlags;
if(StringCchCopy(m_NID.szInfoTitle, sizeof(m_NID.szInfoTitle), pszTitle) != S_OK)
return FALSE;
if(StringCchCopy(m_NID.szInfo, sizeof(m_NID.szInfo), pszText) != S_OK)
return FALSE;
return Shell_NotifyIcon(NIM_MODIFY, &m_NID);
}
BOOL CMyDlg::SetTrayIcon(HICON hIcon)
{
m_NID.hIcon = hIcon;
m_NID.uFlags |= NIF_ICON;
return Shell_NotifyIcon(NIM_MODIFY, &m_NID);
}
BOOL CMyDlg::SetTrayIcon(WORD wIconID)
{
HICON hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(wIconID));
if(!hIcon)
return FALSE;
return SetTrayIcon(hIcon);
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
...
ON_MESSAGE(WM_TRAYICON_EVENT, OnTrayIconEvent)
...
END_MESSAGE_MAP()
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...
CreateTrayIcon();
// Add following line in order to enable tip from the beginning.
// Tip shows automatically each time mouse pointer is over tray icon.
SetTrayIconTipText(TEXT("Initial tip text"));
...
return TRUE;
}
void CMyDlg::OnDestroy()
{
...
DestroyTrayIcon();
...
CDialog::OnDestroy();
}
LRESULT CMyDlg::OnTrayIconEvent(WPARAM wParam, LPARAM lParam)
{
if((UINT)wParam != ID_SYSTEMTRAY)
return ERROR_SUCCESS;
switch((UINT)lParam)
{
case WM_MOUSEMOVE:
{
// do something
// e.g. save mouse position in time of event
GetCursorPos(&m_ptMouseHoverEvent);
...
break;
}
case WM_LBUTTONUP:
{
// e.g. show main dialog or set (new) tip text and display baloon:
CTime timeCurr = CTime::GetCurrentTime();
CString strTimeCurr;
strTimeCurr.Format(TEXT("%d:%d:%d"), timeCurr.GetHour(), timeCurr.GetMinute(), timeCurr.GetSecond());
CString strText(TEXT("This text was set at "));
strText += strTimeCurr;
SetTrayIconTipText((LPCTSTR)strText);
ShowTrayIconBalloon(TEXT("Baloon message title"), TEXT("Left click!"), 1000, NIIF_INFO);
break;
}
case WM_RBUTTONUP:
{
// e.g. show context menu or disable tip and display baloon:
SetTrayIconTipText((LPCTSTR)TEXT(""));
ShowTrayIconBalloon(TEXT("Baloon message title"), TEXT("Right click!"), 1000, NIIF_INFO);
break;
}
}
return ERROR_SUCCESS;
}
@ajtruckle
Copy link

I have changed the code to use if (_tcscpy_s(m_NID.szTip, m_strTrayIconTip) != S_OK).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment