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