Moved taskmgr from rosapps to reactos module for 0.2 release.
[reactos.git] / rosapps / taskmgr / graph.c
1 /*
2 * ReactOS Task Manager
3 *
4 * graph.cpp
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 "graph.h"
35 #include "font.h"
36 #include "perfdata.h"
37
38
39 LONG OldGraphWndProc;
40
41 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd);
42 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd);
43 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd);
44
45 LRESULT CALLBACK Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
46 {
47 HDC hdc;
48 PAINTSTRUCT ps;
49 LONG WindowId;
50
51 switch (message)
52 {
53 case WM_ERASEBKGND:
54 return TRUE;
55
56 /*
57 * Filter out mouse & keyboard messages
58 */
59 /* case WM_APPCOMMAND: */
60 case WM_CAPTURECHANGED:
61 case WM_LBUTTONDBLCLK:
62 case WM_LBUTTONDOWN:
63 case WM_LBUTTONUP:
64 case WM_MBUTTONDBLCLK:
65 case WM_MBUTTONDOWN:
66 case WM_MBUTTONUP:
67 case WM_MOUSEACTIVATE:
68 case WM_MOUSEHOVER:
69 case WM_MOUSELEAVE:
70 case WM_MOUSEMOVE:
71 /* case WM_MOUSEWHEEL: */
72 case WM_NCHITTEST:
73 case WM_NCLBUTTONDBLCLK:
74 case WM_NCLBUTTONDOWN:
75 case WM_NCLBUTTONUP:
76 case WM_NCMBUTTONDBLCLK:
77 case WM_NCMBUTTONDOWN:
78 case WM_NCMBUTTONUP:
79 /* case WM_NCMOUSEHOVER: */
80 /* case WM_NCMOUSELEAVE: */
81 case WM_NCMOUSEMOVE:
82 case WM_NCRBUTTONDBLCLK:
83 case WM_NCRBUTTONDOWN:
84 case WM_NCRBUTTONUP:
85 /* case WM_NCXBUTTONDBLCLK: */
86 /* case WM_NCXBUTTONDOWN: */
87 /* case WM_NCXBUTTONUP: */
88 case WM_RBUTTONDBLCLK:
89 case WM_RBUTTONDOWN:
90 case WM_RBUTTONUP:
91 /* case WM_XBUTTONDBLCLK: */
92 /* case WM_XBUTTONDOWN: */
93 /* case WM_XBUTTONUP: */
94 case WM_ACTIVATE:
95 case WM_CHAR:
96 case WM_DEADCHAR:
97 case WM_GETHOTKEY:
98 case WM_HOTKEY:
99 case WM_KEYDOWN:
100 case WM_KEYUP:
101 case WM_KILLFOCUS:
102 case WM_SETFOCUS:
103 case WM_SETHOTKEY:
104 case WM_SYSCHAR:
105 case WM_SYSDEADCHAR:
106 case WM_SYSKEYDOWN:
107 case WM_SYSKEYUP:
108
109 case WM_NCCALCSIZE:
110 return 0;
111
112 case WM_PAINT:
113
114 hdc = BeginPaint(hWnd, &ps);
115
116 WindowId = GetWindowLong(hWnd, GWL_ID);
117
118 switch (WindowId)
119 {
120 case IDC_CPU_USAGE_GRAPH:
121 Graph_DrawCpuUsageGraph(hdc, hWnd);
122 break;
123 case IDC_MEM_USAGE_GRAPH:
124 Graph_DrawMemUsageGraph(hdc, hWnd);
125 break;
126 case IDC_MEM_USAGE_HISTORY_GRAPH:
127 Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
128 break;
129 }
130
131 EndPaint(hWnd, &ps);
132
133 return 0;
134
135 }
136
137 /*
138 * We pass on all non-handled messages
139 */
140 return CallWindowProc((WNDPROC)OldGraphWndProc, hWnd, message, wParam, lParam);
141 }
142
143 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
144 {
145 RECT rcClient;
146 RECT rcBarLeft;
147 RECT rcBarRight;
148 TCHAR Text[260];
149 ULONG CpuUsage;
150 ULONG CpuKernelUsage;
151 int nBars;
152 int nBarsUsed;
153 /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
154 int nBarsUsedKernel;
155 /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
156 int nBarsFree;
157 /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
158 int i;
159
160 /*
161 * Get the client area rectangle
162 */
163 GetClientRect(hWnd, &rcClient);
164
165 /*
166 * Fill it with blackness
167 */
168 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
169
170 /*
171 * Get the CPU usage
172 */
173 CpuUsage = PerfDataGetProcessorUsage();
174 CpuKernelUsage = PerfDataGetProcessorSystemUsage();
175 if (CpuUsage < 0) CpuUsage = 0;
176 if (CpuUsage > 100) CpuUsage = 100;
177 if (CpuKernelUsage < 0) CpuKernelUsage = 0;
178 if (CpuKernelUsage > 100) CpuKernelUsage = 100;
179
180 /*
181 * Check and see how many digits it will take
182 * so we get the indentation right every time.
183 */
184 if (CpuUsage == 100)
185 {
186 _stprintf(Text, _T("%d%%"), (int)CpuUsage);
187 }
188 else if (CpuUsage < 10)
189 {
190 _stprintf(Text, _T(" %d%%"), (int)CpuUsage);
191 }
192 else
193 {
194 _stprintf(Text, _T(" %d%%"), (int)CpuUsage);
195 }
196
197 /*
198 * Draw the font text onto the graph
199 * The bottom 20 pixels are reserved for the text
200 */
201 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - 32) / 2, rcClient.bottom - 11 - 5);
202
203 /*
204 * Now we have to draw the graph
205 * So first find out how many bars we can fit
206 */
207 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
208 nBarsUsed = (nBars * CpuUsage) / 100;
209 if ((CpuUsage) && (nBarsUsed == 0))
210 {
211 nBarsUsed = 1;
212 }
213 nBarsFree = nBars - nBarsUsed;
214 if (TaskManagerSettings.ShowKernelTimes)
215 {
216 nBarsUsedKernel = ((nBars * 2) * CpuKernelUsage) / 100;
217 nBarsUsed -= (nBarsUsedKernel / 2);
218 }
219 else
220 {
221 nBarsUsedKernel = 0;
222 }
223
224 /*
225 * Now draw the bar graph
226 */
227 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
228 rcBarLeft.right = rcBarLeft.left + 16;
229 rcBarRight.left = rcBarLeft.left + 17;
230 rcBarRight.right = rcBarLeft.right + 17;
231 rcBarLeft.top = rcBarRight.top = 5;
232 rcBarLeft.bottom = rcBarRight.bottom = 7;
233
234 if (nBarsUsed < 0) nBarsUsed = 0;
235 if (nBarsUsed > nBars) nBarsUsed = nBars;
236
237 if (nBarsFree < 0) nBarsFree = 0;
238 if (nBarsFree > nBars) nBarsFree = nBars;
239
240 if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
241 if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
242
243 /*
244 * Draw the "free" bars
245 */
246 for (i=0; i<nBarsFree; i++)
247 {
248 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
249 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
250
251 rcBarLeft.top += 3;
252 rcBarLeft.bottom += 3;
253
254 rcBarRight.top += 3;
255 rcBarRight.bottom += 3;
256 }
257
258 /*
259 * Draw the "used" bars
260 */
261 for (i=0; i<nBarsUsed; i++)
262 {
263 if (nBarsUsed > 5000) nBarsUsed = 5000;
264
265 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
266 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
267
268 rcBarLeft.top += 3;
269 rcBarLeft.bottom += 3;
270
271 rcBarRight.top += 3;
272 rcBarRight.bottom += 3;
273 }
274
275 /*
276 * Draw the "used" kernel bars
277 */
278 rcBarLeft.bottom--;
279 rcBarRight.bottom--;
280 if (nBarsUsedKernel && nBarsUsedKernel % 2)
281 {
282 rcBarLeft.top -= 2;
283 rcBarLeft.bottom -= 2;
284
285 rcBarRight.top -= 2;
286 rcBarRight.bottom -= 2;
287
288 FillSolidRect(hDC, &rcBarLeft, RED);
289 FillSolidRect(hDC, &rcBarRight, RED);
290
291 rcBarLeft.top += 2;
292 rcBarLeft.bottom += 2;
293
294 rcBarRight.top += 2;
295 rcBarRight.bottom += 2;
296
297 nBarsUsedKernel--;
298 }
299 for (i=0; i<nBarsUsedKernel; i++)
300 {
301 if (nBarsUsedKernel > 5000) nBarsUsedKernel = 5000;
302
303 FillSolidRect(hDC, &rcBarLeft, RED);
304 FillSolidRect(hDC, &rcBarRight, RED);
305
306 rcBarLeft.top++;
307 rcBarLeft.bottom++;
308
309 rcBarRight.top++;
310 rcBarRight.bottom++;
311
312 if (i % 2)
313 {
314 rcBarLeft.top++;
315 rcBarLeft.bottom++;
316
317 rcBarRight.top++;
318 rcBarRight.bottom++;
319 }
320 }
321 }
322
323 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
324 {
325 RECT rcClient;
326 RECT rcBarLeft;
327 RECT rcBarRight;
328 TCHAR Text[260];
329 ULONGLONG CommitChargeTotal;
330 ULONGLONG CommitChargeLimit;
331 int nBars;
332 int nBarsUsed = 0;
333 /* Bottom bars that are "used", i.e. are bright green, representing used memory */
334 int nBarsFree;
335 /* 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 _stprintf(Text, _T("%dK"), (int)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) - (_tcslen(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 if (CommitChargeLimit)
368 nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
369 nBarsFree = nBars - nBarsUsed;
370
371 if (nBarsUsed < 0) nBarsUsed = 0;
372 if (nBarsUsed > nBars) nBarsUsed = nBars;
373
374 if (nBarsFree < 0) nBarsFree = 0;
375 if (nBarsFree > nBars) nBarsFree = nBars;
376
377 /*
378 * Now draw the bar graph
379 */
380 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
381 rcBarLeft.right = rcBarLeft.left + 16;
382 rcBarRight.left = rcBarLeft.left + 17;
383 rcBarRight.right = rcBarLeft.right + 17;
384 rcBarLeft.top = rcBarRight.top = 5;
385 rcBarLeft.bottom = rcBarRight.bottom = 7;
386
387 /*
388 * Draw the "free" bars
389 */
390 for (i=0; i<nBarsFree; i++)
391 {
392 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
393 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
394
395 rcBarLeft.top += 3;
396 rcBarLeft.bottom += 3;
397
398 rcBarRight.top += 3;
399 rcBarRight.bottom += 3;
400 }
401
402 /*
403 * Draw the "used" bars
404 */
405 for (i=0; i<nBarsUsed; i++)
406 {
407 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
408 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
409
410 rcBarLeft.top += 3;
411 rcBarLeft.bottom += 3;
412
413 rcBarRight.top += 3;
414 rcBarRight.bottom += 3;
415 }
416 }
417
418 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
419 {
420 RECT rcClient;
421 ULONGLONG CommitChargeLimit;
422 int i;
423 static int offset = 0;
424
425 if (offset++ >= 10)
426 offset = 0;
427
428 /*
429 * Get the client area rectangle
430 */
431 GetClientRect(hWnd, &rcClient);
432
433 /*
434 * Fill it with blackness
435 */
436 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
437
438 /*
439 * Get the memory usage
440 */
441 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
442
443 /*
444 * Draw the graph background
445 *
446 * Draw the horizontal bars
447 */
448 for (i=0; i<rcClient.bottom; i++)
449 {
450 if ((i % 11) == 0)
451 {
452 /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN); */
453 }
454 }
455 /*
456 * Draw the vertical bars
457 */
458 for (i=11; i<rcClient.right + offset; i++)
459 {
460 if ((i % 11) == 0)
461 {
462 /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN); */
463 }
464 }
465
466 /*
467 * Draw the memory usage
468 */
469 for (i=rcClient.right; i>=0; i--)
470 {
471 }
472 }