Created
October 4, 2017 16:23
-
-
Save BojanKomazec/b52c53d2373aed747224f058a8e3d474 to your computer and use it in GitHub Desktop.
MFC: Adding tray icon to the window
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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
Firstly, thank you very much for this code! But I have a couple of questions:
1/ How can we address thus buffer overrun code analysis warning (other than supressing the warning):
2/ I have an embedded PNG image in my MFC project, it is possible to use that for the icon?