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