|
|
#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; }
|