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

#include "tsvs.h"
#define MSG_QUEUE_SIZE 5
CRITICAL_SECTION g_CSTrayThread;
DWORD g_idTrayThread;
HANDLE g_hTrayThread = NULL;
NOTIFYICONDATA NotifyIconData;
HMENU hPopup;
//////////////////////////////////////////////////////////////////////////////
CTrayNotification * g_apQueue[MSG_QUEUE_SIZE] = { NULL };
UINT g_cQueueSize = 0;
const UINT idTrayIcons[] =
{
IDI_ICON1, IDI_ICON2, IDI_ICON3
};
HICON g_TrayIcons[ARRAYSIZE(idTrayIcons)];
UINT g_cTrayIcons = ARRAYSIZE(idTrayIcons);
//////////////////////////////////////////////////////////////////////////////
BOOL DeliverTrayNotification(CTrayNotification * pNot)
{
EnterCriticalSection(&g_CSTrayThread);
// If no worker thread is running, or queue is full, fail
if (0 == g_idTrayThread || g_cQueueSize == MSG_QUEUE_SIZE)
{
LeaveCriticalSection(&g_CSTrayThread);
return FALSE;
}
// Add notification to the queue and post a message to the
// worker thread
g_apQueue[g_cQueueSize++] = pNot;
PostThreadMessage(g_idTrayThread, PM_NOTIFYWAITING, 0, 0);
LeaveCriticalSection(&g_CSTrayThread);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
DWORD TrayThreadMessageLoop(LPVOID)
{
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
switch(msg.message)
{
case PM_NOTIFYWAITING:
{
// Take a message out of the queue
EnterCriticalSection(&g_CSTrayThread);
CTrayNotification * pNot = g_apQueue[0];
for (UINT i = 0; i < g_cQueueSize; i++)
{
g_apQueue[i] = g_apQueue[i+1];
}
g_cQueueSize--;
LeaveCriticalSection(&g_CSTrayThread);
// Give it to the tray to process.
Tray_NotifyIcon(pNot->m_hWnd,
pNot->m_uCallbackMessage,
pNot->m_Message,
pNot->m_hIcon,
pNot->m_szTip);
delete pNot;
break;
}
case PM_QUITTRAYTHREAD:
{
// Delete all messages pending
EnterCriticalSection(&g_CSTrayThread);
while (g_cQueueSize)
{
delete g_apQueue[g_cQueueSize - 1];
g_cQueueSize--;
}
g_idTrayThread = 0;
LeaveCriticalSection(&g_CSTrayThread);
DeleteCriticalSection(&g_CSTrayThread);
ExitThread(0); // chris
//PostQuitMessage(0);
break;
}
default:
{
break;
}
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
void Tray_NotifyIcon(HWND hWnd,
UINT uCallbackMessage,
DWORD Message,
HICON hIcon,
LPCTSTR lpTip)
{
NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
NotifyIconData.uID = uCallbackMessage;
NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
NotifyIconData.uCallbackMessage = uCallbackMessage;
NotifyIconData.hWnd = hWnd;
NotifyIconData.hIcon = hIcon;
if (lpTip)
{
lstrcpyn(NotifyIconData.szTip, lpTip,
ARRAYSIZE(NotifyIconData.szTip));
}
else
{
NotifyIconData.szTip[0] = 0;
}
Shell_NotifyIcon(Message, &NotifyIconData);
}
//////////////////////////////////////////////////////////////////////////////
void Tray_Notify(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_LBUTTONDBLCLK:
ShowRunningInstance();
break;
case WM_RBUTTONDOWN:
{
//HMENU hPopup = LoadPopupMenu(hInst, IDR_TRAYMENU);
hPopup = LoadPopupMenu(hInst, IDR_TRAYMENU);
// Display the tray icons context menu at
// the current cursor location
if (hPopup)
{
POINT pt;
GetCursorPos(&pt);
SetForegroundWindow(hWnd);
TrackPopupMenuEx(hPopup, 0, pt.x, pt.y, hWnd, NULL);
DestroyMenu(hPopup);
}
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////
void ShowRunningInstance()
{
OpenIcon(hWnd);
SetForegroundWindow(hWnd);
SetWindowPos(hWnd, HWND_NOTOPMOST,
0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
HMENU LoadPopupMenu(HINSTANCE hinst, UINT id)
{
HMENU hmenuParent = LoadMenu(hinst, MAKEINTRESOURCE(id));
if (hmenuParent)
{
HMENU hpopup = GetSubMenu(hmenuParent, 0);
RemoveMenu(hmenuParent, 0, MF_BYPOSITION);
DestroyMenu(hmenuParent);
return hpopup;
}
return NULL;
}