Leaked source code of windows server 2003
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.

400 lines
9.7 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: trayicon.cpp
  4. //
  5. // Module: CMMON32.EXE
  6. //
  7. // Synopsis: Implementation for the CTrayIcon class.
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation
  10. //
  11. // Author: quintinb Created Header 08/16/99
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. #include "resource.h"
  16. #include "TrayIcon.h"
  17. #include "Monitor.h"
  18. #include "cm_misc.h"
  19. #include "ShellDll.h"
  20. //+----------------------------------------------------------------------------
  21. //
  22. // Function: CTrayIcon::CTrayIcon
  23. //
  24. // Synopsis: Constructor
  25. //
  26. // Arguments: Nothing
  27. //
  28. // Returns: Nothing
  29. //
  30. // History: fengsun Created Header 2/17/98
  31. //
  32. //+----------------------------------------------------------------------------
  33. CTrayIcon::CTrayIcon()
  34. {
  35. m_hwnd = NULL;
  36. m_hMenu = m_hSubMenu = NULL;
  37. m_uID = 0;
  38. m_hIcon = NULL;
  39. }
  40. //+----------------------------------------------------------------------------
  41. //
  42. // Function: CTrayIcon::~CTrayIcon
  43. //
  44. // Synopsis: Destructor
  45. //
  46. // Arguments: None
  47. //
  48. // Returns: Nothing
  49. //
  50. // History: Created Header 4/7/98
  51. //
  52. //+----------------------------------------------------------------------------
  53. CTrayIcon::~CTrayIcon()
  54. {
  55. if (m_hMenu)
  56. {
  57. DestroyMenu(m_hMenu);
  58. }
  59. if (m_hIcon)
  60. {
  61. DeleteObject(m_hIcon);
  62. }
  63. for (int i=0; i< m_CommandArray.GetSize();i++)
  64. {
  65. CmFree((TCHAR*) m_CommandArray[i]);
  66. }
  67. }
  68. #if 0 // this function is not used
  69. /*
  70. //+----------------------------------------------------------------------------
  71. //
  72. // Function: CTrayIcon::SetTip
  73. //
  74. // Synopsis: Change the tip of the tray icon
  75. //
  76. // Arguments: const TCHAR* lpMsg - message to set
  77. //
  78. // Returns: Nothing
  79. //
  80. // History: fengsun Created Header 2/17/98
  81. //
  82. //+----------------------------------------------------------------------------
  83. void CTrayIcon::SetTip(const TCHAR* lpMsg)
  84. {
  85. MYDBGASSERT(IsWindow(m_hwnd));
  86. MYDBGASSERT(lpMsg);
  87. NOTIFYICONDATA nidData;
  88. ZeroMemory(&nidData,sizeof(nidData));
  89. nidData.cbSize = sizeof(nidData);
  90. nidData.hWnd = m_hwnd;
  91. nidData.uID = m_uID;
  92. nidData.uFlags = NIF_TIP;
  93. lstrcpyn(nidData.szTip,lpMsg,sizeof(nidData.szTip)/sizeof(TCHAR));
  94. //
  95. // Load Shell32.dll and call Shell_NotifyIcon
  96. //
  97. CShellDll ShellDll;
  98. BOOL bRes = ShellDll.NotifyIcon(NIM_MODIFY,&nidData);
  99. MYDBGASSERT(bRes);
  100. }
  101. */
  102. #endif
  103. //+----------------------------------------------------------------------------
  104. //
  105. // Function: CTrayIcon::SetIcon
  106. //
  107. // Synopsis: Set the icon for the tray icon
  108. //
  109. // Arguments: HICON hIcon - icon to set. Use NULL to use existing icon.
  110. // HWND hwnd - window to receive tray icon message
  111. // UINT uMsg - tray icon message
  112. // UINT uID - The id for the tray icon
  113. // const TCHAR* lpMsg - The initial tip for the icon
  114. //
  115. // Returns: Nothing
  116. //
  117. // History: fengsun Created Header 2/17/98
  118. //
  119. //+----------------------------------------------------------------------------
  120. void CTrayIcon::SetIcon(HICON hIcon, HWND hwnd, UINT uMsg, UINT uID, const TCHAR* lpMsg)
  121. {
  122. MYDBGASSERT(IsWindow(hwnd));
  123. //MYDBGASSERT(m_hIcon == NULL);
  124. //MYDBGASSERT(hIcon);
  125. MYDBGASSERT(m_hIcon == NULL && hIcon ||
  126. m_hIcon && hIcon == NULL);
  127. m_hwnd = hwnd;
  128. m_uID = uID;
  129. NOTIFYICONDATA nidData;
  130. ZeroMemory(&nidData,sizeof(nidData));
  131. nidData.cbSize = sizeof(nidData);
  132. nidData.hWnd = m_hwnd;
  133. nidData.uID = uID;
  134. nidData.uFlags = NIF_ICON | NIF_MESSAGE;
  135. //
  136. // we'll reuse the icon if we already have one.
  137. //
  138. if (!m_hIcon)
  139. {
  140. m_hIcon = hIcon;
  141. }
  142. nidData.hIcon = m_hIcon;
  143. nidData.uCallbackMessage = uMsg;
  144. if (lpMsg)
  145. {
  146. nidData.uFlags |= NIF_TIP;
  147. lstrcpynU(nidData.szTip,lpMsg,sizeof(nidData.szTip)/sizeof(TCHAR));
  148. }
  149. //
  150. // Load Shell32.dll and call Shell_NotifyIcon
  151. //
  152. CShellDll ShellDll;
  153. DWORD cRetries = 0;
  154. BOOL bRes = ShellDll.NotifyIcon(NIM_ADD,&nidData);
  155. //
  156. // Check if Icon is already added
  157. //
  158. if (bRes == FALSE)
  159. {
  160. bRes = ShellDll.NotifyIcon(NIM_MODIFY,&nidData);
  161. }
  162. //
  163. // If this fails its very likely that the tray is not started yet. Retry few times
  164. // with a max wait time of 5 mins & then abort
  165. //
  166. while (bRes == FALSE && cRetries < 300)
  167. {
  168. Sleep(1000);
  169. cRetries ++;
  170. // CMTRACE1(TEXT("Shell_NotifyIcon = %d"), bRes);
  171. bRes = ShellDll.NotifyIcon(NIM_ADD,&nidData);
  172. //
  173. // Check if Icon is already added
  174. //
  175. if (bRes == FALSE)
  176. {
  177. bRes = ShellDll.NotifyIcon(NIM_MODIFY,&nidData);
  178. }
  179. }
  180. MYDBGASSERT(bRes);
  181. }
  182. //+----------------------------------------------------------------------------
  183. //
  184. // Function: CTrayIcon::RemoveIcon
  185. //
  186. // Synopsis: remove icon from the tray
  187. //
  188. // Arguments: None
  189. //
  190. // Returns: Nothing
  191. //
  192. // History: fengsun Created Header 2/17/98
  193. //
  194. //+----------------------------------------------------------------------------
  195. void CTrayIcon::RemoveIcon()
  196. {
  197. if (m_hIcon)
  198. {
  199. NOTIFYICONDATA nidData;
  200. ZeroMemory(&nidData,sizeof(nidData));
  201. nidData.cbSize = sizeof(nidData);
  202. nidData.hWnd = m_hwnd;
  203. nidData.uID = m_uID;
  204. //
  205. // Load Shell32.dll and call Shell_NotifyIcon
  206. //
  207. CShellDll ShellDll;
  208. BOOL bRes = ShellDll.NotifyIcon(NIM_DELETE,&nidData);
  209. MYDBGASSERT(bRes);
  210. DeleteObject(m_hIcon);
  211. m_hIcon = NULL;
  212. }
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // class CMultipleString
  217. //
  218. // Description: A string taht have multiple sub strings.
  219. // The format is "stringA\0stringB\0...\0\0"
  220. //
  221. // History: fengsun Created 2/17/98
  222. //
  223. //----------------------------------------------------------------------------
  224. class CMultipleString
  225. {
  226. public:
  227. CMultipleString(const TCHAR* lpStrings) {m_lpStrings = lpStrings;}
  228. const TCHAR* GetNextString();
  229. protected:
  230. const TCHAR * m_lpStrings; // pointer to the string to be distracted
  231. };
  232. //+----------------------------------------------------------------------------
  233. //
  234. // Function: CMultipleString::GetNextString
  235. //
  236. // Synopsis: Get the next substring
  237. //
  238. // Arguments: None
  239. //
  240. // Returns: const TCHAR* - The next sub string or NULL
  241. //
  242. // History: fengsun Created Header 2/17/98
  243. //
  244. //+----------------------------------------------------------------------------
  245. const TCHAR* CMultipleString::GetNextString()
  246. {
  247. MYDBGASSERT(m_lpStrings);
  248. if (m_lpStrings[0] == TEXT('\0'))
  249. {
  250. //
  251. // Reach the end og the string
  252. //
  253. return NULL;
  254. }
  255. const TCHAR* lpReturn = m_lpStrings;
  256. //
  257. // Advance the pointer to the next string
  258. //
  259. m_lpStrings += lstrlenU(lpReturn)+1;
  260. return (lpReturn);
  261. }
  262. //+----------------------------------------------------------------------------
  263. //
  264. // Function: CTrayIcon::CreateMenu
  265. //
  266. // Synopsis: Create the menu for the tray icon
  267. //
  268. // Arguments: const CIni* pIniFile - The ini file which have a tray menu section
  269. // DWORD dwMsgBase - The starting message id for the additional
  270. // command in the tray menu
  271. //
  272. // Returns: Nothing
  273. //
  274. // History: Created Header 2/17/98
  275. //
  276. //+----------------------------------------------------------------------------
  277. void CTrayIcon::CreateMenu(const CIni* pIniFile, DWORD dwMsgBase)
  278. {
  279. MYDBGASSERT(pIniFile);
  280. //
  281. // The default tray menu is the sub-menu of IDM_TRAY in the resource
  282. //
  283. m_hMenu = LoadMenuU(CMonitor::GetInstance(), MAKEINTRESOURCE(IDM_TRAY));
  284. MYDBGASSERT(m_hMenu != NULL);
  285. m_hSubMenu = GetSubMenu(m_hMenu, 0);
  286. MYDBGASSERT(m_hSubMenu != NULL);
  287. //
  288. // lpMenuNames contains all the entry names under c_pszCmSectionMenuOptions
  289. //
  290. LPTSTR lpMenuNames = pIniFile->GPPS(c_pszCmSectionMenuOptions, (LPTSTR)NULL);
  291. if (lpMenuNames[0] == 0)
  292. {
  293. //
  294. // No additional menu item
  295. //
  296. CmFree(lpMenuNames);
  297. return;
  298. }
  299. int nMenuPos; // the position to insert menu;
  300. nMenuPos = GetMenuItemCount(m_hSubMenu);
  301. MYDBGASSERT(nMenuPos >= 0);
  302. //
  303. // Add seperator
  304. //
  305. MYVERIFY(FALSE != InsertMenuU(m_hSubMenu, nMenuPos, MF_BYPOSITION|MF_SEPARATOR, 0, 0));
  306. nMenuPos++;
  307. //
  308. // append menus
  309. //
  310. CMultipleString MultipleStr(lpMenuNames);
  311. while(TRUE)
  312. {
  313. const TCHAR* lpMenuName = MultipleStr.GetNextString();
  314. if (lpMenuName == NULL)
  315. {
  316. //
  317. // No more string
  318. //
  319. break;
  320. }
  321. LPTSTR lpCmdLine = pIniFile->GPPS(c_pszCmSectionMenuOptions,lpMenuName);
  322. MYDBGASSERT(lpCmdLine && lpCmdLine[0]);
  323. if (lpCmdLine[0] == 0)
  324. {
  325. //
  326. // Ignore menu without command line
  327. //
  328. CmFree(lpCmdLine);
  329. continue;
  330. }
  331. //
  332. // Add the command to the menu
  333. //
  334. MYVERIFY(FALSE != InsertMenuU(m_hSubMenu, nMenuPos, MF_BYPOSITION|MF_STRING,
  335. dwMsgBase + m_CommandArray.GetSize(), lpMenuName));
  336. nMenuPos++;
  337. //
  338. // Add the command to the command array
  339. //
  340. m_CommandArray.Add(lpCmdLine);
  341. }
  342. CmFree(lpMenuNames);
  343. }