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