TrayIcon.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. IMPLEMENT_DYNAMIC(CTrayIcon, CObject)
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CTrayIcon construction/creation/destruction
  39. CTrayIcon::CTrayIcon()
  40. {
  41. memset(&m_tnd, 0, sizeof(m_tnd));
  42. m_bEnabled = FALSE;
  43. m_bHidden = FALSE;
  44. }
  45. CTrayIcon::CTrayIcon(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip,
  46. HICON icon, UINT uID)
  47. {
  48. Create(pWnd, uCallbackMessage, szToolTip, icon, uID);
  49. m_bHidden = FALSE;
  50. }
  51. BOOL CTrayIcon::Create(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip,
  52. HICON icon, UINT uID)
  53. {
  54. // this is only for Windows 95 (or higher)
  55. VERIFY(m_bEnabled = ( GetVersion() & 0xff ) >= 4);
  56. if (!m_bEnabled) return FALSE;
  57. //Make sure Notification window is valid
  58. VERIFY(m_bEnabled = (pWnd && ::IsWindow(pWnd->GetSafeHwnd())));
  59. if (!m_bEnabled) return FALSE;
  60. //Make sure we avoid conflict with other messages
  61. ASSERT(uCallbackMessage >= WM_USER);
  62. //Tray only supports tooltip text up to 64 characters
  63. ASSERT(_tcslen(szToolTip) <= 64);
  64. // load up the NOTIFYICONDATA structure
  65. m_tnd.cbSize = sizeof(NOTIFYICONDATA);
  66. m_tnd.hWnd = pWnd->GetSafeHwnd();
  67. m_tnd.uID = uID;
  68. m_tnd.hIcon = icon;
  69. m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  70. m_tnd.uCallbackMessage = uCallbackMessage;
  71. lstrcpy (m_tnd.szTip, szToolTip);
  72. // Set the tray icon
  73. //
  74. (m_bEnabled = Shell_NotifyIcon(NIM_ADD, &m_tnd));
  75. return m_bEnabled;
  76. }
  77. CTrayIcon::~CTrayIcon()
  78. {
  79. RemoveIcon();
  80. }
  81. /////////////////////////////////////////////////////////////////////////////
  82. // CTrayIcon icon manipulation
  83. void CTrayIcon::MoveToRight()
  84. {
  85. HideIcon();
  86. ShowIcon();
  87. }
  88. void CTrayIcon::RemoveIcon()
  89. {
  90. if (!m_bEnabled) return;
  91. m_tnd.uFlags = 0;
  92. Shell_NotifyIcon(NIM_DELETE, &m_tnd);
  93. m_bEnabled = FALSE;
  94. }
  95. void CTrayIcon::HideIcon()
  96. {
  97. if (m_bEnabled && !m_bHidden) {
  98. m_tnd.uFlags = NIF_ICON;
  99. Shell_NotifyIcon (NIM_DELETE, &m_tnd);
  100. m_bHidden = TRUE;
  101. }
  102. }
  103. void CTrayIcon::ShowIcon()
  104. {
  105. if (m_bEnabled && m_bHidden) {
  106. m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  107. Shell_NotifyIcon(NIM_ADD, &m_tnd);
  108. m_bHidden = FALSE;
  109. }
  110. }
  111. BOOL CTrayIcon::SetIcon(HICON hIcon)
  112. {
  113. if (!m_bEnabled) return FALSE;
  114. m_tnd.uFlags = NIF_ICON;
  115. m_tnd.hIcon = hIcon;
  116. return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
  117. }
  118. BOOL CTrayIcon::SetIcon(LPCTSTR lpszIconName)
  119. {
  120. HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);
  121. return SetIcon(hIcon);
  122. }
  123. BOOL CTrayIcon::SetIcon(UINT nIDResource)
  124. {
  125. HICON hIcon = AfxGetApp()->LoadIcon(nIDResource);
  126. return SetIcon(hIcon);
  127. }
  128. BOOL CTrayIcon::SetStandardIcon(LPCTSTR lpIconName)
  129. {
  130. HICON hIcon = LoadIcon(NULL, lpIconName);
  131. return SetIcon(hIcon);
  132. }
  133. BOOL CTrayIcon::SetStandardIcon(UINT nIDResource)
  134. {
  135. HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(nIDResource));
  136. return SetIcon(hIcon);
  137. }
  138. HICON CTrayIcon::GetIcon() const
  139. {
  140. HICON hIcon = NULL;
  141. if (m_bEnabled)
  142. hIcon = m_tnd.hIcon;
  143. return hIcon;
  144. }
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CTrayIcon tooltip text manipulation
  147. BOOL CTrayIcon::SetTooltipText(LPCTSTR pszTip)
  148. {
  149. if (!m_bEnabled) return FALSE;
  150. m_tnd.uFlags = NIF_TIP;
  151. _tcscpy(m_tnd.szTip, pszTip);
  152. return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
  153. }
  154. BOOL CTrayIcon::SetTooltipText(UINT nID)
  155. {
  156. CString strText;
  157. VERIFY(strText.LoadString(nID));
  158. return SetTooltipText(strText);
  159. }
  160. CString CTrayIcon::GetTooltipText() const
  161. {
  162. CString strText;
  163. if (m_bEnabled)
  164. strText = m_tnd.szTip;
  165. return strText;
  166. }
  167. /////////////////////////////////////////////////////////////////////////////
  168. // CTrayIcon notification window stuff
  169. BOOL CTrayIcon::SetNotificationWnd(CWnd* pWnd)
  170. {
  171. if (!m_bEnabled) return FALSE;
  172. //Make sure Notification window is valid
  173. ASSERT(pWnd && ::IsWindow(pWnd->GetSafeHwnd()));
  174. m_tnd.hWnd = pWnd->GetSafeHwnd();
  175. m_tnd.uFlags = 0;
  176. return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
  177. }
  178. CWnd* CTrayIcon::GetNotificationWnd() const
  179. {
  180. return CWnd::FromHandle(m_tnd.hWnd);
  181. }
  182. /////////////////////////////////////////////////////////////////////////////
  183. // CTrayIcon implentation of OnTrayNotification
  184. LRESULT CTrayIcon::OnTrayNotification(UINT wParam, LONG lParam)
  185. {
  186. //Return quickly if its not for this tray icon
  187. if (wParam != m_tnd.uID)
  188. return 0L;
  189. CMenu menu, *pSubMenu;
  190. // Clicking with right button brings up a context menu
  191. if (LOWORD(lParam) == WM_RBUTTONUP)
  192. {
  193. if (!menu.LoadMenu(m_tnd.uID)) return 0;
  194. if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
  195. // Make first menu item the default (bold font)
  196. ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
  197. //Display and track the popup menu
  198. CPoint pos;
  199. GetCursorPos(&pos);
  200. ::SetForegroundWindow(m_tnd.hWnd);
  201. ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0, m_tnd.hWnd, NULL);
  202. //pSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pos.x, pos.y, this, NULL);
  203. menu.DestroyMenu();
  204. }
  205. /* else if (LOWORD(lParam) == WM_LBUTTONDBLCLK || LOWORD(lParam) == WM_LBUTTONDOWN)
  206. {
  207. if (!menu.LoadMenu(m_tnd.uID)) return 0;
  208. if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
  209. // double click received, the default action is to execute first menu item
  210. ::SetForegroundWindow(m_tnd.hWnd);
  211. ::SendMessage(m_tnd.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0);
  212. menu.DestroyMenu();
  213. }*/
  214. return 1;
  215. }