blob: 4db1d8756dcf259dfc0b3485d8b2a47a2e548e18 [file] [log] [blame]
Eric Pouechd6b348f2004-03-23 01:19:54 +00001/*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
24#include <windows.h>
25#include <commctrl.h>
26#include <stdlib.h>
27#include <malloc.h>
28#include <memory.h>
29#include <tchar.h>
30#include <stdio.h>
31#include <winnt.h>
32
33#include "taskmgr.h"
34#include "perfdata.h"
35
36#define BRIGHT_GREEN RGB(0, 255, 0)
37#define DARK_GREEN RGB(0, 130, 0)
38#define RED RGB(255, 0, 0)
39
40
41LONG OldGraphWndProc;
42
43void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd);
44void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd);
45void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd);
46
47LRESULT CALLBACK Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
48{
49 HDC hdc;
50 PAINTSTRUCT ps;
51 LONG WindowId;
52
53 switch (message)
54 {
55 case WM_ERASEBKGND:
56 return TRUE;
57
58 /*
59 * Filter out mouse & keyboard messages
60 */
61 /* case WM_APPCOMMAND: */
62 case WM_CAPTURECHANGED:
63 case WM_LBUTTONDBLCLK:
64 case WM_LBUTTONDOWN:
65 case WM_LBUTTONUP:
66 case WM_MBUTTONDBLCLK:
67 case WM_MBUTTONDOWN:
68 case WM_MBUTTONUP:
69 case WM_MOUSEACTIVATE:
70 case WM_MOUSEHOVER:
71 case WM_MOUSELEAVE:
72 case WM_MOUSEMOVE:
73 /* case WM_MOUSEWHEEL: */
74 case WM_NCHITTEST:
75 case WM_NCLBUTTONDBLCLK:
76 case WM_NCLBUTTONDOWN:
77 case WM_NCLBUTTONUP:
78 case WM_NCMBUTTONDBLCLK:
79 case WM_NCMBUTTONDOWN:
80 case WM_NCMBUTTONUP:
81 /* case WM_NCMOUSEHOVER: */
82 /* case WM_NCMOUSELEAVE: */
83 case WM_NCMOUSEMOVE:
84 case WM_NCRBUTTONDBLCLK:
85 case WM_NCRBUTTONDOWN:
86 case WM_NCRBUTTONUP:
87 /* case WM_NCXBUTTONDBLCLK: */
88 /* case WM_NCXBUTTONDOWN: */
89 /* case WM_NCXBUTTONUP: */
90 case WM_RBUTTONDBLCLK:
91 case WM_RBUTTONDOWN:
92 case WM_RBUTTONUP:
93 /* case WM_XBUTTONDBLCLK: */
94 /* case WM_XBUTTONDOWN: */
95 /* case WM_XBUTTONUP: */
96 case WM_ACTIVATE:
97 case WM_CHAR:
98 case WM_DEADCHAR:
99 case WM_GETHOTKEY:
100 case WM_HOTKEY:
101 case WM_KEYDOWN:
102 case WM_KEYUP:
103 case WM_KILLFOCUS:
104 case WM_SETFOCUS:
105 case WM_SETHOTKEY:
106 case WM_SYSCHAR:
107 case WM_SYSDEADCHAR:
108 case WM_SYSKEYDOWN:
109 case WM_SYSKEYUP:
110
111 case WM_NCCALCSIZE:
112 return 0;
113
114 case WM_PAINT:
115
116 hdc = BeginPaint(hWnd, &ps);
117
118 WindowId = GetWindowLong(hWnd, GWL_ID);
119
120 switch (WindowId)
121 {
122 case IDC_CPU_USAGE_GRAPH:
123 Graph_DrawCpuUsageGraph(hdc, hWnd);
124 break;
125 case IDC_MEM_USAGE_GRAPH:
126 Graph_DrawMemUsageGraph(hdc, hWnd);
127 break;
128 case IDC_MEM_USAGE_HISTORY_GRAPH:
129 Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
130 break;
131 }
132
133 EndPaint(hWnd, &ps);
134
135 return 0;
136
137 }
138
139 /*
140 * We pass on all non-handled messages
141 */
142 return CallWindowProc((WNDPROC)OldGraphWndProc, hWnd, message, wParam, lParam);
143}
144
145void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
146{
147 RECT rcClient;
148 RECT rcBarLeft;
149 RECT rcBarRight;
150 TCHAR Text[260];
151 ULONG CpuUsage;
152 ULONG CpuKernelUsage;
153 int nBars;
154 int nBarsUsed;
155/* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
156 int nBarsUsedKernel;
157/* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
158 int nBarsFree;
159/* 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 _stprintf(Text, _T("%d%%"), (int)CpuUsage);
189 }
190 else if (CpuUsage < 10)
191 {
192 _stprintf(Text, _T(" %d%%"), (int)CpuUsage);
193 }
194 else
195 {
196 _stprintf(Text, _T(" %d%%"), (int)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
325void 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 = 0;
335/* Bottom bars that are "used", i.e. are bright green, representing used memory */
336 int nBarsFree;
337/* Top bars that are "unused", i.e. are dark green, representing free memory */
338 int i;
339
340 /*
341 * Get the client area rectangle
342 */
343 GetClientRect(hWnd, &rcClient);
344
345 /*
346 * Fill it with blackness
347 */
348 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
349
350 /*
351 * Get the memory usage
352 */
353 CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
354 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
355
356 _stprintf(Text, _T("%dK"), (int)CommitChargeTotal);
357
358 /*
359 * Draw the font text onto the graph
360 * The bottom 20 pixels are reserved for the text
361 */
362 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - (_tcslen(Text) * 8)) / 2, rcClient.bottom - 11 - 5);
363
364 /*
365 * Now we have to draw the graph
366 * So first find out how many bars we can fit
367 */
368 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
369 if (CommitChargeLimit)
370 nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
371 nBarsFree = nBars - nBarsUsed;
372
373 if (nBarsUsed < 0) nBarsUsed = 0;
374 if (nBarsUsed > nBars) nBarsUsed = nBars;
375
376 if (nBarsFree < 0) nBarsFree = 0;
377 if (nBarsFree > nBars) nBarsFree = nBars;
378
379 /*
380 * Now draw the bar graph
381 */
382 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
383 rcBarLeft.right = rcBarLeft.left + 16;
384 rcBarRight.left = rcBarLeft.left + 17;
385 rcBarRight.right = rcBarLeft.right + 17;
386 rcBarLeft.top = rcBarRight.top = 5;
387 rcBarLeft.bottom = rcBarRight.bottom = 7;
388
389 /*
390 * Draw the "free" bars
391 */
392 for (i=0; i<nBarsFree; i++)
393 {
394 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
395 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
396
397 rcBarLeft.top += 3;
398 rcBarLeft.bottom += 3;
399
400 rcBarRight.top += 3;
401 rcBarRight.bottom += 3;
402 }
403
404 /*
405 * Draw the "used" bars
406 */
407 for (i=0; i<nBarsUsed; i++)
408 {
409 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
410 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
411
412 rcBarLeft.top += 3;
413 rcBarLeft.bottom += 3;
414
415 rcBarRight.top += 3;
416 rcBarRight.bottom += 3;
417 }
418}
419
420void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
421{
422 RECT rcClient;
423 ULONGLONG CommitChargeLimit;
424 int i;
425 static int offset = 0;
426
427 if (offset++ >= 10)
428 offset = 0;
429
430 /*
431 * Get the client area rectangle
432 */
433 GetClientRect(hWnd, &rcClient);
434
435 /*
436 * Fill it with blackness
437 */
438 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
439
440 /*
441 * Get the memory usage
442 */
443 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
444
445 /*
446 * Draw the graph background
447 *
448 * Draw the horizontal bars
449 */
450 for (i=0; i<rcClient.bottom; i++)
451 {
452 if ((i % 11) == 0)
453 {
454 /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN); */
455 }
456 }
457 /*
458 * Draw the vertical bars
459 */
460 for (i=11; i<rcClient.right + offset; i++)
461 {
462 if ((i % 11) == 0)
463 {
464 /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN); */
465 }
466 }
467
468 /*
469 * Draw the memory usage
470 */
471 for (i=rcClient.right; i>=0; i--)
472 {
473 }
474}