-
Notifications
You must be signed in to change notification settings - Fork 0
/
TrayIconImpl.h
164 lines (152 loc) · 3.84 KB
/
TrayIconImpl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// See Robert Edward Caldecott's article on Code Project: http://www.codeproject.com/wtl/wtltrayicon.asp
// Implementation of the CNotifyIconData class and the CTrayIconImpl template.
#pragma once
#include <atlmisc.h>
// Wrapper class for the Win32 NOTIFYICONDATA structure
class CNotifyIconData : public NOTIFYICONDATA
{
public:
CNotifyIconData()
{
memset(this, 0, sizeof(NOTIFYICONDATA));
cbSize = sizeof(NOTIFYICONDATA);
}
};
// Template used to support adding an icon to the taskbar.
// This class will maintain a taskbar icon and associated context menu.
template <class T>
class CTrayIconImpl
{
private:
UINT WM_TRAYICON;
CNotifyIconData m_nid;
bool m_bInstalled;
UINT m_nDefault;
public:
CTrayIconImpl() : m_bInstalled(false), m_nDefault(0)
{
WM_TRAYICON = ::RegisterWindowMessage(_T("WM_TRAYICON"));
}
~CTrayIconImpl()
{
// Remove the icon
RemoveIcon();
}
// Install a taskbar icon
// lpszToolTip - The tooltip to display
// hIcon - The icon to display
// nID - The resource ID of the context menu
/// returns true on success
bool InstallIcon(LPCTSTR lpszToolTip, HICON hIcon, UINT nID)
{
T* pT = static_cast<T*>(this);
// Fill in the data
m_nid.hWnd = pT->m_hWnd;
m_nid.uID = nID;
m_nid.hIcon = hIcon;
m_nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
m_nid.uCallbackMessage = WM_TRAYICON;
#if _MSC_VER < 1400
_tcscpy(m_nid.szTip, lpszToolTip);
#else
_tcscpy_s(m_nid.szTip, _countof(m_nid.szTip), lpszToolTip);
#endif
// Install
m_bInstalled = Shell_NotifyIcon(NIM_ADD, &m_nid) ? true : false;
// Done
return m_bInstalled;
}
// Remove taskbar icon
// returns true on success
bool RemoveIcon()
{
if (!m_bInstalled)
return false;
// Remove
m_nid.uFlags = 0;
return Shell_NotifyIcon(NIM_DELETE, &m_nid) ? true : false;
}
// Set the icon tooltip text
// returns true on success
bool SetTooltipText(LPCTSTR pszTooltipText)
{
if (pszTooltipText == NULL)
return FALSE;
// Fill the structure
m_nid.uFlags = NIF_TIP;
_tcscpy(m_nid.szTip, pszTooltipText);
// Set
return Shell_NotifyIcon(NIM_MODIFY, &m_nid) ? true : false;
}
// Set the default menu item ID
inline void SetDefaultItem(UINT nID) { m_nDefault = nID; }
BEGIN_MSG_MAP(CTrayIcon)
MESSAGE_HANDLER(WM_TRAYICON, OnTrayIcon)
END_MSG_MAP()
LRESULT OnTrayIcon(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
// Is this the ID we want?
if (wParam != m_nid.uID)
return 0;
T* pT = static_cast<T*>(this);
// Was the right-button clicked?
if (LOWORD(lParam) == WM_RBUTTONUP)
{
// Load the menu
CMenu oMenu;
if (!oMenu.LoadMenu(m_nid.uID))
return 0;
// Get the sub-menu
CMenuHandle oPopup(oMenu.GetSubMenu(0));
// Prepare
pT->PrepareMenu(oPopup);
// Get the menu position
CPoint pos;
GetCursorPos(&pos);
// Make app the foreground
SetForegroundWindow(pT->m_hWnd);
// Set the default menu item
if (m_nDefault == 0)
oPopup.SetMenuDefaultItem(0, TRUE);
else
oPopup.SetMenuDefaultItem(m_nDefault);
// Track
oPopup.TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, pT->m_hWnd);
// BUGFIX: See "PRB: Menus for Notification Icons Don't Work Correctly"
pT->PostMessage(WM_NULL);
// Done
oMenu.DestroyMenu();
}
else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
{
// Make app the foreground
SetForegroundWindow(pT->m_hWnd);
// Load the menu
CMenu oMenu;
if (!oMenu.LoadMenu(m_nid.uID))
return 0;
// Get the sub-menu
CMenuHandle oPopup(oMenu.GetSubMenu(0));
// Get the item
if (m_nDefault)
{
// Send
pT->SendMessage(WM_COMMAND, m_nDefault, 0);
}
else
{
UINT nItem = oPopup.GetMenuItemID(0);
// Send
pT->SendMessage(WM_COMMAND, nItem, 0);
}
// Done
oMenu.DestroyMenu();
}
return 0;
}
// Allow the menu items to be enabled/checked/etc.
virtual void PrepareMenu(HMENU hMenu)
{
// Stub
}
};