1 /*
2 * PROJECT: ReactOS Task Manager
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Tray Icon.
5 * COPYRIGHT: Copyright 1999-2001 Brian Palmer <brianp@reactos.org>
6 * Copyright 2005 Klemens Friedl <frik85@reactos.at>
7 */
8
9 #include "precomp.h"
10
11 static HICON
TrayIcon_GetProcessorUsageIcon(_In_ ULONG CpuUsage)12 TrayIcon_GetProcessorUsageIcon(
13 _In_ ULONG CpuUsage)
14 {
15 HICON hTrayIcon = NULL;
16 HDC hScreenDC = NULL;
17 HDC hDC = NULL;
18 HBITMAP hBitmap = NULL;
19 HBITMAP hOldBitmap = NULL;
20 HBITMAP hBitmapMask = NULL;
21 ICONINFO iconInfo;
22 int nLinesToDraw;
23 HBRUSH hBitmapBrush = NULL;
24 RECT rc;
25
26 /* Get a handle to the screen DC */
27 hScreenDC = GetDC(NULL);
28 if (!hScreenDC)
29 goto done;
30
31 /* Create our own DC from it */
32 hDC = CreateCompatibleDC(hScreenDC);
33 if (!hDC)
34 goto done;
35
36 /*
37 * Load the bitmaps
38 */
39 hBitmap = LoadBitmapW(hInst, MAKEINTRESOURCEW(IDB_TRAYICON));
40 hBitmapMask = LoadBitmapW(hInst, MAKEINTRESOURCEW(IDB_TRAYMASK));
41 if (!hBitmap || !hBitmapMask)
42 goto done;
43
44 hBitmapBrush = CreateSolidBrush(RGB(0, 255, 0));
45 if (!hBitmapBrush)
46 goto done;
47
48 /*
49 * Select the bitmap into our device context
50 * so we can draw on it.
51 */
52 hOldBitmap = SelectObject(hDC, hBitmap);
53
54 /*
55 * Calculate how many lines to draw
56 * since we have 11 rows of space
57 * to draw the cpu usage instead of
58 * just having 10.
59 */
60 nLinesToDraw = (CpuUsage + (CpuUsage / 10)) / 11;
61 rc.left = 3;
62 rc.top = 12 - nLinesToDraw;
63 rc.right = 13;
64 rc.bottom = 13;
65
66 /* Now draw the cpu usage */
67 if (nLinesToDraw)
68 FillRect(hDC, &rc, hBitmapBrush);
69
70 /*
71 * Now that we are done drawing put the
72 * old bitmap back.
73 */
74 hBitmap = SelectObject(hDC, hOldBitmap);
75 hOldBitmap = NULL;
76
77 iconInfo.fIcon = TRUE;
78 iconInfo.hbmMask = hBitmapMask;
79 iconInfo.hbmColor = hBitmap;
80
81 hTrayIcon = CreateIconIndirect(&iconInfo);
82
83 done:
84 /*
85 * Cleanup
86 */
87 if (hScreenDC)
88 ReleaseDC(NULL, hScreenDC);
89 if (hDC)
90 DeleteDC(hDC);
91 if (hBitmapBrush)
92 DeleteObject(hBitmapBrush);
93 if (hBitmap)
94 DeleteObject(hBitmap);
95 if (hBitmapMask)
96 DeleteObject(hBitmapMask);
97
98 /* Return the newly created tray icon (if successful) */
99 return hTrayIcon;
100 }
101
102 static BOOL
TrayIcon_Update(_In_ DWORD dwMessage)103 TrayIcon_Update(
104 _In_ DWORD dwMessage)
105 {
106 static WCHAR szMsg[64] = L"";
107
108 NOTIFYICONDATAW nid;
109 ULONG CpuUsage;
110 HICON hIcon = NULL;
111 BOOL bRetVal;
112
113 if (!*szMsg)
114 LoadStringW(hInst, IDS_MSG_TRAYICONCPUUSAGE, szMsg, _countof(szMsg));
115
116 ZeroMemory(&nid, sizeof(nid));
117
118 CpuUsage = PerfDataGetProcessorUsage();
119 hIcon = TrayIcon_GetProcessorUsageIcon(CpuUsage);
120
121 nid.cbSize = sizeof(nid);
122 nid.hWnd = hMainWnd;
123 nid.uID = 0;
124 nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
125 nid.uCallbackMessage = WM_ONTRAYICON;
126 nid.hIcon = hIcon;
127
128 StringCchPrintfW(nid.szTip, _countof(nid.szTip), szMsg, CpuUsage);
129
130 bRetVal = Shell_NotifyIconW(dwMessage, &nid);
131
132 if (hIcon)
133 DestroyIcon(hIcon);
134
135 return bRetVal;
136 }
137
TrayIcon_AddIcon(VOID)138 BOOL TrayIcon_AddIcon(VOID)
139 {
140 return TrayIcon_Update(NIM_ADD);
141 }
142
TrayIcon_RemoveIcon(VOID)143 BOOL TrayIcon_RemoveIcon(VOID)
144 {
145 NOTIFYICONDATAW nid;
146
147 ZeroMemory(&nid, sizeof(nid));
148
149 nid.cbSize = sizeof(nid);
150 nid.hWnd = hMainWnd;
151 nid.uID = 0;
152 nid.uFlags = 0;
153 nid.uCallbackMessage = WM_ONTRAYICON;
154
155 return Shell_NotifyIconW(NIM_DELETE, &nid);
156 }
157
TrayIcon_UpdateIcon(VOID)158 BOOL TrayIcon_UpdateIcon(VOID)
159 {
160 return TrayIcon_Update(NIM_MODIFY);
161 }
162