200 lines
5.4 KiB
C++
200 lines
5.4 KiB
C++
|
#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;
|
||
|
}
|