trayicon.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 8k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //+-------------------------------------------------------------------------
  2. //
  3. //  TaskMan - NT TaskManager
  4. //  Copyright (C) Microsoft
  5. //
  6. //  File:       trayicon.CPP
  7. //
  8. //  History:    Jan-27-96   DavePl  Created
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "precomp.h"
  12. // Queue for messages to be processed by the worker thread
  13. #define MSG_QUEUE_SIZE 5
  14. CTrayNotification * g_apQueue[MSG_QUEUE_SIZE] = { NULL };
  15. CRITICAL_SECTION    g_CSTrayThread;
  16. UINT                g_cQueueSize              = 0;
  17. /*++ DeliverTrayNotification (MAIN THREAD CODE)
  18. Routine Description:
  19.    Adds a tray notification block to the list of things to be done
  20.    by the tray notify worker thread
  21.     
  22. Arguments:
  23.     pNot                - The CTrayNotification object to be queued
  24. Returns:
  25.     
  26.     TRUE                - Message added to queue
  27.     FALSE               - Queue full
  28. Revision History:
  29.     Mar-27-95 Davepl  Created
  30.     May-28-99 Jonburs Don't ignore NIM_DELETE when queue is full
  31. */
  32. BOOL DeliverTrayNotification(CTrayNotification * pNot)
  33. {
  34.     EnterCriticalSection(&g_CSTrayThread);
  35.     // If no worker thread is running fail
  36.     
  37.     if (0 == g_idTrayThread)
  38.     {
  39.         LeaveCriticalSection(&g_CSTrayThread);
  40.         return FALSE;
  41.     }
  42.     // If the queue is full, fail unless the new notification
  43.     // is NIM_DELETE
  44.     if (MSG_QUEUE_SIZE == g_cQueueSize)
  45.     {
  46.         if (NIM_DELETE != pNot->m_Message)
  47.         {
  48.             LeaveCriticalSection(&g_CSTrayThread);
  49.             return FALSE;
  50.         }
  51.         else
  52.         {
  53.             // Replace last entry on the queue.  Do NOT post.
  54.             delete g_apQueue[g_cQueueSize - 1];
  55.             g_apQueue[g_cQueueSize - 1] = pNot;
  56.             LeaveCriticalSection(&g_CSTrayThread);
  57.             return TRUE;
  58.         }
  59.     }
  60.     // Add notification to the queue and post a message to the
  61.     // worker thread
  62.     g_apQueue[g_cQueueSize++] = pNot;
  63.     PostThreadMessage(g_idTrayThread, PM_NOTIFYWAITING, 0, 0);
  64.     
  65.     LeaveCriticalSection(&g_CSTrayThread);
  66.     return TRUE;
  67. }
  68. /*++ TrayThreadMessageLoop (WORKER THREAD CODE)
  69. Routine Description:
  70.    Waits for messages telling it a notification packet is ready
  71.    in the queue, then dispatches it to the tray  
  72.     
  73.    Mar-27-95 Davepl  Created
  74.    May-28-99 Jonburs Check for NIM_DELETE during PM_QUITTRAYTHREAD
  75. --*/
  76. DWORD TrayThreadMessageLoop(LPVOID)
  77. {
  78.     MSG msg;
  79.     while(GetMessage(&msg, NULL, 0, 0))
  80.     {
  81.         switch(msg.message)
  82.         {
  83.             case PM_NOTIFYWAITING:
  84.             {
  85.                 // Take a message out of the queue
  86.                 EnterCriticalSection(&g_CSTrayThread);
  87.         
  88.                 ASSERT(g_cQueueSize);
  89.                 CTrayNotification * pNot = g_apQueue[0];
  90.                 for (UINT i = 0; i < g_cQueueSize; i++)
  91.                 {
  92.                     g_apQueue[i] = g_apQueue[i+1];
  93.                 }
  94.                 g_cQueueSize--;
  95.                 LeaveCriticalSection(&g_CSTrayThread);
  96.                 // Give it to the tray to process.  If it blocks, our queue
  97.                 // will fill, but taskman itself won't hang
  98.                 Tray_NotifyIcon(pNot->m_hWnd,
  99.                                 pNot->m_uCallbackMessage,
  100.                                 pNot->m_Message,
  101.                                 pNot->m_hIcon,            
  102.                                 pNot->m_szTip);
  103.                 delete pNot;
  104.                 break;
  105.             }
  106.             case PM_QUITTRAYTHREAD:
  107.             {
  108.                 // Delete all messages pending
  109.                 EnterCriticalSection(&g_CSTrayThread);                
  110.                 while (g_cQueueSize)
  111.                 {
  112.                     // Need to check if a delete notification was on
  113.                     // the queue to ensure that our icon gets removed
  114.                     CTrayNotification * pNot = g_apQueue[g_cQueueSize - 1];
  115.                     if (NIM_DELETE == pNot->m_Message)
  116.                     {
  117.                         Tray_NotifyIcon(pNot->m_hWnd,
  118.                                         pNot->m_uCallbackMessage,
  119.                                         pNot->m_Message,
  120.                                         pNot->m_hIcon,            
  121.                                         pNot->m_szTip);
  122.                     }
  123.                     delete pNot;
  124.                     g_cQueueSize--;
  125.                 }
  126.                 g_idTrayThread = 0;
  127.                 LeaveCriticalSection(&g_CSTrayThread);
  128.                 DeleteCriticalSection(&g_CSTrayThread);
  129.                 PostQuitMessage(0);
  130.                 break;
  131.             }
  132.             default:
  133.             {
  134.                 ASSERT(0 && "Taskman tray worker got unexpected message");
  135.                 break;
  136.             }
  137.         }
  138.     }
  139.     
  140.     return 0;
  141. }
  142. /*++ Tray_NotifyIcon (WORKER THREAD CODE)
  143. Routine Description:
  144.    Handles adding, updating, etc., of icon on the tray
  145.     
  146. Arguments:
  147.     hWnd                - icon owner
  148.     uCallbackMessage    - message ID to be used for callback
  149.     Message             - argument to Shell_NotifyIcon (NIM_ADD, NIM_DELETE, etc)
  150.     hIcon               - Handle to the icon
  151.     lpTip               - tooltip text for the icon
  152. Revision History:
  153.     Jan-27-95 Davepl  Created
  154. --*/
  155. void Tray_NotifyIcon(HWND    hWnd,
  156.                      UINT    uCallbackMessage,
  157.                      DWORD   Message,
  158.                      HICON   hIcon,            
  159.                      LPCTSTR lpTip)
  160. {
  161.     NOTIFYICONDATA NotifyIconData;
  162.     NotifyIconData.cbSize           = sizeof(NOTIFYICONDATA);
  163.     NotifyIconData.uID              = uCallbackMessage;
  164.     NotifyIconData.uFlags           = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  165.     NotifyIconData.uCallbackMessage = uCallbackMessage;
  166.     NotifyIconData.hWnd = hWnd;
  167.     NotifyIconData.hIcon = hIcon;
  168.     if (lpTip) 
  169.     {
  170.         lstrcpyn(NotifyIconData.szTip, lpTip, ARRAYSIZE(NotifyIconData.szTip));
  171.     } 
  172.     else 
  173.     {
  174.         NotifyIconData.szTip[0] = 0;
  175.     }
  176.     Shell_NotifyIcon(Message, &NotifyIconData);
  177. }
  178. /*++ Tray_Notify (MAIN THREAD CODE)
  179. Routine Description:
  180.    Handles notifications sent by the tray
  181.     
  182. Revision History:
  183.     Jan-27-95 Davepl  Created
  184. --*/
  185. void Tray_Notify(HWND hWnd, WPARAM wParam, LPARAM lParam)                     
  186. {                                                                              
  187.     switch (lParam) 
  188.     {
  189.         case WM_LBUTTONDBLCLK:                                                 
  190.             ShowRunningInstance();
  191.             break;                                                             
  192.         case WM_RBUTTONDOWN:
  193.         {
  194.             HMENU hPopup = LoadPopupMenu(g_hInstance, IDR_TRAYMENU);
  195.             // Display the tray icons context menu at the current cursor location
  196.                         
  197.             if (hPopup)
  198.             {
  199.                 POINT pt;
  200.                 GetCursorPos(&pt);
  201.                 if (IsWindowVisible(g_hMainWnd))
  202.                 {
  203.                     DeleteMenu(hPopup, IDM_RESTORETASKMAN, MF_BYCOMMAND);
  204.                 }
  205.                 else
  206.                 {
  207.                     SetMenuDefaultItem(hPopup, IDM_RESTORETASKMAN, FALSE);
  208.                 }
  209.                 CheckMenuItem(hPopup, IDM_ALWAYSONTOP,   
  210.                     MF_BYCOMMAND | (g_Options.m_fAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
  211.                 SetForegroundWindow(hWnd);
  212.                 g_fInPopup = TRUE;
  213.                 TrackPopupMenuEx(hPopup, 0, pt.x, pt.y, hWnd, NULL);
  214.                 g_fInPopup = FALSE;
  215.                 DestroyMenu(hPopup);
  216.             }
  217.             break;
  218.         }
  219.     }                                                                          
  220. }