Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

246 lines
6.4 KiB

//+-------------------------------------------------------------------------
//
// TaskMan - NT TaskManager
// Copyright (C) Microsoft
//
// File: trayicon.CPP
//
// History: Jan-27-96 DavePl Created
//
//--------------------------------------------------------------------------
#include "precomp.h"
// Queue for messages to be processed by the worker thread
#define MSG_QUEUE_SIZE 5
CTrayNotification * g_apQueue[MSG_QUEUE_SIZE] = { NULL };
CRITICAL_SECTION g_CSTrayThread;
UINT g_cQueueSize = 0;
/*++ DeliverTrayNotification (MAIN THREAD CODE)
Routine Description:
Adds a tray notification block to the list of things to be done
by the tray notify worker thread
Arguments:
pNot - The CTrayNotification object to be queued
Returns:
TRUE - Message added to queue
FALSE - Queue full
Revision History:
Mar-27-95 Davepl Created
*/
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;
}
/*++ TrayThreadMessageLoop (WORKER THREAD CODE)
Routine Description:
Waits for messages telling it a notification packet is ready
in the queue, then dispatches it to the tray
Mar-27-95 Davepl Created
--*/
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);
ASSERT(g_cQueueSize);
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. If it blocks, our queue
// will fill, but taskman itself won't hang
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);
PostQuitMessage(0);
break;
}
default:
{
ASSERT(0 && "Taskman tray worker got unexpected message");
break;
}
}
}
return 0;
}
/*++ Tray_NotifyIcon (WORKER THREAD CODE)
Routine Description:
Handles adding, updating, etc., of icon on the tray
Arguments:
hWnd - icon owner
uCallbackMessage - message ID to be used for callback
Message - argument to Shell_NotifyIcon (NIM_ADD, NIM_DELETE, etc)
hIcon - Handle to the icon
lpTip - tooltip text for the icon
Revision History:
Jan-27-95 Davepl Created
--*/
void Tray_NotifyIcon(HWND hWnd,
UINT uCallbackMessage,
DWORD Message,
HICON hIcon,
LPCTSTR lpTip)
{
NOTIFYICONDATA NotifyIconData;
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);
}
/*++ Tray_Notify (MAIN THREAD CODE)
Routine Description:
Handles notifications sent by the tray
Revision History:
Jan-27-95 Davepl Created
--*/
void Tray_Notify(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_LBUTTONDBLCLK:
ShowRunningInstance();
break;
case WM_RBUTTONDOWN:
{
HMENU hPopup = LoadPopupMenu(g_hInstance, IDR_TRAYMENU);
// Display the tray icons context menu at the current cursor location
if (hPopup)
{
POINT pt;
GetCursorPos(&pt);
if (IsWindowVisible(g_hMainWnd))
{
DeleteMenu(hPopup, IDM_RESTORETASKMAN, MF_BYCOMMAND);
}
else
{
SetMenuDefaultItem(hPopup, IDM_RESTORETASKMAN, FALSE);
}
CheckMenuItem(hPopup, IDM_ALWAYSONTOP,
MF_BYCOMMAND | (g_Options.m_fAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
SetForegroundWindow(hWnd);
g_fInPopup = TRUE;
TrackPopupMenuEx(hPopup, 0, pt.x, pt.y, hWnd, NULL);
g_fInPopup = FALSE;
DestroyMenu(hPopup);
}
break;
}
}
}