TrayIcon.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /////////////////////////////////////////////////////////////////////////////
  2. // TrayIcon.cpp : implementation file
  3. //
  4. // This is a conglomeration of ideas from the MSJ "Webster" application,
  5. // sniffing round the online docs, and from other implementations such
  6. // as PJ Naughter's "CTrayIconifyIcon" (http://indigo.ie/~pjn/ntray.html)
  7. // especially the "CTrayIcon::OnTrayNotification" member function.
  8. //
  9. // This class is a light wrapper around the windows system tray stuff. It
  10. // adds an icon to the system tray with the specified ToolTip text and
  11. // callback notification value, which is sent back to the Parent window.
  12. //
  13. // The tray icon can be instantiated using either the constructor or by
  14. // declaring the object and creating (and displaying) it later on in the
  15. // program. eg.
  16. //
  17. // CTrayIcon m_TrayIcon; // Member variable of some class
  18. //
  19. // ...
  20. // // in some member function maybe...
  21. // m_TrayIcon.Create(pParentWnd, WM_MY_NOTIFY, "Click here",
  22. // hIcon, nTrayIconID);
  23. //
  24. // Clobbered together by Chris Maunder.
  25. //
  26. //
  27. /////////////////////////////////////////////////////////////////////////////
  28. #include "stdafx.h"
  29. #include "TrayIcon.h"
  30. #include "resource.h"
  31. #ifdef _DEBUG
  32. #define new DEBUG_NEW
  33. #undef THIS_FILE
  34. static char THIS_FILE[] = __FILE__;
  35. #endif
  36. extern BOOL g_bAutoRun;
  37. IMPLEMENT_DYNAMIC(CTrayIcon, CObject)
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CTrayIcon construction/creation/destruction
  40. CTrayIcon::CTrayIcon()
  41. {
  42. memset(&m_tnd, 0, sizeof(m_tnd));
  43. m_bEnabled = FALSE;
  44. m_bHidden = FALSE;
  45. }
  46. CTrayIcon::CTrayIcon(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip,
  47. HICON icon, UINT uID)
  48. {
  49. Create(pWnd, uCallbackMessage, szToolTip, icon, uID);
  50. m_bHidden = FALSE;
  51. }
  52. BOOL CTrayIcon::Create(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip,
  53. HICON icon, UINT uID)
  54. {
  55. // this is only for Windows 95 (or higher)
  56. VERIFY(m_bEnabled = ( GetVersion() & 0xff ) >= 4);
  57. if (!m_bEnabled) return FALSE;
  58. //Make sure Notification window is valid
  59. VERIFY(m_bEnabled = (pWnd && ::IsWindow(pWnd->GetSafeHwnd())));
  60. if (!m_bEnabled) return FALSE;
  61. //Make sure we avoid conflict with other messages
  62. ASSERT(uCallbackMessage >= WM_USER);
  63. //Tray only supports tooltip text up to 64 characters
  64. ASSERT(_tcslen(szToolTip) <= 64);
  65. // load up the NOTIFYICONDATA structure
  66. m_tnd.cbSize = sizeof(NOTIFYICONDATA);
  67. m_tnd.hWnd = pWnd->GetSafeHwnd();
  68. m_tnd.uID = uID;
  69. m_tnd.hIcon = icon;
  70. m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  71. m_tnd.uCallbackMessage = uCallbackMessage;
  72. lstrcpy (m_tnd.szTip, szToolTip);
  73. // Set the tray icon
  74. //
  75. (m_bEnabled = Shell_NotifyIcon(NIM_ADD, &m_tnd));
  76. return m_bEnabled;
  77. }
  78. CTrayIcon::~CTrayIcon()
  79. {
  80. RemoveIcon();
  81. }
  82. /////////////////////////////////////////////////////////////////////////////
  83. // CTrayIcon icon manipulation
  84. void CTrayIcon::MoveToRight()
  85. {
  86. HideIcon();
  87. ShowIcon();
  88. }
  89. void CTrayIcon::RemoveIcon()
  90. {
  91. if (!m_bEnabled) return;
  92. m_tnd.uFlags = 0;
  93. Shell_NotifyIcon(NIM_DELETE, &m_tnd);
  94. m_bEnabled = FALSE;
  95. }
  96. void CTrayIcon::HideIcon()
  97. {
  98. if (m_bEnabled && !m_bHidden) {
  99. m_tnd.uFlags = NIF_ICON;
  100. Shell_NotifyIcon (NIM_DELETE, &m_tnd);
  101. m_bHidden = TRUE;
  102. }
  103. }
  104. void CTrayIcon::ShowIcon()
  105. {
  106. if (m_bEnabled && m_bHidden) {
  107. m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  108. Shell_NotifyIcon(NIM_ADD, &m_tnd);
  109. m_bHidden = FALSE;
  110. }
  111. }
  112. BOOL CTrayIcon::SetIcon(HICON hIcon)
  113. {
  114. if (!m_bEnabled) return FALSE;
  115. m_tnd.uFlags = NIF_ICON;
  116. m_tnd.hIcon = hIcon;
  117. return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
  118. }
  119. BOOL CTrayIcon::SetIcon(LPCTSTR lpszIconName)
  120. {
  121. HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);
  122. return SetIcon(hIcon);
  123. }
  124. BOOL CTrayIcon::SetIcon(UINT nIDResource)
  125. {
  126. HICON hIcon = AfxGetApp()->LoadIcon(nIDResource);
  127. return SetIcon(hIcon);
  128. }
  129. BOOL CTrayIcon::SetStandardIcon(LPCTSTR lpIconName)
  130. {
  131. HICON hIcon = LoadIcon(NULL, lpIconName);
  132. return SetIcon(hIcon);
  133. }
  134. BOOL CTrayIcon::SetStandardIcon(UINT nIDResource)
  135. {
  136. HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(nIDResource));
  137. return SetIcon(hIcon);
  138. }
  139. HICON CTrayIcon::GetIcon() const
  140. {
  141. HICON hIcon = NULL;
  142. if (m_bEnabled)
  143. hIcon = m_tnd.hIcon;
  144. return hIcon;
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. // CTrayIcon tooltip text manipulation
  148. BOOL CTrayIcon::SetTooltipText(LPCTSTR pszTip)
  149. {
  150. if (!m_bEnabled) return FALSE;
  151. m_tnd.uFlags = NIF_TIP;
  152. _tcscpy(m_tnd.szTip, pszTip);
  153. return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
  154. }
  155. BOOL CTrayIcon::SetTooltipText(UINT nID)
  156. {
  157. CString strText;
  158. VERIFY(strText.LoadString(nID));
  159. return SetTooltipText(strText);
  160. }
  161. CString CTrayIcon::GetTooltipText() const
  162. {
  163. CString strText;
  164. if (m_bEnabled)
  165. strText = m_tnd.szTip;
  166. return strText;
  167. }
  168. /////////////////////////////////////////////////////////////////////////////
  169. // CTrayIcon notification window stuff
  170. BOOL CTrayIcon::SetNotificationWnd(CWnd* pWnd)
  171. {
  172. if (!m_bEnabled) return FALSE;
  173. //Make sure Notification window is valid
  174. ASSERT(pWnd && ::IsWindow(pWnd->GetSafeHwnd()));
  175. m_tnd.hWnd = pWnd->GetSafeHwnd();
  176. m_tnd.uFlags = 0;
  177. return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
  178. }
  179. CWnd* CTrayIcon::GetNotificationWnd() const
  180. {
  181. return CWnd::FromHandle(m_tnd.hWnd);
  182. }
  183. /////////////////////////////////////////////////////////////////////////////
  184. // CTrayIcon implentation of OnTrayNotification
  185. LRESULT CTrayIcon::OnTrayNotification(UINT wParam, LONG lParam)
  186. {
  187. //Return quickly if its not for this tray icon
  188. if (wParam != m_tnd.uID)
  189. return 0L;
  190. CMenu menu, *pSubMenu;
  191. // Clicking with right button brings up a context menu
  192. if (LOWORD(lParam) == WM_RBUTTONUP)
  193. {
  194. if (!menu.LoadMenu(m_tnd.uID)) return 0;
  195. if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
  196. // Make first menu item the default (bold font)
  197. ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
  198. //Display and track the popup menu
  199. CPoint pos;
  200. GetCursorPos(&pos);
  201. ::SetForegroundWindow(m_tnd.hWnd);
  202. ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0, m_tnd.hWnd, NULL);
  203. //pSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pos.x, pos.y, this, NULL);
  204. menu.DestroyMenu();
  205. }
  206. else if (LOWORD(lParam) == WM_LBUTTONDBLCLK || LOWORD(lParam) == WM_LBUTTONDOWN)
  207. {
  208. if (!menu.LoadMenu(m_tnd.uID)) return 0;
  209. if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
  210. // double click received, the default action is to execute first menu item
  211. ::SetForegroundWindow(m_tnd.hWnd);
  212. ::SendMessage(m_tnd.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0);
  213. menu.DestroyMenu();
  214. }
  215. return 1;
  216. }