1 /*
2  *  ReactOS Task Manager
3  *
4  *  perfpage.c
5  *
6  *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program 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
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License along
19  *  with this program; if not, write to the Free Software Foundation, Inc.,
20  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #include "precomp.h"
24 #include <shlwapi.h>
25 
26 extern BOOL bInMenuLoop;        /* Tells us if we are in the menu loop - from taskmgr.c */
27 
28 TM_GRAPH_CONTROL PerformancePageCpuUsageHistoryGraph;
29 TM_GRAPH_CONTROL PerformancePageMemUsageHistoryGraph;
30 
31 HWND  hPerformancePage;                               /*  Performance Property Page */
32 HWND  hPerformancePageCpuUsageGraph;                  /*  CPU Usage Graph */
33 HWND  hPerformancePageMemUsageGraph;                  /*  MEM Usage Graph */
34 HWND  hPerformancePageCpuUsageHistoryGraph;           /*  CPU Usage History Graph */
35 HWND  hPerformancePageMemUsageHistoryGraph;           /*  Memory Usage History Graph */
36 HWND  hPerformancePageTotalsFrame;                    /*  Totals Frame */
37 HWND  hPerformancePageCommitChargeFrame;              /*  Commit Charge Frame */
38 HWND  hPerformancePageKernelMemoryFrame;              /*  Kernel Memory Frame */
39 HWND  hPerformancePagePhysicalMemoryFrame;            /*  Physical Memory Frame */
40 HWND  hPerformancePageCpuUsageFrame;
41 HWND  hPerformancePageMemUsageFrame;
42 HWND  hPerformancePageCpuUsageHistoryFrame;
43 HWND  hPerformancePageMemUsageHistoryFrame;
44 HWND  hPerformancePageCommitChargeTotalEdit;          /*  Commit Charge Total Edit Control */
45 HWND  hPerformancePageCommitChargeLimitEdit;          /*  Commit Charge Limit Edit Control */
46 HWND  hPerformancePageCommitChargePeakEdit;           /*  Commit Charge Peak Edit Control */
47 HWND  hPerformancePageKernelMemoryTotalEdit;          /*  Kernel Memory Total Edit Control */
48 HWND  hPerformancePageKernelMemoryPagedEdit;          /*  Kernel Memory Paged Edit Control */
49 HWND  hPerformancePageKernelMemoryNonPagedEdit;       /*  Kernel Memory NonPaged Edit Control */
50 HWND  hPerformancePagePhysicalMemoryTotalEdit;        /*  Physical Memory Total Edit Control */
51 HWND  hPerformancePagePhysicalMemoryAvailableEdit;    /*  Physical Memory Available Edit Control */
52 HWND  hPerformancePagePhysicalMemorySystemCacheEdit;  /*  Physical Memory System Cache Edit Control */
53 HWND  hPerformancePageTotalsHandleCountEdit;          /*  Total Handles Edit Control */
54 HWND  hPerformancePageTotalsProcessCountEdit;         /*  Total Processes Edit Control */
55 HWND  hPerformancePageTotalsThreadCountEdit;          /*  Total Threads Edit Control */
56 
57 #ifdef RUN_PERF_PAGE
58 static HANDLE hPerformanceThread = NULL;
59 static DWORD  dwPerformanceThread;
60 #endif
61 
62 static int     nPerformancePageWidth;
63 static int     nPerformancePageHeight;
64 static int     lastX, lastY;
65 DWORD WINAPI   PerformancePageRefreshThread(void *lpParameter);
66 
67 void AdjustFrameSize(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference, int pos)
68 {
69     RECT  rc;
70     int   cx, cy, sx, sy;
71 
72     GetClientRect(hCntrl, &rc);
73     MapWindowPoints(hCntrl, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT));
74     if (pos) {
75         cx = rc.left;
76         cy = rc.top;
77         sx = rc.right - rc.left;
78         switch (pos) {
79         case 1:
80             break;
81         case 2:
82             cy += nYDifference / 2;
83             break;
84         case 3:
85             sx += nXDifference;
86             break;
87         case 4:
88             cy += nYDifference / 2;
89             sx += nXDifference;
90             break;
91         }
92         sy = rc.bottom - rc.top + nYDifference / 2;
93         SetWindowPos(hCntrl, NULL, cx, cy, sx, sy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER);
94     } else {
95         cx = rc.left + nXDifference;
96         cy = rc.top + nYDifference;
97         SetWindowPos(hCntrl, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
98     }
99     InvalidateRect(hCntrl, NULL, TRUE);
100 }
101 
102 static void AdjustControlPosition(HWND hCntrl, HWND hDlg, int nXDifference, int nYDifference)
103 {
104     AdjustFrameSize(hCntrl, hDlg, nXDifference, nYDifference, 0);
105 }
106 
107 static void AdjustCntrlPos(int ctrl_id, HWND hDlg, int nXDifference, int nYDifference)
108 {
109     AdjustFrameSize(GetDlgItem(hDlg, ctrl_id), hDlg, nXDifference, nYDifference, 0);
110 }
111 
112 INT_PTR CALLBACK
113 PerformancePageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
114 {
115     RECT  rc;
116     int   nXDifference;
117     int   nYDifference;
118 /*     HDC hdc; */
119 /*     PAINTSTRUCT ps; */
120 
121     switch (message) {
122     case WM_DESTROY:
123         GraphCtrl_Dispose(&PerformancePageCpuUsageHistoryGraph);
124         GraphCtrl_Dispose(&PerformancePageMemUsageHistoryGraph);
125 #ifdef RUN_PERF_PAGE
126         EndLocalThread(&hPerformanceThread, dwPerformanceThread);
127 #endif
128         break;
129 
130     case WM_INITDIALOG:
131     {
132         BOOL bGraph;
133         TM_FORMAT fmt;
134 
135         /*  Save the width and height */
136         GetClientRect(hDlg, &rc);
137         nPerformancePageWidth = rc.right;
138         nPerformancePageHeight = rc.bottom;
139 
140         /*  Update window position */
141         SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
142 
143         /*
144          *  Get handles to all the controls
145          */
146         hPerformancePageTotalsFrame = GetDlgItem(hDlg, IDC_TOTALS_FRAME);
147         hPerformancePageCommitChargeFrame = GetDlgItem(hDlg, IDC_COMMIT_CHARGE_FRAME);
148         hPerformancePageKernelMemoryFrame = GetDlgItem(hDlg, IDC_KERNEL_MEMORY_FRAME);
149         hPerformancePagePhysicalMemoryFrame = GetDlgItem(hDlg, IDC_PHYSICAL_MEMORY_FRAME);
150 
151         hPerformancePageCpuUsageFrame = GetDlgItem(hDlg, IDC_CPU_USAGE_FRAME);
152         hPerformancePageMemUsageFrame = GetDlgItem(hDlg, IDC_MEM_USAGE_FRAME);
153         hPerformancePageCpuUsageHistoryFrame = GetDlgItem(hDlg, IDC_CPU_USAGE_HISTORY_FRAME);
154         hPerformancePageMemUsageHistoryFrame = GetDlgItem(hDlg, IDC_MEMORY_USAGE_HISTORY_FRAME);
155 
156         hPerformancePageCommitChargeTotalEdit = GetDlgItem(hDlg, IDC_COMMIT_CHARGE_TOTAL);
157         hPerformancePageCommitChargeLimitEdit = GetDlgItem(hDlg, IDC_COMMIT_CHARGE_LIMIT);
158         hPerformancePageCommitChargePeakEdit = GetDlgItem(hDlg, IDC_COMMIT_CHARGE_PEAK);
159         hPerformancePageKernelMemoryTotalEdit = GetDlgItem(hDlg, IDC_KERNEL_MEMORY_TOTAL);
160         hPerformancePageKernelMemoryPagedEdit = GetDlgItem(hDlg, IDC_KERNEL_MEMORY_PAGED);
161         hPerformancePageKernelMemoryNonPagedEdit = GetDlgItem(hDlg, IDC_KERNEL_MEMORY_NONPAGED);
162         hPerformancePagePhysicalMemoryTotalEdit = GetDlgItem(hDlg, IDC_PHYSICAL_MEMORY_TOTAL);
163         hPerformancePagePhysicalMemoryAvailableEdit = GetDlgItem(hDlg, IDC_PHYSICAL_MEMORY_AVAILABLE);
164         hPerformancePagePhysicalMemorySystemCacheEdit = GetDlgItem(hDlg, IDC_PHYSICAL_MEMORY_SYSTEM_CACHE);
165         hPerformancePageTotalsHandleCountEdit = GetDlgItem(hDlg, IDC_TOTALS_HANDLE_COUNT);
166         hPerformancePageTotalsProcessCountEdit = GetDlgItem(hDlg, IDC_TOTALS_PROCESS_COUNT);
167         hPerformancePageTotalsThreadCountEdit = GetDlgItem(hDlg, IDC_TOTALS_THREAD_COUNT);
168 
169         hPerformancePageCpuUsageGraph = GetDlgItem(hDlg, IDC_CPU_USAGE_GRAPH);
170         hPerformancePageMemUsageGraph = GetDlgItem(hDlg, IDC_MEM_USAGE_GRAPH);
171         hPerformancePageMemUsageHistoryGraph = GetDlgItem(hDlg, IDC_MEM_USAGE_HISTORY_GRAPH);
172         hPerformancePageCpuUsageHistoryGraph = GetDlgItem(hDlg, IDC_CPU_USAGE_HISTORY_GRAPH);
173 
174         /*  Create the controls */
175         fmt.clrBack = RGB(0, 0, 0);
176         fmt.clrGrid = RGB(0, 128, 64);
177         fmt.clrPlot0 = RGB(0, 255, 0);
178         fmt.clrPlot1 = RGB(255, 0, 0);
179         fmt.GridCellWidth = fmt.GridCellHeight = 12;
180         fmt.DrawSecondaryPlot = TaskManagerSettings.ShowKernelTimes;
181         bGraph = GraphCtrl_Create(&PerformancePageCpuUsageHistoryGraph, hPerformancePageCpuUsageHistoryGraph, hDlg, &fmt);
182         if (!bGraph)
183         {
184             EndDialog(hDlg, 0);
185             return FALSE;
186         }
187 
188         fmt.clrPlot0 = RGB(255, 255, 0);
189         fmt.clrPlot1 = RGB(100, 255, 255);
190         fmt.DrawSecondaryPlot = TRUE;
191         bGraph = GraphCtrl_Create(&PerformancePageMemUsageHistoryGraph, hPerformancePageMemUsageHistoryGraph, hDlg, &fmt);
192         if (!bGraph)
193         {
194             EndDialog(hDlg, 0);
195             return FALSE;
196         }
197 
198         /*  Start our refresh thread */
199 #ifdef RUN_PERF_PAGE
200         hPerformanceThread = CreateThread(NULL, 0, PerformancePageRefreshThread, NULL, 0, &dwPerformanceThread);
201 #endif
202 
203         /*
204          *  Subclass graph buttons
205          */
206         OldGraphWndProc = (WNDPROC)SetWindowLongPtrW(hPerformancePageCpuUsageGraph, GWLP_WNDPROC, (LONG_PTR)Graph_WndProc);
207         SetWindowLongPtrW(hPerformancePageMemUsageGraph, GWLP_WNDPROC, (LONG_PTR)Graph_WndProc);
208         OldGraphCtrlWndProc = (WNDPROC)SetWindowLongPtrW(hPerformancePageMemUsageHistoryGraph, GWLP_WNDPROC, (LONG_PTR)GraphCtrl_WndProc);
209         SetWindowLongPtrW(hPerformancePageCpuUsageHistoryGraph, GWLP_WNDPROC, (LONG_PTR)GraphCtrl_WndProc);
210         return TRUE;
211     }
212 
213     case WM_COMMAND:
214         break;
215 #if 0
216     case WM_NCPAINT:
217         hdc = GetDC(hDlg);
218         GetClientRect(hDlg, &rc);
219         Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
220         ReleaseDC(hDlg, hdc);
221         break;
222 
223     case WM_PAINT:
224         hdc = BeginPaint(hDlg, &ps);
225         GetClientRect(hDlg, &rc);
226         Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
227         EndPaint(hDlg, &ps);
228         break;
229 #endif
230     case WM_SIZE:
231         do {
232         int  cx, cy;
233 
234         if (wParam == SIZE_MINIMIZED)
235             return 0;
236 
237         cx = LOWORD(lParam);
238         cy = HIWORD(lParam);
239         nXDifference = cx - nPerformancePageWidth;
240         nYDifference = cy - nPerformancePageHeight;
241         nPerformancePageWidth = cx;
242         nPerformancePageHeight = cy;
243         } while (0);
244 
245         /*  Reposition the performance page's controls */
246         AdjustFrameSize(hPerformancePageTotalsFrame, hDlg, 0, nYDifference, 0);
247         AdjustFrameSize(hPerformancePageCommitChargeFrame, hDlg, 0, nYDifference, 0);
248         AdjustFrameSize(hPerformancePageKernelMemoryFrame, hDlg, 0, nYDifference, 0);
249         AdjustFrameSize(hPerformancePagePhysicalMemoryFrame, hDlg, 0, nYDifference, 0);
250         AdjustCntrlPos(IDS_COMMIT_CHARGE_TOTAL, hDlg, 0, nYDifference);
251         AdjustCntrlPos(IDS_COMMIT_CHARGE_LIMIT, hDlg, 0, nYDifference);
252         AdjustCntrlPos(IDS_COMMIT_CHARGE_PEAK, hDlg, 0, nYDifference);
253         AdjustCntrlPos(IDS_KERNEL_MEMORY_TOTAL, hDlg, 0, nYDifference);
254         AdjustCntrlPos(IDS_KERNEL_MEMORY_PAGED, hDlg, 0, nYDifference);
255         AdjustCntrlPos(IDS_KERNEL_MEMORY_NONPAGED, hDlg, 0, nYDifference);
256         AdjustCntrlPos(IDS_PHYSICAL_MEMORY_TOTAL, hDlg, 0, nYDifference);
257         AdjustCntrlPos(IDS_PHYSICAL_MEMORY_AVAILABLE, hDlg, 0, nYDifference);
258         AdjustCntrlPos(IDS_PHYSICAL_MEMORY_SYSTEM_CACHE, hDlg, 0, nYDifference);
259         AdjustCntrlPos(IDS_TOTALS_HANDLE_COUNT, hDlg, 0, nYDifference);
260         AdjustCntrlPos(IDS_TOTALS_PROCESS_COUNT, hDlg, 0, nYDifference);
261         AdjustCntrlPos(IDS_TOTALS_THREAD_COUNT, hDlg, 0, nYDifference);
262 
263         AdjustControlPosition(hPerformancePageCommitChargeTotalEdit, hDlg, 0, nYDifference);
264         AdjustControlPosition(hPerformancePageCommitChargeLimitEdit, hDlg, 0, nYDifference);
265         AdjustControlPosition(hPerformancePageCommitChargePeakEdit, hDlg, 0, nYDifference);
266         AdjustControlPosition(hPerformancePageKernelMemoryTotalEdit, hDlg, 0, nYDifference);
267         AdjustControlPosition(hPerformancePageKernelMemoryPagedEdit, hDlg, 0, nYDifference);
268         AdjustControlPosition(hPerformancePageKernelMemoryNonPagedEdit, hDlg, 0, nYDifference);
269         AdjustControlPosition(hPerformancePagePhysicalMemoryTotalEdit, hDlg, 0, nYDifference);
270         AdjustControlPosition(hPerformancePagePhysicalMemoryAvailableEdit, hDlg, 0, nYDifference);
271         AdjustControlPosition(hPerformancePagePhysicalMemorySystemCacheEdit, hDlg, 0, nYDifference);
272         AdjustControlPosition(hPerformancePageTotalsHandleCountEdit, hDlg, 0, nYDifference);
273         AdjustControlPosition(hPerformancePageTotalsProcessCountEdit, hDlg, 0, nYDifference);
274         AdjustControlPosition(hPerformancePageTotalsThreadCountEdit, hDlg, 0, nYDifference);
275 
276         nXDifference += lastX;
277         nYDifference += lastY;
278         lastX = lastY = 0;
279         if (nXDifference % 2) {
280             if (nXDifference > 0) {
281                 nXDifference--;
282                 lastX++;
283             } else {
284                 nXDifference++;
285                 lastX--;
286             }
287         }
288         if (nYDifference % 2) {
289             if (nYDifference > 0) {
290                 nYDifference--;
291                 lastY++;
292             } else {
293                 nYDifference++;
294                 lastY--;
295             }
296         }
297         AdjustFrameSize(hPerformancePageCpuUsageFrame, hDlg, nXDifference, nYDifference, 1);
298         AdjustFrameSize(hPerformancePageMemUsageFrame, hDlg, nXDifference, nYDifference, 2);
299         AdjustFrameSize(hPerformancePageCpuUsageHistoryFrame, hDlg, nXDifference, nYDifference, 3);
300         AdjustFrameSize(hPerformancePageMemUsageHistoryFrame, hDlg, nXDifference, nYDifference, 4);
301         AdjustFrameSize(hPerformancePageCpuUsageGraph, hDlg, nXDifference, nYDifference, 1);
302         AdjustFrameSize(hPerformancePageMemUsageGraph, hDlg, nXDifference, nYDifference, 2);
303         AdjustFrameSize(hPerformancePageCpuUsageHistoryGraph, hDlg, nXDifference, nYDifference, 3);
304         AdjustFrameSize(hPerformancePageMemUsageHistoryGraph, hDlg, nXDifference, nYDifference, 4);
305         break;
306     }
307     return 0;
308 }
309 
310 void RefreshPerformancePage(void)
311 {
312 #ifdef RUN_PERF_PAGE
313     /*  Signal the event so that our refresh thread */
314     /*  will wake up and refresh the performance page */
315     PostThreadMessage(dwPerformanceThread, WM_TIMER, 0, 0);
316 #endif
317 }
318 
319 DWORD WINAPI PerformancePageRefreshThread(void *lpParameter)
320 {
321     ULONGLONG  CommitChargeTotal;
322     ULONGLONG  CommitChargeLimit;
323     ULONGLONG  CommitChargePeak;
324 
325     ULONG  CpuUsage;
326     ULONG  CpuKernelUsage;
327 
328     ULONGLONG  KernelMemoryTotal;
329     ULONGLONG  KernelMemoryPaged;
330     ULONGLONG  KernelMemoryNonPaged;
331 
332     ULONGLONG  PhysicalMemoryTotal;
333     ULONGLONG  PhysicalMemoryAvailable;
334     ULONGLONG  PhysicalMemorySystemCache;
335 
336     ULONG  TotalHandles;
337     ULONG  TotalThreads;
338     ULONG  TotalProcesses;
339 
340     MSG    msg;
341 
342     WCHAR  Text[260];
343     WCHAR  szMemUsage[256], szCpuUsage[256], szProcesses[256];
344 
345     LoadStringW(hInst, IDS_STATUS_CPUUSAGE, szCpuUsage, 256);
346     LoadStringW(hInst, IDS_STATUS_MEMUSAGE, szMemUsage, 256);
347     LoadStringW(hInst, IDS_STATUS_PROCESSES, szProcesses, 256);
348 
349     while (1)
350     {
351         int nBarsUsed1;
352         int nBarsUsed2;
353 
354         WCHAR szChargeTotalFormat[256];
355         WCHAR szChargeLimitFormat[256];
356 
357         /*  Wait for an the event or application close */
358         if (GetMessage(&msg, NULL, 0, 0) <= 0)
359             return 0;
360 
361         if (msg.message == WM_TIMER)
362         {
363             /*
364              *  Update the commit charge info
365              */
366             CommitChargeTotal = PerfDataGetCommitChargeTotalK();
367             CommitChargeLimit = PerfDataGetCommitChargeLimitK();
368             CommitChargePeak  = PerfDataGetCommitChargePeakK();
369             _ultow(CommitChargeTotal, Text, 10);
370             SetWindowTextW(hPerformancePageCommitChargeTotalEdit, Text);
371             _ultow(CommitChargeLimit, Text, 10);
372             SetWindowTextW(hPerformancePageCommitChargeLimitEdit, Text);
373             _ultow(CommitChargePeak, Text, 10);
374             SetWindowTextW(hPerformancePageCommitChargePeakEdit, Text);
375 
376             StrFormatByteSizeW(CommitChargeTotal * 1024,
377                                szChargeTotalFormat,
378                                _countof(szChargeTotalFormat));
379 
380             StrFormatByteSizeW(CommitChargeLimit * 1024,
381                                szChargeLimitFormat,
382                                _countof(szChargeLimitFormat));
383 
384             if (!bInMenuLoop)
385             {
386                 wsprintfW(Text, szMemUsage, szChargeTotalFormat, szChargeLimitFormat,
387                     (CommitChargeLimit ? ((CommitChargeTotal * 100) / CommitChargeLimit) : 0));
388                 SendMessageW(hStatusWnd, SB_SETTEXT, 2, (LPARAM)Text);
389             }
390 
391             /*
392              *  Update the kernel memory info
393              */
394             KernelMemoryTotal = PerfDataGetKernelMemoryTotalK();
395             KernelMemoryPaged = PerfDataGetKernelMemoryPagedK();
396             KernelMemoryNonPaged = PerfDataGetKernelMemoryNonPagedK();
397             _ultow(KernelMemoryTotal, Text, 10);
398             SetWindowTextW(hPerformancePageKernelMemoryTotalEdit, Text);
399             _ultow(KernelMemoryPaged, Text, 10);
400             SetWindowTextW(hPerformancePageKernelMemoryPagedEdit, Text);
401             _ultow(KernelMemoryNonPaged, Text, 10);
402             SetWindowTextW(hPerformancePageKernelMemoryNonPagedEdit, Text);
403 
404             /*
405              *  Update the physical memory info
406              */
407             PhysicalMemoryTotal = PerfDataGetPhysicalMemoryTotalK();
408             PhysicalMemoryAvailable = PerfDataGetPhysicalMemoryAvailableK();
409             PhysicalMemorySystemCache = PerfDataGetPhysicalMemorySystemCacheK();
410             _ultow(PhysicalMemoryTotal, Text, 10);
411             SetWindowTextW(hPerformancePagePhysicalMemoryTotalEdit, Text);
412             _ultow(PhysicalMemoryAvailable, Text, 10);
413             SetWindowTextW(hPerformancePagePhysicalMemoryAvailableEdit, Text);
414             _ultow(PhysicalMemorySystemCache, Text, 10);
415             SetWindowTextW(hPerformancePagePhysicalMemorySystemCacheEdit, Text);
416 
417             /*
418              *  Update the totals info
419              */
420             TotalHandles = PerfDataGetSystemHandleCount();
421             TotalThreads = PerfDataGetTotalThreadCount();
422             TotalProcesses = PerfDataGetProcessCount();
423             _ultow(TotalHandles, Text, 10);
424             SetWindowTextW(hPerformancePageTotalsHandleCountEdit, Text);
425             _ultow(TotalThreads, Text, 10);
426             SetWindowTextW(hPerformancePageTotalsThreadCountEdit, Text);
427             _ultow(TotalProcesses, Text, 10);
428             SetWindowTextW(hPerformancePageTotalsProcessCountEdit, Text);
429             if (!bInMenuLoop)
430             {
431                 wsprintfW(Text, szProcesses, TotalProcesses);
432                 SendMessageW(hStatusWnd, SB_SETTEXT, 0, (LPARAM)Text);
433             }
434 
435             /*
436              *  Redraw the graphs
437              */
438             InvalidateRect(hPerformancePageCpuUsageGraph, NULL, FALSE);
439             InvalidateRect(hPerformancePageMemUsageGraph, NULL, FALSE);
440 
441             /*
442              *  Get the CPU usage
443              */
444             CpuUsage = PerfDataGetProcessorUsage();
445             if (CpuUsage <= 0 )       CpuUsage = 0;
446             if (CpuUsage > 100)       CpuUsage = 100;
447 
448             if (!bInMenuLoop)
449             {
450                 wsprintfW(Text, szCpuUsage, CpuUsage);
451                 SendMessageW(hStatusWnd, SB_SETTEXT, 1, (LPARAM)Text);
452             }
453 
454             CpuKernelUsage = PerfDataGetProcessorSystemUsage();
455             if (CpuKernelUsage <= 0)
456                 CpuKernelUsage = 0;
457             else if (CpuKernelUsage > 100)
458                 CpuKernelUsage = 100;
459 
460             /*
461              *  Get the memory usage
462              */
463             CommitChargeTotal = PerfDataGetCommitChargeTotalK();
464             CommitChargeLimit = PerfDataGetCommitChargeLimitK();
465             nBarsUsed1 = CommitChargeLimit ? ((CommitChargeTotal * 100) / CommitChargeLimit) : 0;
466 
467             PhysicalMemoryTotal = PerfDataGetPhysicalMemoryTotalK();
468             PhysicalMemoryAvailable = PerfDataGetPhysicalMemoryAvailableK();
469             nBarsUsed2 = PhysicalMemoryTotal ? ((PhysicalMemoryAvailable * 100) / PhysicalMemoryTotal) : 0;
470 
471             GraphCtrl_AddPoint(&PerformancePageCpuUsageHistoryGraph, CpuUsage, CpuKernelUsage);
472             GraphCtrl_AddPoint(&PerformancePageMemUsageHistoryGraph, nBarsUsed1, nBarsUsed2);
473             InvalidateRect(hPerformancePageMemUsageHistoryGraph, NULL, FALSE);
474             InvalidateRect(hPerformancePageCpuUsageHistoryGraph, NULL, FALSE);
475         }
476     }
477     return 0;
478 }
479 
480 void PerformancePage_OnViewShowKernelTimes(void)
481 {
482     HMENU  hMenu;
483     HMENU  hViewMenu;
484 
485     hMenu = GetMenu(hMainWnd);
486     hViewMenu = GetSubMenu(hMenu, 2);
487 
488     /*  Check or uncheck the show 16-bit tasks menu item */
489     if (GetMenuState(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND) & MF_CHECKED)
490     {
491         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
492         TaskManagerSettings.ShowKernelTimes = FALSE;
493         PerformancePageCpuUsageHistoryGraph.DrawSecondaryPlot = FALSE;
494     }
495     else
496     {
497         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
498         TaskManagerSettings.ShowKernelTimes = TRUE;
499         PerformancePageCpuUsageHistoryGraph.DrawSecondaryPlot = TRUE;
500     }
501 
502     GraphCtrl_RedrawBitmap(&PerformancePageCpuUsageHistoryGraph, PerformancePageCpuUsageHistoryGraph.BitmapHeight);
503     RefreshPerformancePage();
504 }
505 
506 void PerformancePage_OnViewCPUHistoryOneGraphAll(void)
507 {
508     HMENU  hMenu;
509     HMENU  hViewMenu;
510     HMENU  hCPUHistoryMenu;
511 
512     hMenu = GetMenu(hMainWnd);
513     hViewMenu = GetSubMenu(hMenu, 2);
514     hCPUHistoryMenu = GetSubMenu(hViewMenu, 3);
515 
516     TaskManagerSettings.CPUHistory_OneGraphPerCPU = FALSE;
517     CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
518 }
519 
520 void PerformancePage_OnViewCPUHistoryOneGraphPerCPU(void)
521 {
522     HMENU  hMenu;
523     HMENU  hViewMenu;
524     HMENU  hCPUHistoryMenu;
525 
526     hMenu = GetMenu(hMainWnd);
527     hViewMenu = GetSubMenu(hMenu, 2);
528     hCPUHistoryMenu = GetSubMenu(hViewMenu, 3);
529 
530     TaskManagerSettings.CPUHistory_OneGraphPerCPU = TRUE;
531     CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
532 }
533 
534