xref: /reactos/base/applications/taskmgr/graph.c (revision 016acd17)
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
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 
88         hdc = BeginPaint(hWnd, &ps);
89 
90         WindowId = GetWindowLongPtrW(hWnd, GWLP_ID);
91 
92         switch (WindowId)
93         {
94         case IDC_CPU_USAGE_GRAPH:
95             Graph_DrawCpuUsageGraph(hdc, hWnd);
96             break;
97         case IDC_MEM_USAGE_GRAPH:
98             Graph_DrawMemUsageGraph(hdc, hWnd);
99             break;
100         case IDC_MEM_USAGE_HISTORY_GRAPH:
101             Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
102             break;
103         }
104 
105         EndPaint(hWnd, &ps);
106 
107         return 0;
108 
109     }
110 
111     /*
112      * We pass on all non-handled messages
113      */
114     return CallWindowProcW(OldGraphWndProc, hWnd, message, wParam, lParam);
115 }
116 
117 void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
118 {
119     RECT      rcClient;
120     RECT      rcBarLeft;
121     RECT      rcBarRight;
122     RECT      rcText;
123     COLORREF  crPrevForeground;
124     WCHAR     Text[260];
125     HFONT     hOldFont;
126     ULONG     CpuUsage;
127     ULONG     CpuKernelUsage;
128     int       nBars;
129     int       nBarsUsed;
130 /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
131     int       nBarsUsedKernel;
132 /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
133     int       nBarsFree;
134 /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
135     int       i;
136 
137     /*
138      * Get the client area rectangle
139      */
140     GetClientRect(hWnd, &rcClient);
141 
142     /*
143      * Fill it with blackness
144      */
145     FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
146 
147     /*
148      * Get the CPU usage
149      */
150     CpuUsage = PerfDataGetProcessorUsage();
151 
152     wsprintfW(Text, L"%d%%", (int)CpuUsage);
153 
154     /*
155      * Draw the font text onto the graph
156      */
157     rcText = rcClient;
158     InflateRect(&rcText, -2, -2);
159     crPrevForeground = SetTextColor(hDC, RGB(0, 255, 0));
160     hOldFont = SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
161     DrawTextW(hDC, Text, -1, &rcText, DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE);
162     SelectObject(hDC, hOldFont);
163     SetTextColor(hDC, crPrevForeground);
164 
165     /*
166      * Now we have to draw the graph
167      * So first find out how many bars we can fit
168      */
169     nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
170     nBarsUsed = (nBars * CpuUsage) / 100;
171     if ((CpuUsage) && (nBarsUsed == 0))
172     {
173         nBarsUsed = 1;
174     }
175     nBarsFree = nBars - (nlastBarsUsed>nBarsUsed ? nlastBarsUsed : nBarsUsed);
176 
177     if (TaskManagerSettings.ShowKernelTimes)
178     {
179         CpuKernelUsage = PerfDataGetProcessorSystemUsage();
180         nBarsUsedKernel = (nBars * CpuKernelUsage) / 100;
181     }
182     else
183     {
184         nBarsUsedKernel = 0;
185     }
186 
187     /*
188      * Now draw the bar graph
189      */
190     rcBarLeft.left =  ((rcClient.right - rcClient.left) - 33) / 2;
191     rcBarLeft.right =  rcBarLeft.left + 16;
192     rcBarRight.left = rcBarLeft.left + 17;
193     rcBarRight.right = rcBarLeft.right + 17;
194     rcBarLeft.top = rcBarRight.top = 5;
195     rcBarLeft.bottom = rcBarRight.bottom = 7;
196 
197     if (nBarsUsed < 0)     nBarsUsed = 0;
198     if (nBarsUsed > nBars) nBarsUsed = nBars;
199 
200     if (nBarsFree < 0)     nBarsFree = 0;
201     if (nBarsFree > nBars) nBarsFree = nBars;
202 
203     if (nBarsUsedKernel < 0)     nBarsUsedKernel = 0;
204     if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
205 
206     /*
207      * Draw the "free" bars
208      */
209     for (i=0; i<nBarsFree; i++)
210     {
211         FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
212         FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
213 
214         rcBarLeft.top += 3;
215         rcBarLeft.bottom += 3;
216 
217         rcBarRight.top += 3;
218         rcBarRight.bottom += 3;
219     }
220 
221     /*
222      * Draw the last "used" bars
223      */
224     if ((nlastBarsUsed - nBarsUsed) > 0) {
225         for (i=0; i< (nlastBarsUsed - nBarsUsed); i++)
226         {
227             if (nlastBarsUsed > 5000) nlastBarsUsed = 5000;
228 
229             FillSolidRect(hDC, &rcBarLeft, MEDIUM_GREEN);
230             FillSolidRect(hDC, &rcBarRight, MEDIUM_GREEN);
231 
232             rcBarLeft.top += 3;
233             rcBarLeft.bottom += 3;
234 
235             rcBarRight.top += 3;
236             rcBarRight.bottom += 3;
237         }
238     }
239     nlastBarsUsed = nBarsUsed;
240     /*
241      * Draw the "used" bars
242      */
243     for (i=0; i<nBarsUsed; i++)
244     {
245         if (nBarsUsed > 5000) nBarsUsed = 5000;
246 
247         FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
248         FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
249 
250         rcBarLeft.top += 3;
251         rcBarLeft.bottom += 3;
252 
253         rcBarRight.top += 3;
254         rcBarRight.bottom += 3;
255     }
256 
257     /*
258      * Draw the "used" kernel bars
259      */
260 
261     rcBarLeft.top -=3;
262     rcBarLeft.bottom -=3;
263 
264     rcBarRight.top -=3;
265     rcBarRight.bottom -=3;
266 
267     for (i=0; i<nBarsUsedKernel; i++)
268     {
269 
270         FillSolidRect(hDC, &rcBarLeft, RED);
271         FillSolidRect(hDC, &rcBarRight, RED);
272 
273         rcBarLeft.top -=3;
274         rcBarLeft.bottom -=3;
275 
276         rcBarRight.top -=3;
277         rcBarRight.bottom -=3;
278 
279     }
280 
281     SelectObject(hDC, hOldFont);
282 }
283 
284 void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
285 {
286     RECT       rcClient;
287     RECT       rcBarLeft;
288     RECT       rcBarRight;
289     RECT       rcText;
290     COLORREF   crPrevForeground;
291     WCHAR      Text[260];
292     HFONT      hOldFont;
293     ULONGLONG  CommitChargeTotal;
294     ULONGLONG  CommitChargeLimit;
295     int        nBars;
296     int        nBarsUsed = 0;
297 /* Bottom bars that are "used", i.e. are bright green, representing used memory */
298     int        nBarsFree;
299 /* Top bars that are "unused", i.e. are dark green, representing free memory */
300     int        i;
301 
302     /*
303      * Get the client area rectangle
304      */
305     GetClientRect(hWnd, &rcClient);
306 
307     /*
308      * Fill it with blackness
309      */
310     FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
311 
312     /*
313      * Get the memory usage
314      */
315     CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
316     CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
317 
318     if (CommitChargeTotal > 1024)
319         wsprintfW(Text, L"%d MB", (int)(CommitChargeTotal / 1024));
320     else
321         wsprintfW(Text, L"%d K", (int)CommitChargeTotal);
322     /*
323      * Draw the font text onto the graph
324      */
325     rcText = rcClient;
326     InflateRect(&rcText, -2, -2);
327     crPrevForeground = SetTextColor(hDC, RGB(0, 255, 0));
328     hOldFont = SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
329     DrawTextW(hDC, Text, -1, &rcText, DT_BOTTOM | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE);
330     SelectObject(hDC, hOldFont);
331     SetTextColor(hDC, crPrevForeground);
332 
333     /*
334      * Now we have to draw the graph
335      * So first find out how many bars we can fit
336      */
337     nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
338         if (CommitChargeLimit)
339     nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
340     nBarsFree = nBars - nBarsUsed;
341 
342     if (nBarsUsed < 0)     nBarsUsed = 0;
343     if (nBarsUsed > nBars) nBarsUsed = nBars;
344 
345     if (nBarsFree < 0)     nBarsFree = 0;
346     if (nBarsFree > nBars) nBarsFree = nBars;
347 
348     /*
349      * Now draw the bar graph
350      */
351     rcBarLeft.left =  ((rcClient.right - rcClient.left) - 33) / 2;
352     rcBarLeft.right =  rcBarLeft.left + 16;
353     rcBarRight.left = rcBarLeft.left + 17;
354     rcBarRight.right = rcBarLeft.right + 17;
355     rcBarLeft.top = rcBarRight.top = 5;
356     rcBarLeft.bottom = rcBarRight.bottom = 7;
357 
358     /*
359      * Draw the "free" bars
360      */
361     for (i=0; i<nBarsFree; i++)
362     {
363         FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
364         FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
365 
366         rcBarLeft.top += 3;
367         rcBarLeft.bottom += 3;
368 
369         rcBarRight.top += 3;
370         rcBarRight.bottom += 3;
371     }
372 
373     /*
374      * Draw the "used" bars
375      */
376     for (i=0; i<nBarsUsed; i++)
377     {
378         FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
379         FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
380 
381         rcBarLeft.top += 3;
382         rcBarLeft.bottom += 3;
383 
384         rcBarRight.top += 3;
385         rcBarRight.bottom += 3;
386     }
387 
388     SelectObject(hDC, hOldFont);
389 }
390 
391 void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
392 {
393     RECT        rcClient;
394     //ULONGLONG   CommitChargeLimit;
395     int         i;
396     static int  offset = 0;
397 
398     if (offset++ >= 10)
399         offset = 0;
400 
401     /*
402      * Get the client area rectangle
403      */
404     GetClientRect(hWnd, &rcClient);
405 
406     /*
407      * Fill it with blackness
408      */
409     FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
410 
411     /*
412      * Get the memory usage
413      */
414     //CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
415 
416     /*
417      * Draw the graph background
418      *
419      * Draw the horizontal bars
420      */
421     for (i=0; i<rcClient.bottom; i++)
422     {
423         if ((i % 11) == 0)
424         {
425             /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN);  */
426         }
427     }
428     /*
429      * Draw the vertical bars
430      */
431     for (i=11; i<rcClient.right + offset; i++)
432     {
433         if ((i % 11) == 0)
434         {
435             /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN);  */
436         }
437     }
438 
439     /*
440      * Draw the memory usage
441      */
442     for (i=rcClient.right; i>=0; i--)
443     {
444     }
445 }
446