3403b2282485811814974416b4187f535f85b8db
[reactos.git] / reactos / subsys / system / 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 #include "precomp.h"
24 #include <commctrl.h>
25 #include <stdlib.h>
26 #include <malloc.h>
27 #include <memory.h>
28 #include <tchar.h>
29 #include <stdio.h>
30 #include <winnt.h>
31
32 #include "graph.h"
33 #include "font.h"
34 #include "perfdata.h"
35
36
37 LONG OldGraphWndProc;
38
39 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd);
40 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd);
41 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd);
42
43 LRESULT CALLBACK Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
44 {
45 HDC hdc;
46 PAINTSTRUCT ps;
47 LONG WindowId;
48
49 switch (message)
50 {
51 case WM_ERASEBKGND:
52 return TRUE;
53
54 /*
55 * Filter out mouse & keyboard messages
56 */
57 /* case WM_APPCOMMAND: */
58 case WM_CAPTURECHANGED:
59 case WM_LBUTTONDBLCLK:
60 case WM_LBUTTONDOWN:
61 case WM_LBUTTONUP:
62 case WM_MBUTTONDBLCLK:
63 case WM_MBUTTONDOWN:
64 case WM_MBUTTONUP:
65 case WM_MOUSEACTIVATE:
66 case WM_MOUSEHOVER:
67 case WM_MOUSELEAVE:
68 case WM_MOUSEMOVE:
69 /* case WM_MOUSEWHEEL: */
70 case WM_NCHITTEST:
71 case WM_NCLBUTTONDBLCLK:
72 case WM_NCLBUTTONDOWN:
73 case WM_NCLBUTTONUP:
74 case WM_NCMBUTTONDBLCLK:
75 case WM_NCMBUTTONDOWN:
76 case WM_NCMBUTTONUP:
77 /* case WM_NCMOUSEHOVER: */
78 /* case WM_NCMOUSELEAVE: */
79 case WM_NCMOUSEMOVE:
80 case WM_NCRBUTTONDBLCLK:
81 case WM_NCRBUTTONDOWN:
82 case WM_NCRBUTTONUP:
83 /* case WM_NCXBUTTONDBLCLK: */
84 /* case WM_NCXBUTTONDOWN: */
85 /* case WM_NCXBUTTONUP: */
86 case WM_RBUTTONDBLCLK:
87 case WM_RBUTTONDOWN:
88 case WM_RBUTTONUP:
89 /* case WM_XBUTTONDBLCLK: */
90 /* case WM_XBUTTONDOWN: */
91 /* case WM_XBUTTONUP: */
92 case WM_ACTIVATE:
93 case WM_CHAR:
94 case WM_DEADCHAR:
95 case WM_GETHOTKEY:
96 case WM_HOTKEY:
97 case WM_KEYDOWN:
98 case WM_KEYUP:
99 case WM_KILLFOCUS:
100 case WM_SETFOCUS:
101 case WM_SETHOTKEY:
102 case WM_SYSCHAR:
103 case WM_SYSDEADCHAR:
104 case WM_SYSKEYDOWN:
105 case WM_SYSKEYUP:
106
107 case WM_NCCALCSIZE:
108 return 0;
109
110 case WM_PAINT:
111
112 hdc = BeginPaint(hWnd, &ps);
113
114 WindowId = GetWindowLong(hWnd, GWL_ID);
115
116 switch (WindowId)
117 {
118 case IDC_CPU_USAGE_GRAPH:
119 Graph_DrawCpuUsageGraph(hdc, hWnd);
120 break;
121 case IDC_MEM_USAGE_GRAPH:
122 Graph_DrawMemUsageGraph(hdc, hWnd);
123 break;
124 case IDC_MEM_USAGE_HISTORY_GRAPH:
125 Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
126 break;
127 }
128
129 EndPaint(hWnd, &ps);
130
131 return 0;
132
133 }
134
135 /*
136 * We pass on all non-handled messages
137 */
138 return CallWindowProc((WNDPROC)OldGraphWndProc, hWnd, message, wParam, lParam);
139 }
140
141 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
142 {
143 RECT rcClient;
144 RECT rcBarLeft;
145 RECT rcBarRight;
146 TCHAR Text[260];
147 ULONG CpuUsage;
148 ULONG CpuKernelUsage;
149 int nBars;
150 int nBarsUsed;
151 /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
152 int nBarsUsedKernel;
153 /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
154 int nBarsFree;
155 /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
156 int i;
157
158 /*
159 * Get the client area rectangle
160 */
161 GetClientRect(hWnd, &rcClient);
162
163 /*
164 * Fill it with blackness
165 */
166 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
167
168 /*
169 * Get the CPU usage
170 */
171 CpuUsage = PerfDataGetProcessorUsage();
172 CpuKernelUsage = PerfDataGetProcessorSystemUsage();
173 if (CpuUsage < 0) CpuUsage = 0;
174 if (CpuUsage > 100) CpuUsage = 100;
175 if (CpuKernelUsage < 0) CpuKernelUsage = 0;
176 if (CpuKernelUsage > 100) CpuKernelUsage = 100;
177
178 /*
179 * Check and see how many digits it will take
180 * so we get the indentation right every time.
181 */
182 if (CpuUsage == 100)
183 {
184 _stprintf(Text, _T("%d%%"), (int)CpuUsage);
185 }
186 else if (CpuUsage < 10)
187 {
188 _stprintf(Text, _T(" %d%%"), (int)CpuUsage);
189 }
190 else
191 {
192 _stprintf(Text, _T(" %d%%"), (int)CpuUsage);
193 }
194
195 /*
196 * Draw the font text onto the graph
197 * The bottom 20 pixels are reserved for the text
198 */
199 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - 32) / 2, rcClient.bottom - 11 - 5);
200
201 /*
202 * Now we have to draw the graph
203 * So first find out how many bars we can fit
204 */
205 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
206 nBarsUsed = (nBars * CpuUsage) / 100;
207 if ((CpuUsage) && (nBarsUsed == 0))
208 {
209 nBarsUsed = 1;
210 }
211 nBarsFree = nBars - nBarsUsed;
212 if (TaskManagerSettings.ShowKernelTimes)
213 {
214 nBarsUsedKernel = ((nBars * 2) * CpuKernelUsage) / 100;
215 nBarsUsed -= (nBarsUsedKernel / 2);
216 }
217 else
218 {
219 nBarsUsedKernel = 0;
220 }
221
222 /*
223 * Now draw the bar graph
224 */
225 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
226 rcBarLeft.right = rcBarLeft.left + 16;
227 rcBarRight.left = rcBarLeft.left + 17;
228 rcBarRight.right = rcBarLeft.right + 17;
229 rcBarLeft.top = rcBarRight.top = 5;
230 rcBarLeft.bottom = rcBarRight.bottom = 7;
231
232 if (nBarsUsed < 0) nBarsUsed = 0;
233 if (nBarsUsed > nBars) nBarsUsed = nBars;
234
235 if (nBarsFree < 0) nBarsFree = 0;
236 if (nBarsFree > nBars) nBarsFree = nBars;
237
238 if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
239 if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
240
241 /*
242 * Draw the "free" bars
243 */
244 for (i=0; i<nBarsFree; i++)
245 {
246 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
247 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
248
249 rcBarLeft.top += 3;
250 rcBarLeft.bottom += 3;
251
252 rcBarRight.top += 3;
253 rcBarRight.bottom += 3;
254 }
255
256 /*
257 * Draw the "used" bars
258 */
259 for (i=0; i<nBarsUsed; i++)
260 {
261 if (nBarsUsed > 5000) nBarsUsed = 5000;
262
263 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
264 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
265
266 rcBarLeft.top += 3;
267 rcBarLeft.bottom += 3;
268
269 rcBarRight.top += 3;
270 rcBarRight.bottom += 3;
271 }
272
273 /*
274 * Draw the "used" kernel bars
275 */
276 rcBarLeft.bottom--;
277 rcBarRight.bottom--;
278 if (nBarsUsedKernel && nBarsUsedKernel % 2)
279 {
280 rcBarLeft.top -= 2;
281 rcBarLeft.bottom -= 2;
282
283 rcBarRight.top -= 2;
284 rcBarRight.bottom -= 2;
285
286 FillSolidRect(hDC, &rcBarLeft, RED);
287 FillSolidRect(hDC, &rcBarRight, RED);
288
289 rcBarLeft.top += 2;
290 rcBarLeft.bottom += 2;
291
292 rcBarRight.top += 2;
293 rcBarRight.bottom += 2;
294
295 nBarsUsedKernel--;
296 }
297 for (i=0; i<nBarsUsedKernel; i++)
298 {
299 if (nBarsUsedKernel > 5000) nBarsUsedKernel = 5000;
300
301 FillSolidRect(hDC, &rcBarLeft, RED);
302 FillSolidRect(hDC, &rcBarRight, RED);
303
304 rcBarLeft.top++;
305 rcBarLeft.bottom++;
306
307 rcBarRight.top++;
308 rcBarRight.bottom++;
309
310 if (i % 2)
311 {
312 rcBarLeft.top++;
313 rcBarLeft.bottom++;
314
315 rcBarRight.top++;
316 rcBarRight.bottom++;
317 }
318 }
319 }
320
321 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
322 {
323 RECT rcClient;
324 RECT rcBarLeft;
325 RECT rcBarRight;
326 TCHAR Text[260];
327 ULONGLONG CommitChargeTotal;
328 ULONGLONG CommitChargeLimit;
329 int nBars;
330 int nBarsUsed = 0;
331 /* Bottom bars that are "used", i.e. are bright green, representing used memory */
332 int nBarsFree;
333 /* Top bars that are "unused", i.e. are dark green, representing free memory */
334 int i;
335
336 /*
337 * Get the client area rectangle
338 */
339 GetClientRect(hWnd, &rcClient);
340
341 /*
342 * Fill it with blackness
343 */
344 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
345
346 /*
347 * Get the memory usage
348 */
349 CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
350 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
351
352 _stprintf(Text, _T("%dK"), (int)CommitChargeTotal);
353
354 /*
355 * Draw the font text onto the graph
356 * The bottom 20 pixels are reserved for the text
357 */
358 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - (_tcslen(Text) * 8)) / 2, rcClient.bottom - 11 - 5);
359
360 /*
361 * Now we have to draw the graph
362 * So first find out how many bars we can fit
363 */
364 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
365 if (CommitChargeLimit)
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 /* FillSolidRect2(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 /* FillSolidRect2(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 }