push 514b285b0c98f6a7a84c63e51c3091a87ae6d177
[wine/hacks.git] / programs / taskmgr / graph.c
blob821100c2f3df5d1430805821266a9d23b318e482
1 /*
2 * ReactOS Task Manager
4 * graph.c
6 * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
7 * Copyright (C) 2008 Vladimir Pankratov
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
25 #include <windows.h>
26 #include <commctrl.h>
27 #include <stdlib.h>
28 #include <malloc.h>
29 #include <memory.h>
30 #include <stdio.h>
31 #include <winnt.h>
33 #include "wine/unicode.h"
34 #include "taskmgr.h"
35 #include "perfdata.h"
37 #define BRIGHT_GREEN RGB(0, 255, 0)
38 #define DARK_GREEN RGB(0, 130, 0)
39 #define RED RGB(255, 0, 0)
42 WNDPROC OldGraphWndProc;
44 static void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
46 RECT rcClient;
47 RECT rcBarLeft;
48 RECT rcBarRight;
49 WCHAR Text[256];
50 ULONG CpuUsage;
51 ULONG CpuKernelUsage;
52 int nBars;
53 int nBarsUsed;
54 /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
55 int nBarsUsedKernel;
56 /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
57 int nBarsFree;
58 /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
59 int i;
61 static const WCHAR wszFormatI[] = {'%','d','%','%',0};
62 static const WCHAR wszFormatII[] = {' ',' ','%','d','%','%',0};
63 static const WCHAR wszFormatIII[] = {' ','%','d','%','%',0};
66 * Get the client area rectangle
68 GetClientRect(hWnd, &rcClient);
71 * Fill it with blackness
73 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
76 * Get the CPU usage
78 CpuUsage = PerfDataGetProcessorUsage();
79 CpuKernelUsage = PerfDataGetProcessorSystemUsage();
82 * Check and see how many digits it will take
83 * so we get the indentation right every time.
85 if (CpuUsage == 100)
87 sprintfW(Text, wszFormatI, (int)CpuUsage);
89 else if (CpuUsage < 10)
91 sprintfW(Text, wszFormatII, (int)CpuUsage);
93 else
95 sprintfW(Text, wszFormatIII, (int)CpuUsage);
99 * Draw the font text onto the graph
100 * The bottom 20 pixels are reserved for the text
102 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - 32) / 2, rcClient.bottom - 11 - 5);
105 * Now we have to draw the graph
106 * So first find out how many bars we can fit
108 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
109 nBarsUsed = (nBars * CpuUsage) / 100;
110 if ((CpuUsage) && (nBarsUsed == 0))
112 nBarsUsed = 1;
114 nBarsFree = nBars - nBarsUsed;
115 if (TaskManagerSettings.ShowKernelTimes)
117 nBarsUsedKernel = ((nBars * 2) * CpuKernelUsage) / 100;
118 nBarsUsed -= (nBarsUsedKernel / 2);
120 else
122 nBarsUsedKernel = 0;
126 * Now draw the bar graph
128 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
129 rcBarLeft.right = rcBarLeft.left + 16;
130 rcBarRight.left = rcBarLeft.left + 17;
131 rcBarRight.right = rcBarLeft.right + 17;
132 rcBarLeft.top = rcBarRight.top = 5;
133 rcBarLeft.bottom = rcBarRight.bottom = 7;
135 if (nBarsUsed < 0) nBarsUsed = 0;
136 if (nBarsUsed > nBars) nBarsUsed = nBars;
138 if (nBarsFree < 0) nBarsFree = 0;
139 if (nBarsFree > nBars) nBarsFree = nBars;
141 if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
142 if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
145 * Draw the "free" bars
147 for (i=0; i<nBarsFree; i++)
149 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
150 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
152 rcBarLeft.top += 3;
153 rcBarLeft.bottom += 3;
155 rcBarRight.top += 3;
156 rcBarRight.bottom += 3;
160 * Draw the "used" bars
162 for (i=0; i<nBarsUsed; i++)
164 if (nBarsUsed > 5000) nBarsUsed = 5000;
166 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
167 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
169 rcBarLeft.top += 3;
170 rcBarLeft.bottom += 3;
172 rcBarRight.top += 3;
173 rcBarRight.bottom += 3;
177 * Draw the "used" kernel bars
179 rcBarLeft.bottom--;
180 rcBarRight.bottom--;
181 if (nBarsUsedKernel && nBarsUsedKernel % 2)
183 rcBarLeft.top -= 2;
184 rcBarLeft.bottom -= 2;
186 rcBarRight.top -= 2;
187 rcBarRight.bottom -= 2;
189 FillSolidRect(hDC, &rcBarLeft, RED);
190 FillSolidRect(hDC, &rcBarRight, RED);
192 rcBarLeft.top += 2;
193 rcBarLeft.bottom += 2;
195 rcBarRight.top += 2;
196 rcBarRight.bottom += 2;
198 nBarsUsedKernel--;
200 for (i=0; i<nBarsUsedKernel; i++)
202 if (nBarsUsedKernel > 5000) nBarsUsedKernel = 5000;
204 FillSolidRect(hDC, &rcBarLeft, RED);
205 FillSolidRect(hDC, &rcBarRight, RED);
207 rcBarLeft.top++;
208 rcBarLeft.bottom++;
210 rcBarRight.top++;
211 rcBarRight.bottom++;
213 if (i % 2)
215 rcBarLeft.top++;
216 rcBarLeft.bottom++;
218 rcBarRight.top++;
219 rcBarRight.bottom++;
224 static void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
226 RECT rcClient;
227 RECT rcBarLeft;
228 RECT rcBarRight;
229 WCHAR Text[256];
230 ULONGLONG CommitChargeTotal;
231 ULONGLONG CommitChargeLimit;
232 int nBars;
233 int nBarsUsed = 0;
234 /* Bottom bars that are "used", i.e. are bright green, representing used memory */
235 int nBarsFree;
236 /* Top bars that are "unused", i.e. are dark green, representing free memory */
237 int i;
239 static const WCHAR wszFormat[] = {'%','d','K',0};
242 * Get the client area rectangle
244 GetClientRect(hWnd, &rcClient);
247 * Fill it with blackness
249 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
252 * Get the memory usage
254 CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
255 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
257 sprintfW(Text, wszFormat, (int)CommitChargeTotal);
260 * Draw the font text onto the graph
261 * The bottom 20 pixels are reserved for the text
263 Font_DrawText(hDC, Text, ((rcClient.right - rcClient.left) - (strlenW(Text) * 8)) / 2, rcClient.bottom - 11 - 5);
266 * Now we have to draw the graph
267 * So first find out how many bars we can fit
269 nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
270 if (CommitChargeLimit)
271 nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
272 nBarsFree = nBars - nBarsUsed;
274 if (nBarsUsed < 0) nBarsUsed = 0;
275 if (nBarsUsed > nBars) nBarsUsed = nBars;
277 if (nBarsFree < 0) nBarsFree = 0;
278 if (nBarsFree > nBars) nBarsFree = nBars;
281 * Now draw the bar graph
283 rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
284 rcBarLeft.right = rcBarLeft.left + 16;
285 rcBarRight.left = rcBarLeft.left + 17;
286 rcBarRight.right = rcBarLeft.right + 17;
287 rcBarLeft.top = rcBarRight.top = 5;
288 rcBarLeft.bottom = rcBarRight.bottom = 7;
291 * Draw the "free" bars
293 for (i=0; i<nBarsFree; i++)
295 FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
296 FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
298 rcBarLeft.top += 3;
299 rcBarLeft.bottom += 3;
301 rcBarRight.top += 3;
302 rcBarRight.bottom += 3;
306 * Draw the "used" bars
308 for (i=0; i<nBarsUsed; i++)
310 FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
311 FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
313 rcBarLeft.top += 3;
314 rcBarLeft.bottom += 3;
316 rcBarRight.top += 3;
317 rcBarRight.bottom += 3;
321 static void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
323 RECT rcClient;
324 ULONGLONG CommitChargeLimit;
325 int i;
326 static int offset = 0;
328 if (offset++ >= 10)
329 offset = 0;
332 * Get the client area rectangle
334 GetClientRect(hWnd, &rcClient);
337 * Fill it with blackness
339 FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
342 * Get the memory usage
344 CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
347 * Draw the graph background
349 * Draw the horizontal bars
351 for (i=0; i<rcClient.bottom; i++)
353 if ((i % 11) == 0)
355 /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN); */
359 * Draw the vertical bars
361 for (i=11; i<rcClient.right + offset; i++)
363 if ((i % 11) == 0)
365 /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN); */
370 * Draw the memory usage
372 for (i=rcClient.right; i>=0; i--)
377 INT_PTR CALLBACK
378 Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
380 HDC hdc;
381 PAINTSTRUCT ps;
382 LONG WindowId;
384 switch (message)
386 case WM_ERASEBKGND:
387 return TRUE;
390 * Filter out mouse & keyboard messages
392 /* case WM_APPCOMMAND: */
393 case WM_CAPTURECHANGED:
394 case WM_LBUTTONDBLCLK:
395 case WM_LBUTTONDOWN:
396 case WM_LBUTTONUP:
397 case WM_MBUTTONDBLCLK:
398 case WM_MBUTTONDOWN:
399 case WM_MBUTTONUP:
400 case WM_MOUSEACTIVATE:
401 case WM_MOUSEHOVER:
402 case WM_MOUSELEAVE:
403 case WM_MOUSEMOVE:
404 /* case WM_MOUSEWHEEL: */
405 case WM_NCHITTEST:
406 case WM_NCLBUTTONDBLCLK:
407 case WM_NCLBUTTONDOWN:
408 case WM_NCLBUTTONUP:
409 case WM_NCMBUTTONDBLCLK:
410 case WM_NCMBUTTONDOWN:
411 case WM_NCMBUTTONUP:
412 /* case WM_NCMOUSEHOVER: */
413 /* case WM_NCMOUSELEAVE: */
414 case WM_NCMOUSEMOVE:
415 case WM_NCRBUTTONDBLCLK:
416 case WM_NCRBUTTONDOWN:
417 case WM_NCRBUTTONUP:
418 /* case WM_NCXBUTTONDBLCLK: */
419 /* case WM_NCXBUTTONDOWN: */
420 /* case WM_NCXBUTTONUP: */
421 case WM_RBUTTONDBLCLK:
422 case WM_RBUTTONDOWN:
423 case WM_RBUTTONUP:
424 /* case WM_XBUTTONDBLCLK: */
425 /* case WM_XBUTTONDOWN: */
426 /* case WM_XBUTTONUP: */
427 case WM_ACTIVATE:
428 case WM_CHAR:
429 case WM_DEADCHAR:
430 case WM_GETHOTKEY:
431 case WM_HOTKEY:
432 case WM_KEYDOWN:
433 case WM_KEYUP:
434 case WM_KILLFOCUS:
435 case WM_SETFOCUS:
436 case WM_SETHOTKEY:
437 case WM_SYSCHAR:
438 case WM_SYSDEADCHAR:
439 case WM_SYSKEYDOWN:
440 case WM_SYSKEYUP:
442 case WM_NCCALCSIZE:
443 return 0;
445 case WM_PAINT:
447 hdc = BeginPaint(hWnd, &ps);
449 WindowId = GetWindowLongPtr(hWnd, GWLP_ID);
451 switch (WindowId)
453 case IDC_CPU_USAGE_GRAPH:
454 Graph_DrawCpuUsageGraph(hdc, hWnd);
455 break;
456 case IDC_MEM_USAGE_GRAPH:
457 Graph_DrawMemUsageGraph(hdc, hWnd);
458 break;
459 case IDC_MEM_USAGE_HISTORY_GRAPH:
460 Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
461 break;
464 EndPaint(hWnd, &ps);
466 return 0;
471 * We pass on all non-handled messages
473 return CallWindowProc((WNDPROC)OldGraphWndProc, hWnd, message, wParam, lParam);