Fixes to performance page resizing and font.bmp updated.
[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 case WM_NCCALCSIZE:
115 return 0;
116
117 case WM_PAINT:
118
119 hdc = BeginPaint(hWnd, &ps);
120
121 WindowId = GetWindowLong(hWnd, GWL_ID);
122
123 switch (WindowId)
124 {
125 case IDC_CPU_USAGE_GRAPH:
126 Graph_DrawCpuUsageGraph(hdc, hWnd);
127 break;
128 case IDC_MEM_USAGE_GRAPH:
129 Graph_DrawMemUsageGraph(hdc, hWnd);
130 break;
131 case IDC_MEM_USAGE_HISTORY_GRAPH:
132 Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
133 break;
134 }
135
136 EndPaint(hWnd, &ps);
137
138 return 0;
139
140 }
141
142 //
143 // We pass on all non-handled messages
144 //
145 return CallWindowProc((WNDPROC)OldGraphWndProc, hWnd, message, wParam, lParam);
146 }
147
148 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
149 {
150 RECT rcClient;
151 RECT rcBarLeft;
152 RECT rcBarRight;
153 TCHAR Text[260];
154 ULONG CpuUsage;
155 ULONG CpuKernelUsage;
156 int nBars;
157 int nBarsUsed; // Bottom bars that are "used", i.e. are bright green, representing used cpu time
158 int nBarsUsedKernel; // Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time
159 int nBarsFree; // Top bars that are "unused", i.e. are dark green, representing free cpu time
160 int i;
161
162 //
163 // Get the client area rectangle
164 //
165 GetClientRect(hWnd, &rcClient);
166
167 //
168 // Fill it with blackness
169 //
170 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
171
172 //
173 // Get the CPU usage
174 //
175 CpuUsage = PerfDataGetProcessorUsage();
176 CpuKernelUsage = PerfDataGetProcessorSystemUsage();
177 if (CpuUsage < 0) CpuUsage = 0;
178 if (CpuUsage > 100) CpuUsage = 100;
179 if (CpuKernelUsage < 0) CpuKernelUsage = 0;
180 if (CpuKernelUsage > 100) CpuKernelUsage = 100;
181
182 //
183 // Check and see how many digits it will take
184 // so we get the indentation right every time.
185 //
186 if (CpuUsage == 100)
187 {
188 sprintf(Text, "%d%%", CpuUsage);
189 }
190 else if (CpuUsage < 10)
191 {
192 sprintf(Text, " %d%%", CpuUsage);
193 }
194 else
195 {
196 sprintf(Text, " %d%%", CpuUsage);
197 }
198
199 //
200 // Draw the font text onto the graph
201 // The bottom 20 pixels are reserved for the text
202 //
203 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - 32) / 2, rcClient.bottom - 11 - 5);
204
205 //
206 // Now we have to draw the graph
207 // So first find out how many bars we can fit
208 //
209 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
210 nBarsUsed = (nBars * CpuUsage) / 100;
211 if ((CpuUsage) && (nBarsUsed == 0))
212 {
213 nBarsUsed = 1;
214 }
215 nBarsFree = nBars - nBarsUsed;
216 if (TaskManagerSettings.ShowKernelTimes)
217 {
218 nBarsUsedKernel = ((nBars * 2) * CpuKernelUsage) / 100;
219 nBarsUsed -= (nBarsUsedKernel / 2);
220 }
221 else
222 {
223 nBarsUsedKernel = 0;
224 }
225
226 //
227 // Now draw the bar graph
228 //
229 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
230 rcBarLeft.right = rcBarLeft.left + 16;
231 rcBarRight.left = rcBarLeft.left + 17;
232 rcBarRight.right = rcBarLeft.right + 17;
233 rcBarLeft.top = rcBarRight.top = 5;
234 rcBarLeft.bottom = rcBarRight.bottom = 7;
235
236 if (nBarsUsed < 0) nBarsUsed = 0;
237 if (nBarsUsed > nBars) nBarsUsed = nBars;
238
239 if (nBarsFree < 0) nBarsFree = 0;
240 if (nBarsFree > nBars) nBarsFree = nBars;
241
242 if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
243 if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
244
245 //
246 // Draw the "free" bars
247 //
248 for (i=0; i<nBarsFree; i++)
249 {
250 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
251 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
252
253 rcBarLeft.top += 3;
254 rcBarLeft.bottom += 3;
255
256 rcBarRight.top += 3;
257 rcBarRight.bottom += 3;
258 }
259
260 //
261 // Draw the "used" bars
262 //
263 for (i=0; i<nBarsUsed; i++)
264 {
265 if (nBarsUsed > 5000) nBarsUsed = 5000;
266
267 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
268 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
269
270 rcBarLeft.top += 3;
271 rcBarLeft.bottom += 3;
272
273 rcBarRight.top += 3;
274 rcBarRight.bottom += 3;
275 }
276
277 //
278 // Draw the "used" kernel bars
279 //
280 rcBarLeft.bottom--;
281 rcBarRight.bottom--;
282 if (nBarsUsedKernel && nBarsUsedKernel % 2)
283 {
284 rcBarLeft.top -= 2;
285 rcBarLeft.bottom -= 2;
286
287 rcBarRight.top -= 2;
288 rcBarRight.bottom -= 2;
289
290 FillSolidRect(hDC, &rcBarLeft, RED);
291 FillSolidRect(hDC, &rcBarRight, RED);
292
293 rcBarLeft.top += 2;
294 rcBarLeft.bottom += 2;
295
296 rcBarRight.top += 2;
297 rcBarRight.bottom += 2;
298
299 nBarsUsedKernel--;
300 }
301 for (i=0; i<nBarsUsedKernel; i++)
302 {
303 if (nBarsUsedKernel > 5000) nBarsUsedKernel = 5000;
304
305 FillSolidRect(hDC, &rcBarLeft, RED);
306 FillSolidRect(hDC, &rcBarRight, RED);
307
308 rcBarLeft.top++;
309 rcBarLeft.bottom++;
310
311 rcBarRight.top++;
312 rcBarRight.bottom++;
313
314 if (i % 2)
315 {
316 rcBarLeft.top++;
317 rcBarLeft.bottom++;
318
319 rcBarRight.top++;
320 rcBarRight.bottom++;
321 }
322 }
323 }
324
325 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
326 {
327 RECT rcClient;
328 RECT rcBarLeft;
329 RECT rcBarRight;
330 TCHAR Text[260];
331 ULONGLONG CommitChargeTotal;
332 ULONGLONG CommitChargeLimit;
333 int nBars;
334 int nBarsUsed; // Bottom bars that are "used", i.e. are bright green, representing used memory
335 int nBarsFree; // Top bars that are "unused", i.e. are dark green, representing free memory
336 int i;
337
338 //
339 // Get the client area rectangle
340 //
341 GetClientRect(hWnd, &rcClient);
342
343 //
344 // Fill it with blackness
345 //
346 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
347
348 //
349 // Get the memory usage
350 //
351 CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
352 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
353
354 sprintf(Text, "%dK", CommitChargeTotal);
355
356 //
357 // Draw the font text onto the graph
358 // The bottom 20 pixels are reserved for the text
359 //
360 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - (strlen(Text) * 8)) / 2, rcClient.bottom - 11 - 5);
361
362 //
363 // Now we have to draw the graph
364 // So first find out how many bars we can fit
365 //
366 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
367 nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
368 nBarsFree = nBars - nBarsUsed;
369
370 if (nBarsUsed < 0) nBarsUsed = 0;
371 if (nBarsUsed > nBars) nBarsUsed = nBars;
372
373 if (nBarsFree < 0) nBarsFree = 0;
374 if (nBarsFree > nBars) nBarsFree = nBars;
375
376 //
377 // Now draw the bar graph
378 //
379 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
380 rcBarLeft.right = rcBarLeft.left + 16;
381 rcBarRight.left = rcBarLeft.left + 17;
382 rcBarRight.right = rcBarLeft.right + 17;
383 rcBarLeft.top = rcBarRight.top = 5;
384 rcBarLeft.bottom = rcBarRight.bottom = 7;
385
386 //
387 // Draw the "free" bars
388 //
389 for (i=0; i<nBarsFree; i++)
390 {
391 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
392 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
393
394 rcBarLeft.top += 3;
395 rcBarLeft.bottom += 3;
396
397 rcBarRight.top += 3;
398 rcBarRight.bottom += 3;
399 }
400
401 //
402 // Draw the "used" bars
403 //
404 for (i=0; i<nBarsUsed; i++)
405 {
406 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
407 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
408
409 rcBarLeft.top += 3;
410 rcBarLeft.bottom += 3;
411
412 rcBarRight.top += 3;
413 rcBarRight.bottom += 3;
414 }
415 }
416
417 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
418 {
419 RECT rcClient;
420 ULONGLONG CommitChargeLimit;
421 int i;
422 static int offset = 0;
423
424 if (offset++ >= 10)
425 offset = 0;
426
427 //
428 // Get the client area rectangle
429 //
430 GetClientRect(hWnd, &rcClient);
431
432 //
433 // Fill it with blackness
434 //
435 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
436
437 //
438 // Get the memory usage
439 //
440 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
441
442 //
443 // Draw the graph background
444 //
445 // Draw the horizontal bars
446 //
447 for (i=0; i<rcClient.bottom; i++)
448 {
449 if ((i % 11) == 0)
450 {
451 FillSolidRect(hDC, 0, i, rcClient.right, 1, DARK_GREEN);
452 }
453 }
454 //
455 // Draw the vertical bars
456 //
457 for (i=11; i<rcClient.right + offset; i++)
458 {
459 if ((i % 11) == 0)
460 {
461 FillSolidRect(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN);
462 }
463 }
464
465 //
466 // Draw the memory usage
467 //
468 for (i=rcClient.right; i>=0; i--)
469 {
470 }
471 }