[APPLICATIONS]
[reactos.git] / reactos / base / applications / taskmgr / graph.c
1 /*
2 * ReactOS Task Manager
3 *
4 * graph.c
5 *
6 * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "precomp.h"
24
25 int nlastBarsUsed = 0;
26
27 WNDPROC OldGraphWndProc;
28
29 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd);
30 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd);
31 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd);
32
33 INT_PTR CALLBACK
34 Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
35 {
36 HDC hdc;
37 PAINTSTRUCT ps;
38 LONG WindowId;
39
40 switch (message)
41 {
42 case WM_ERASEBKGND:
43 return TRUE;
44
45 /*
46 * Filter out mouse & keyboard messages
47 */
48 /* case WM_APPCOMMAND: */
49 case WM_CAPTURECHANGED:
50 case WM_LBUTTONDBLCLK:
51 case WM_LBUTTONDOWN:
52 case WM_LBUTTONUP:
53 case WM_MBUTTONDBLCLK:
54 case WM_MBUTTONDOWN:
55 case WM_MBUTTONUP:
56 case WM_MOUSEACTIVATE:
57 case WM_MOUSEHOVER:
58 case WM_MOUSELEAVE:
59 case WM_MOUSEMOVE:
60 /* case WM_MOUSEWHEEL: */
61 case WM_NCHITTEST:
62 case WM_NCLBUTTONDBLCLK:
63 case WM_NCLBUTTONDOWN:
64 case WM_NCLBUTTONUP:
65 case WM_NCMBUTTONDBLCLK:
66 case WM_NCMBUTTONDOWN:
67 case WM_NCMBUTTONUP:
68 /* case WM_NCMOUSEHOVER: */
69 /* case WM_NCMOUSELEAVE: */
70 case WM_NCMOUSEMOVE:
71 case WM_NCRBUTTONDBLCLK:
72 case WM_NCRBUTTONDOWN:
73 case WM_NCRBUTTONUP:
74 /* case WM_NCXBUTTONDBLCLK: */
75 /* case WM_NCXBUTTONDOWN: */
76 /* case WM_NCXBUTTONUP: */
77 case WM_RBUTTONDBLCLK:
78 case WM_RBUTTONDOWN:
79 case WM_RBUTTONUP:
80 /* case WM_XBUTTONDBLCLK: */
81 /* case WM_XBUTTONDOWN: */
82 /* case WM_XBUTTONUP: */
83 case WM_ACTIVATE:
84 case WM_CHAR:
85 case WM_DEADCHAR:
86 case WM_GETHOTKEY:
87 case WM_HOTKEY:
88 case WM_KEYDOWN:
89 case WM_KEYUP:
90 case WM_KILLFOCUS:
91 case WM_SETFOCUS:
92 case WM_SETHOTKEY:
93 case WM_SYSCHAR:
94 case WM_SYSDEADCHAR:
95 case WM_SYSKEYDOWN:
96 case WM_SYSKEYUP:
97
98 case WM_NCCALCSIZE:
99 return 0;
100
101 case WM_PAINT:
102
103 hdc = BeginPaint(hWnd, &ps);
104
105 WindowId = GetWindowLongPtrW(hWnd, GWLP_ID);
106
107 switch (WindowId)
108 {
109 case IDC_CPU_USAGE_GRAPH:
110 Graph_DrawCpuUsageGraph(hdc, hWnd);
111 break;
112 case IDC_MEM_USAGE_GRAPH:
113 Graph_DrawMemUsageGraph(hdc, hWnd);
114 break;
115 case IDC_MEM_USAGE_HISTORY_GRAPH:
116 Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
117 break;
118 }
119
120 EndPaint(hWnd, &ps);
121
122 return 0;
123
124 }
125
126 /*
127 * We pass on all non-handled messages
128 */
129 return CallWindowProcW(OldGraphWndProc, hWnd, message, wParam, lParam);
130 }
131
132 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
133 {
134 RECT rcClient;
135 RECT rcBarLeft;
136 RECT rcBarRight;
137 RECT rcText;
138 COLORREF crPrevForeground;
139 WCHAR Text[260];
140 HFONT hOldFont;
141 ULONG CpuUsage;
142 ULONG CpuKernelUsage;
143 int nBars;
144 int nBarsUsed;
145 /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
146 int nBarsUsedKernel;
147 /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
148 int nBarsFree;
149 /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
150 int i;
151
152 /*
153 * Get the client area rectangle
154 */
155 GetClientRect(hWnd, &rcClient);
156
157 /*
158 * Fill it with blackness
159 */
160 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
161
162 /*
163 * Get the CPU usage
164 */
165 CpuUsage = PerfDataGetProcessorUsage();
166 if (CpuUsage <= 0) CpuUsage = 0;
167 if (CpuUsage > 100) CpuUsage = 100;
168
169 wsprintfW(Text, L"%d%%", (int)CpuUsage);
170
171 /*
172 * Draw the font text onto the graph
173 */
174 rcText = rcClient;
175 InflateRect(&rcText, -2, -2);
176 crPrevForeground = SetTextColor(hDC, RGB(0, 255, 0));
177 hOldFont = SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
178 DrawTextW(hDC, Text, -1, &rcText, DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE);
179 SelectObject(hDC, hOldFont);
180 SetTextColor(hDC, crPrevForeground);
181
182 /*
183 * Now we have to draw the graph
184 * So first find out how many bars we can fit
185 */
186 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
187 nBarsUsed = (nBars * CpuUsage) / 100;
188 if ((CpuUsage) && (nBarsUsed == 0))
189 {
190 nBarsUsed = 1;
191 }
192 nBarsFree = nBars - (nlastBarsUsed>nBarsUsed ? nlastBarsUsed : nBarsUsed);
193
194 if (TaskManagerSettings.ShowKernelTimes)
195 {
196 CpuKernelUsage = PerfDataGetProcessorSystemUsage();
197 if (CpuKernelUsage <= 0) CpuKernelUsage = 0;
198 if (CpuKernelUsage >= 100) CpuKernelUsage = 100;
199 nBarsUsedKernel = (nBars * CpuKernelUsage) / 100;
200 }
201 else
202 {
203 nBarsUsedKernel = 0;
204 }
205
206 /*
207 * Now draw the bar graph
208 */
209 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
210 rcBarLeft.right = rcBarLeft.left + 16;
211 rcBarRight.left = rcBarLeft.left + 17;
212 rcBarRight.right = rcBarLeft.right + 17;
213 rcBarLeft.top = rcBarRight.top = 5;
214 rcBarLeft.bottom = rcBarRight.bottom = 7;
215
216 if (nBarsUsed < 0) nBarsUsed = 0;
217 if (nBarsUsed > nBars) nBarsUsed = nBars;
218
219 if (nBarsFree < 0) nBarsFree = 0;
220 if (nBarsFree > nBars) nBarsFree = nBars;
221
222 if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
223 if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
224
225 /*
226 * Draw the "free" bars
227 */
228 for (i=0; i<nBarsFree; i++)
229 {
230 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
231 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
232
233 rcBarLeft.top += 3;
234 rcBarLeft.bottom += 3;
235
236 rcBarRight.top += 3;
237 rcBarRight.bottom += 3;
238 }
239
240 /*
241 * Draw the last "used" bars
242 */
243 if ((nlastBarsUsed - nBarsUsed) > 0) {
244 for (i=0; i< (nlastBarsUsed - nBarsUsed); i++)
245 {
246 if (nlastBarsUsed > 5000) nlastBarsUsed = 5000;
247
248 FillSolidRect(hDC, &rcBarLeft, MEDIUM_GREEN);
249 FillSolidRect(hDC, &rcBarRight, MEDIUM_GREEN);
250
251 rcBarLeft.top += 3;
252 rcBarLeft.bottom += 3;
253
254 rcBarRight.top += 3;
255 rcBarRight.bottom += 3;
256 }
257 }
258 nlastBarsUsed = nBarsUsed;
259 /*
260 * Draw the "used" bars
261 */
262 for (i=0; i<nBarsUsed; i++)
263 {
264 if (nBarsUsed > 5000) nBarsUsed = 5000;
265
266 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
267 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
268
269 rcBarLeft.top += 3;
270 rcBarLeft.bottom += 3;
271
272 rcBarRight.top += 3;
273 rcBarRight.bottom += 3;
274 }
275
276 /*
277 * Draw the "used" kernel bars
278 */
279
280 rcBarLeft.top -=3;
281 rcBarLeft.bottom -=3;
282
283 rcBarRight.top -=3;
284 rcBarRight.bottom -=3;
285
286 for (i=0; i<nBarsUsedKernel; i++)
287 {
288
289 FillSolidRect(hDC, &rcBarLeft, RED);
290 FillSolidRect(hDC, &rcBarRight, RED);
291
292 rcBarLeft.top -=3;
293 rcBarLeft.bottom -=3;
294
295 rcBarRight.top -=3;
296 rcBarRight.bottom -=3;
297
298 }
299
300 SelectObject(hDC, hOldFont);
301 }
302
303 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
304 {
305 RECT rcClient;
306 RECT rcBarLeft;
307 RECT rcBarRight;
308 RECT rcText;
309 COLORREF crPrevForeground;
310 WCHAR Text[260];
311 HFONT hOldFont;
312 ULONGLONG CommitChargeTotal;
313 ULONGLONG CommitChargeLimit;
314 int nBars;
315 int nBarsUsed = 0;
316 /* Bottom bars that are "used", i.e. are bright green, representing used memory */
317 int nBarsFree;
318 /* Top bars that are "unused", i.e. are dark green, representing free memory */
319 int i;
320
321 /*
322 * Get the client area rectangle
323 */
324 GetClientRect(hWnd, &rcClient);
325
326 /*
327 * Fill it with blackness
328 */
329 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
330
331 /*
332 * Get the memory usage
333 */
334 CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
335 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
336
337 if (CommitChargeTotal > 1024)
338 wsprintfW(Text, L"%d MB", (int)(CommitChargeTotal / 1024));
339 else
340 wsprintfW(Text, L"%d K", (int)CommitChargeTotal);
341 /*
342 * Draw the font text onto the graph
343 */
344 rcText = rcClient;
345 InflateRect(&rcText, -2, -2);
346 crPrevForeground = SetTextColor(hDC, RGB(0, 255, 0));
347 hOldFont = SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
348 DrawTextW(hDC, Text, -1, &rcText, DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE);
349 SelectObject(hDC, hOldFont);
350 SetTextColor(hDC, crPrevForeground);
351
352 /*
353 * Now we have to draw the graph
354 * So first find out how many bars we can fit
355 */
356 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
357 if (CommitChargeLimit)
358 nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
359 nBarsFree = nBars - nBarsUsed;
360
361 if (nBarsUsed < 0) nBarsUsed = 0;
362 if (nBarsUsed > nBars) nBarsUsed = nBars;
363
364 if (nBarsFree < 0) nBarsFree = 0;
365 if (nBarsFree > nBars) nBarsFree = nBars;
366
367 /*
368 * Now draw the bar graph
369 */
370 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
371 rcBarLeft.right = rcBarLeft.left + 16;
372 rcBarRight.left = rcBarLeft.left + 17;
373 rcBarRight.right = rcBarLeft.right + 17;
374 rcBarLeft.top = rcBarRight.top = 5;
375 rcBarLeft.bottom = rcBarRight.bottom = 7;
376
377 /*
378 * Draw the "free" bars
379 */
380 for (i=0; i<nBarsFree; i++)
381 {
382 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
383 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
384
385 rcBarLeft.top += 3;
386 rcBarLeft.bottom += 3;
387
388 rcBarRight.top += 3;
389 rcBarRight.bottom += 3;
390 }
391
392 /*
393 * Draw the "used" bars
394 */
395 for (i=0; i<nBarsUsed; i++)
396 {
397 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
398 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
399
400 rcBarLeft.top += 3;
401 rcBarLeft.bottom += 3;
402
403 rcBarRight.top += 3;
404 rcBarRight.bottom += 3;
405 }
406
407 SelectObject(hDC, hOldFont);
408 }
409
410 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
411 {
412 RECT rcClient;
413 //ULONGLONG CommitChargeLimit;
414 int i;
415 static int offset = 0;
416
417 if (offset++ >= 10)
418 offset = 0;
419
420 /*
421 * Get the client area rectangle
422 */
423 GetClientRect(hWnd, &rcClient);
424
425 /*
426 * Fill it with blackness
427 */
428 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
429
430 /*
431 * Get the memory usage
432 */
433 //CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
434
435 /*
436 * Draw the graph background
437 *
438 * Draw the horizontal bars
439 */
440 for (i=0; i<rcClient.bottom; i++)
441 {
442 if ((i % 11) == 0)
443 {
444 /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN); */
445 }
446 }
447 /*
448 * Draw the vertical bars
449 */
450 for (i=11; i<rcClient.right + offset; i++)
451 {
452 if ((i % 11) == 0)
453 {
454 /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN); */
455 }
456 }
457
458 /*
459 * Draw the memory usage
460 */
461 for (i=rcClient.right; i>=0; i--)
462 {
463 }
464 }