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.

199 lines
5.4 KiB

  1. #include "tsvs.h"
  2. #define MSG_QUEUE_SIZE 5
  3. CRITICAL_SECTION g_CSTrayThread;
  4. DWORD g_idTrayThread;
  5. HANDLE g_hTrayThread = NULL;
  6. NOTIFYICONDATA NotifyIconData;
  7. HMENU hPopup;
  8. //////////////////////////////////////////////////////////////////////////////
  9. CTrayNotification * g_apQueue[MSG_QUEUE_SIZE] = { NULL };
  10. UINT g_cQueueSize = 0;
  11. const UINT idTrayIcons[] =
  12. {
  13. IDI_ICON1, IDI_ICON2, IDI_ICON3
  14. };
  15. HICON g_TrayIcons[ARRAYSIZE(idTrayIcons)];
  16. UINT g_cTrayIcons = ARRAYSIZE(idTrayIcons);
  17. //////////////////////////////////////////////////////////////////////////////
  18. BOOL DeliverTrayNotification(CTrayNotification * pNot)
  19. {
  20. EnterCriticalSection(&g_CSTrayThread);
  21. // If no worker thread is running, or queue is full, fail
  22. if (0 == g_idTrayThread || g_cQueueSize == MSG_QUEUE_SIZE)
  23. {
  24. LeaveCriticalSection(&g_CSTrayThread);
  25. return FALSE;
  26. }
  27. // Add notification to the queue and post a message to the
  28. // worker thread
  29. g_apQueue[g_cQueueSize++] = pNot;
  30. PostThreadMessage(g_idTrayThread, PM_NOTIFYWAITING, 0, 0);
  31. LeaveCriticalSection(&g_CSTrayThread);
  32. return TRUE;
  33. }
  34. //////////////////////////////////////////////////////////////////////////////
  35. DWORD TrayThreadMessageLoop(LPVOID)
  36. {
  37. MSG msg;
  38. while(GetMessage(&msg, NULL, 0, 0))
  39. {
  40. switch(msg.message)
  41. {
  42. case PM_NOTIFYWAITING:
  43. {
  44. // Take a message out of the queue
  45. EnterCriticalSection(&g_CSTrayThread);
  46. CTrayNotification * pNot = g_apQueue[0];
  47. for (UINT i = 0; i < g_cQueueSize; i++)
  48. {
  49. g_apQueue[i] = g_apQueue[i+1];
  50. }
  51. g_cQueueSize--;
  52. LeaveCriticalSection(&g_CSTrayThread);
  53. // Give it to the tray to process.
  54. Tray_NotifyIcon(pNot->m_hWnd,
  55. pNot->m_uCallbackMessage,
  56. pNot->m_Message,
  57. pNot->m_hIcon,
  58. pNot->m_szTip);
  59. delete pNot;
  60. break;
  61. }
  62. case PM_QUITTRAYTHREAD:
  63. {
  64. // Delete all messages pending
  65. EnterCriticalSection(&g_CSTrayThread);
  66. while (g_cQueueSize)
  67. {
  68. delete g_apQueue[g_cQueueSize - 1];
  69. g_cQueueSize--;
  70. }
  71. g_idTrayThread = 0;
  72. LeaveCriticalSection(&g_CSTrayThread);
  73. DeleteCriticalSection(&g_CSTrayThread);
  74. ExitThread(0); // chris
  75. //PostQuitMessage(0);
  76. break;
  77. }
  78. default:
  79. {
  80. break;
  81. }
  82. }
  83. }
  84. return 0;
  85. }
  86. //////////////////////////////////////////////////////////////////////////////
  87. void Tray_NotifyIcon(HWND hWnd,
  88. UINT uCallbackMessage,
  89. DWORD Message,
  90. HICON hIcon,
  91. LPCTSTR lpTip)
  92. {
  93. NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  94. NotifyIconData.uID = uCallbackMessage;
  95. NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  96. NotifyIconData.uCallbackMessage = uCallbackMessage;
  97. NotifyIconData.hWnd = hWnd;
  98. NotifyIconData.hIcon = hIcon;
  99. if (lpTip)
  100. {
  101. lstrcpyn(NotifyIconData.szTip, lpTip,
  102. ARRAYSIZE(NotifyIconData.szTip));
  103. }
  104. else
  105. {
  106. NotifyIconData.szTip[0] = 0;
  107. }
  108. Shell_NotifyIcon(Message, &NotifyIconData);
  109. }
  110. //////////////////////////////////////////////////////////////////////////////
  111. void Tray_Notify(HWND hWnd, WPARAM wParam, LPARAM lParam)
  112. {
  113. switch (lParam)
  114. {
  115. case WM_LBUTTONDBLCLK:
  116. ShowRunningInstance();
  117. break;
  118. case WM_RBUTTONDOWN:
  119. {
  120. //HMENU hPopup = LoadPopupMenu(hInst, IDR_TRAYMENU);
  121. hPopup = LoadPopupMenu(hInst, IDR_TRAYMENU);
  122. // Display the tray icons context menu at
  123. // the current cursor location
  124. if (hPopup)
  125. {
  126. POINT pt;
  127. GetCursorPos(&pt);
  128. SetForegroundWindow(hWnd);
  129. TrackPopupMenuEx(hPopup, 0, pt.x, pt.y, hWnd, NULL);
  130. DestroyMenu(hPopup);
  131. }
  132. break;
  133. }
  134. }
  135. }
  136. //////////////////////////////////////////////////////////////////////////////
  137. void ShowRunningInstance()
  138. {
  139. OpenIcon(hWnd);
  140. SetForegroundWindow(hWnd);
  141. SetWindowPos(hWnd, HWND_NOTOPMOST,
  142. 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
  143. }
  144. //////////////////////////////////////////////////////////////////////////////
  145. //////////////////////////////////////////////////////////////////////////////
  146. HMENU LoadPopupMenu(HINSTANCE hinst, UINT id)
  147. {
  148. HMENU hmenuParent = LoadMenu(hinst, MAKEINTRESOURCE(id));
  149. if (hmenuParent)
  150. {
  151. HMENU hpopup = GetSubMenu(hmenuParent, 0);
  152. RemoveMenu(hmenuParent, 0, MF_BYPOSITION);
  153. DestroyMenu(hmenuParent);
  154. return hpopup;
  155. }
  156. return NULL;
  157. }