Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

363 lines
8.7 KiB

  1. // Tray.cpp
  2. #include "pch.h"
  3. #include "tray.h"
  4. #define LEFT_MENU (0)
  5. #define RIGHT_MENU (1)
  6. /////////////////////////////////////////////////////////////////////////////
  7. CTrayIcon::CTrayIcon(HWND hWnd, HICON hIcon, LPCTSTR pszText, UINT uID) :
  8. m_iDefaultCmd(-1)
  9. {
  10. TRACEPROC("CTrayIcon::CTrayIcon", 2)
  11. TRACEENTER(("(hwnd=%x,hIcon=%x,Text=%s,ID=%x)\n",
  12. hWnd, hIcon, pszText, uID));
  13. m_hMenu[LEFT_MENU] = m_hSubMenu[LEFT_MENU] = 0;
  14. m_hMenu[RIGHT_MENU] = m_hSubMenu[RIGHT_MENU] = 0;
  15. m_msgTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated"));
  16. memset(&m_nid, 0, sizeof(m_nid));
  17. m_nid.cbSize = sizeof(NOTIFYICONDATA);
  18. m_nid.hWnd = hWnd;
  19. m_nid.uID = uID;
  20. m_nid.uFlags = NIF_MESSAGE;
  21. m_nid.uCallbackMessage = RegisterWindowMessage(TEXT("{D0061156-D460-4230-AF87-9E7658AB987D}"));
  22. if (hIcon)
  23. {
  24. m_nid.uFlags |= NIF_ICON;
  25. m_nid.hIcon = hIcon;
  26. }
  27. if (pszText)
  28. {
  29. m_nid.uFlags |= NIF_TIP;
  30. lstrcpyn(m_nid.szTip, pszText, sizeof(m_nid.szTip));
  31. }
  32. if (!Shell_NotifyIcon(NIM_ADD, &m_nid))
  33. {
  34. TABSRVERR(("CTrayIcon::CTrayIcon: Shell_NotifyIcon failed (err=%d)\n",
  35. GetLastError()));
  36. }
  37. TRACEEXIT(("!\n"));
  38. return;
  39. }
  40. /////////////////////////////////////////////////////////////////////////////
  41. void CTrayIcon::Delete()
  42. {
  43. TRACEPROC("CTrayIcon::Delete", 2)
  44. TRACEENTER(("()\n"));
  45. if (m_nid.uFlags & NIF_ICON)
  46. {
  47. m_nid.uFlags = NIF_ICON;
  48. if (!Shell_NotifyIcon(NIM_DELETE, &m_nid))
  49. SetLastError(::GetLastError());
  50. m_nid.uFlags = 0;
  51. // Cleanup the icon...
  52. if (m_nid.hIcon)
  53. {
  54. DestroyIcon(m_nid.hIcon);
  55. m_nid.hIcon = 0;
  56. }
  57. // ...and the menus
  58. HMENU hmLeft = m_hMenu[LEFT_MENU];
  59. if (m_hMenu[LEFT_MENU])
  60. {
  61. DestroyMenu(m_hMenu[LEFT_MENU]);
  62. m_hMenu[LEFT_MENU] = m_hSubMenu[LEFT_MENU] = 0;
  63. }
  64. // watch for right & left menus being the same
  65. if (m_hMenu[RIGHT_MENU] && m_hMenu[RIGHT_MENU] != hmLeft)
  66. {
  67. DestroyMenu(m_hMenu[RIGHT_MENU]);
  68. m_hMenu[RIGHT_MENU] = m_hSubMenu[RIGHT_MENU] = 0;
  69. }
  70. }
  71. TRACEEXIT(("!\n"));
  72. return;
  73. }
  74. #if 0
  75. /////////////////////////////////////////////////////////////////////////////
  76. HICON CTrayIcon::SetIcon(HICON hIcon)
  77. {
  78. TRACEPROC("CTrayIcon::SetIcon", 2)
  79. HICON hOldIcon = m_nid.hIcon;
  80. TRACEENTER(("(hIcon=%x)\n", hIcon));
  81. if (hIcon)
  82. {
  83. m_nid.hIcon = hIcon;
  84. m_nid.uFlags |= NIF_ICON;
  85. if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
  86. SetLastError(::GetLastError());
  87. }
  88. else
  89. {
  90. Delete();
  91. }
  92. TRACEEXIT(("=%x\n", hOldIcon));
  93. return hOldIcon;
  94. }
  95. /////////////////////////////////////////////////////////////////////////////
  96. void CTrayIcon::SetText(LPCTSTR pszText)
  97. {
  98. TRACEPROC("CTrayIcon::SetText", 2)
  99. TRACEENTER(("(Text=%s)\n", pszText));
  100. if (pszText)
  101. {
  102. m_nid.uFlags |= NIF_TIP;
  103. lstrcpyn(m_nid.szTip, pszText, sizeof(m_nid.szTip));
  104. if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
  105. SetLastError(::GetLastError());
  106. }
  107. TRACEEXIT(("!\n"));
  108. return;
  109. }
  110. #endif
  111. /////////////////////////////////////////////////////////////////////////////
  112. void CTrayIcon::BalloonToolTip(
  113. LPCTSTR pszTitle,
  114. LPCTSTR pszText,
  115. UINT uTimeout,
  116. DWORD dwFlags)
  117. {
  118. TRACEPROC("CTrayIcon::BalloonToolTip", 2)
  119. UINT uFlags = m_nid.uFlags;
  120. TRACEENTER(("(Title=%s,Text=%s,Timeout=%d,Flags=%x)\n",
  121. pszTitle, pszText, uTimeout, dwFlags));
  122. m_nid.uFlags = NIF_INFO;
  123. m_nid.uTimeout = uTimeout;
  124. lstrcpyn(m_nid.szInfo, pszText, ARRAYSIZE(m_nid.szInfo));
  125. lstrcpyn(m_nid.szInfoTitle, pszTitle, ARRAYSIZE(m_nid.szInfoTitle));
  126. m_nid.dwInfoFlags = dwFlags;
  127. if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
  128. {
  129. TABSRVERR(("CTrayIcon::BalloonToolTip: Shell_NotifyIcon failed (err=%d)\n",
  130. GetLastError()));
  131. }
  132. m_nid.uFlags = uFlags;
  133. TRACEEXIT(("!\n"));
  134. return;
  135. }
  136. /////////////////////////////////////////////////////////////////////////////
  137. #if 0
  138. static VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  139. {
  140. TRACEPROC("TimerProc", 5)
  141. TRACEENTER(("(hwnd=%x,Msg=%s,EventId=%x,Time=%x)\n",
  142. hWnd, LookupName(uMsg, WMMsgNames), idEvent, dwTime));
  143. KillTimer(hWnd, idEvent);
  144. CTrayIcon* This = reinterpret_cast<CTrayIcon*>(idEvent);
  145. if (This->m_hSubMenu[LEFT_MENU])
  146. This->DoMenu(This->m_hSubMenu[LEFT_MENU]);
  147. TRACEEXIT(("!\n"));
  148. return;
  149. }
  150. #endif
  151. /////////////////////////////////////////////////////////////////////////////
  152. BOOL CTrayIcon::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  153. LRESULT& lResult)
  154. {
  155. TRACEPROC("CTrayIcon::WndProc", 5)
  156. BOOL rc = FALSE;
  157. TRACEENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
  158. hWnd, LookupName(uMsg, WMMsgNames), wParam, lParam));
  159. if (uMsg == m_msgTaskbarCreated)
  160. {
  161. lResult = OnTaskbarCreated();
  162. rc = TRUE;
  163. }
  164. else if (uMsg == m_nid.uCallbackMessage)
  165. {
  166. lResult = OnNotify(lParam);
  167. rc = TRUE;
  168. }
  169. else if (uMsg == WM_DESTROY)
  170. {
  171. // Our controlling window is being destroyed. Clean up if we
  172. // haven't already, then pass on the WM_DESTROY
  173. Delete();
  174. }
  175. TRACEEXIT(("=%x\n", rc));
  176. return rc;
  177. }
  178. /////////////////////////////////////////////////////////////////////////////
  179. LRESULT CTrayIcon::OnNotify(LPARAM lParam)
  180. {
  181. TRACEPROC("CTrayIcon::OnNotify", 2)
  182. TRACEENTER(("(lParam=%x)\n", lParam));
  183. switch (lParam)
  184. {
  185. case WM_LBUTTONUP:
  186. if (m_iDefaultCmd != -1)
  187. PostMessage(m_nid.hWnd, WM_COMMAND, m_iDefaultCmd, 0);
  188. break;
  189. #if 0
  190. case WM_LBUTTONDOWN:
  191. SetTimer(m_nid.hWnd, (UINT_PTR)this, GetDoubleClickTime(), TimerProc);
  192. break;
  193. case WM_LBUTTONDBLCLK:
  194. KillTimer(m_nid.hWnd, (UINT_PTR)this);
  195. if (m_iDefaultCmd != -1)
  196. PostMessage(m_nid.hWnd, WM_COMMAND, m_iDefaultCmd, 0);
  197. break;
  198. #endif
  199. case WM_RBUTTONUP:
  200. if (m_hSubMenu[RIGHT_MENU])
  201. DoMenu(m_hSubMenu[RIGHT_MENU]);
  202. break;
  203. }
  204. TRACEEXIT(("=0\n"));
  205. return 0;
  206. }
  207. /////////////////////////////////////////////////////////////////////////////
  208. LRESULT CTrayIcon::OnTaskbarCreated()
  209. {
  210. TRACEPROC("CTrayIcon::OnTaskbarCreated", 2)
  211. TRACEENTER(("()\n"));
  212. if (m_nid.hWnd && m_nid.hIcon && (m_nid.uFlags & NIF_ICON))
  213. {
  214. if (!Shell_NotifyIcon(NIM_ADD, &m_nid))
  215. {
  216. TABSRVERR(("CTrayIcon::OnTaskbarCreated: Shell_NotifyIcon failed (err=%d)\n",
  217. GetLastError()));
  218. }
  219. }
  220. TRACEEXIT(("=0\n"));
  221. return 0;
  222. }
  223. /////////////////////////////////////////////////////////////////////////////
  224. HMENU CTrayIcon::SetSubMenu(BOOL fLeftMenu, HMENU hMenu, int nPos)
  225. {
  226. TRACEPROC("CTrayIcon::SetSubMenu", 2)
  227. int idx = (fLeftMenu) ? LEFT_MENU : RIGHT_MENU;
  228. HMENU hOldMenu = m_hMenu[idx];
  229. TRACEENTER(("(fLeftMenu=%d,hMenu=%x,Pos=%d)\n", fLeftMenu, hMenu, nPos));
  230. m_hMenu[idx] = m_hSubMenu[idx] = hMenu;
  231. if (hMenu && nPos >= 0)
  232. {
  233. m_hSubMenu[idx] = GetSubMenu(hMenu, nPos); //NO TYPO
  234. }
  235. if (idx == LEFT_MENU)
  236. {
  237. m_iDefaultCmd = -1;
  238. if (hMenu && m_hSubMenu[idx])
  239. m_iDefaultCmd = GetMenuDefaultItem(m_hSubMenu[idx], FALSE, 0);
  240. }
  241. TRACEEXIT(("=%x\n", hOldMenu));
  242. return hOldMenu;
  243. }
  244. /////////////////////////////////////////////////////////////////////////////
  245. void CTrayIcon::DoMenu(HMENU hMenu)
  246. {
  247. TRACEPROC("CTrayIcon::DoMenu", 2)
  248. POINT pt;
  249. UINT iCmd;
  250. TCHAR tszMenuText[128];
  251. TRACEENTER(("(hMenu=%x)\n", hMenu));
  252. GetCursorPos(&pt);
  253. SetForegroundWindow(m_nid.hWnd); // necessary?
  254. LoadString(ghMod,
  255. gdwfTabSrv & TSF_SUPERTIP_OPENED?
  256. IDS_HIDE_SUPERTIP: IDS_SHOW_SUPERTIP,
  257. tszMenuText,
  258. ARRAYSIZE(tszMenuText));
  259. ModifyMenu(hMenu,
  260. IDM_OPEN,
  261. MF_BYCOMMAND | MF_STRING,
  262. IDM_OPEN,
  263. tszMenuText);
  264. LoadString(ghMod,
  265. gdwfTabSrv & TSF_PORTRAIT_MODE?
  266. IDS_SCREEN_LANDSCAPE: IDS_SCREEN_PORTRAIT,
  267. tszMenuText,
  268. ARRAYSIZE(tszMenuText));
  269. ModifyMenu(hMenu,
  270. IDM_TOGGLE_ROTATION,
  271. MF_BYCOMMAND | MF_STRING,
  272. IDM_TOGGLE_ROTATION,
  273. tszMenuText);
  274. iCmd = TrackPopupMenu(hMenu, /* TPM_RETURNCMD | */ TPM_NONOTIFY | TPM_RIGHTBUTTON,
  275. pt.x, pt.y, 0, m_nid.hWnd, NULL);
  276. PostMessage(m_nid.hWnd, WM_NULL, 0, 0); // MS doucmented work-around for taskbar menu
  277. // problem with TrackPopupMenu - still needed?
  278. //PostMessage(m_nid.hWnd, WM_COMMAND, iCmd, 0);
  279. TRACEEXIT(("!\n"));
  280. return;
  281. }