123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- /*
- * ReactOS Task Manager
- *
- * graph.c
- *
- * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
- * Copyright (C) 2008 Vladimir Pankratov
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <windows.h>
- #include <commctrl.h>
- #include <shlwapi.h>
- #include <winnt.h>
- #include "taskmgr.h"
- #include "perfdata.h"
- #define BRIGHT_GREEN RGB(0, 255, 0)
- #define DARK_GREEN RGB(0, 130, 0)
- #define RED RGB(255, 0, 0)
- WNDPROC OldGraphWndProc;
- static void Graph_DrawCpuUsageGraph(HDC hDC, HWND hWnd)
- {
- RECT rcClient;
- RECT rcBarLeft;
- RECT rcBarRight;
- RECT rcText;
- WCHAR Text[256];
- ULONG CpuUsage;
- ULONG CpuKernelUsage;
- int nBars;
- int nBarsUsed;
- /* Bottom bars that are "used", i.e. are bright green, representing used cpu time */
- int nBarsUsedKernel;
- /* Bottom bars that are "used", i.e. are bright green, representing used cpu kernel time */
- int nBarsFree;
- /* Top bars that are "unused", i.e. are dark green, representing free cpu time */
- int i;
- static const WCHAR wszFormatI[] = {'%','d','%','%',0};
- static const WCHAR wszFormatII[] = {' ',' ','%','d','%','%',0};
- static const WCHAR wszFormatIII[] = {' ','%','d','%','%',0};
-
- /*
- * Get the client area rectangle
- */
- GetClientRect(hWnd, &rcClient);
-
- /*
- * Fill it with blackness
- */
- FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
-
- /*
- * Get the CPU usage
- */
- CpuUsage = PerfDataGetProcessorUsage();
- CpuKernelUsage = PerfDataGetProcessorSystemUsage();
- /*
- * Check and see how many digits it will take
- * so we get the indentation right every time.
- */
- if (CpuUsage == 100)
- {
- swprintf(Text, ARRAY_SIZE(Text), wszFormatI, (int)CpuUsage);
- }
- else if (CpuUsage < 10)
- {
- swprintf(Text, ARRAY_SIZE(Text), wszFormatII, (int)CpuUsage);
- }
- else
- {
- swprintf(Text, ARRAY_SIZE(Text), wszFormatIII, (int)CpuUsage);
- }
-
- /*
- * Draw the font text onto the graph
- * The bottom 20 pixels are reserved for the text
- */
- CopyRect(&rcText, &rcClient);
- rcText.top = rcText.bottom - 19;
- SetTextColor(hDC, BRIGHT_GREEN);
- DrawTextW(hDC, Text, -1, &rcText, DT_CENTER);
- /*
- * Now we have to draw the graph
- * So first find out how many bars we can fit
- */
- nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
- nBarsUsed = (nBars * CpuUsage) / 100;
- if ((CpuUsage) && (nBarsUsed == 0))
- {
- nBarsUsed = 1;
- }
- nBarsFree = nBars - nBarsUsed;
- if (TaskManagerSettings.ShowKernelTimes)
- {
- nBarsUsedKernel = ((nBars * 2) * CpuKernelUsage) / 100;
- nBarsUsed -= (nBarsUsedKernel / 2);
- }
- else
- {
- nBarsUsedKernel = 0;
- }
- /*
- * Now draw the bar graph
- */
- rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
- rcBarLeft.right = rcBarLeft.left + 16;
- rcBarRight.left = rcBarLeft.left + 17;
- rcBarRight.right = rcBarLeft.right + 17;
- rcBarLeft.top = rcBarRight.top = 5;
- rcBarLeft.bottom = rcBarRight.bottom = 7;
- if (nBarsUsed < 0) nBarsUsed = 0;
- if (nBarsUsed > nBars) nBarsUsed = nBars;
- if (nBarsFree < 0) nBarsFree = 0;
- if (nBarsFree > nBars) nBarsFree = nBars;
- if (nBarsUsedKernel < 0) nBarsUsedKernel = 0;
- if (nBarsUsedKernel > nBars) nBarsUsedKernel = nBars;
- /*
- * Draw the "free" bars
- */
- for (i=0; i<nBarsFree; i++)
- {
- FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
- FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
-
- rcBarLeft.top += 3;
- rcBarLeft.bottom += 3;
-
- rcBarRight.top += 3;
- rcBarRight.bottom += 3;
- }
-
- /*
- * Draw the "used" bars
- */
- for (i=0; i<nBarsUsed; i++)
- {
- if (nBarsUsed > 5000) nBarsUsed = 5000;
- FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
- FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
-
- rcBarLeft.top += 3;
- rcBarLeft.bottom += 3;
-
- rcBarRight.top += 3;
- rcBarRight.bottom += 3;
- }
-
- /*
- * Draw the "used" kernel bars
- */
- rcBarLeft.bottom--;
- rcBarRight.bottom--;
- if (nBarsUsedKernel && nBarsUsedKernel % 2)
- {
- rcBarLeft.top -= 2;
- rcBarLeft.bottom -= 2;
-
- rcBarRight.top -= 2;
- rcBarRight.bottom -= 2;
- FillSolidRect(hDC, &rcBarLeft, RED);
- FillSolidRect(hDC, &rcBarRight, RED);
-
- rcBarLeft.top += 2;
- rcBarLeft.bottom += 2;
-
- rcBarRight.top += 2;
- rcBarRight.bottom += 2;
- nBarsUsedKernel--;
- }
- for (i=0; i<nBarsUsedKernel; i++)
- {
- if (nBarsUsedKernel > 5000) nBarsUsedKernel = 5000;
- FillSolidRect(hDC, &rcBarLeft, RED);
- FillSolidRect(hDC, &rcBarRight, RED);
-
- rcBarLeft.top++;
- rcBarLeft.bottom++;
-
- rcBarRight.top++;
- rcBarRight.bottom++;
- if (i % 2)
- {
- rcBarLeft.top++;
- rcBarLeft.bottom++;
-
- rcBarRight.top++;
- rcBarRight.bottom++;
- }
- }
- }
- static void Graph_DrawMemUsageGraph(HDC hDC, HWND hWnd)
- {
- RECT rcClient;
- RECT rcBarLeft;
- RECT rcBarRight;
- RECT rcText;
- WCHAR Text[256];
- ULONGLONG CommitChargeTotal;
- ULONGLONG CommitChargeLimit;
- int nBars;
- int nBarsUsed = 0;
- /* Bottom bars that are "used", i.e. are bright green, representing used memory */
- int nBarsFree;
- /* Top bars that are "unused", i.e. are dark green, representing free memory */
- int i;
- /*
- * Get the client area rectangle
- */
- GetClientRect(hWnd, &rcClient);
-
- /*
- * Fill it with blackness
- */
- FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
-
- /*
- * Get the memory usage
- */
- CommitChargeTotal = (ULONGLONG)PerfDataGetCommitChargeTotalK();
- CommitChargeLimit = (ULONGLONG)PerfDataGetCommitChargeLimitK();
- if (CommitChargeTotal < 1024)
- StrFormatKBSizeW(CommitChargeTotal, Text, ARRAY_SIZE(Text));
- else
- StrFormatByteSizeW(CommitChargeTotal, Text, ARRAY_SIZE(Text));
-
- /*
- * Draw the font text onto the graph
- * The bottom 20 pixels are reserved for the text
- */
- CopyRect(&rcText, &rcClient);
- rcText.top = rcText.bottom - 19;
- SetTextColor(hDC, BRIGHT_GREEN);
- DrawTextW(hDC, Text, -1, &rcText, DT_CENTER);
- /*
- * Now we have to draw the graph
- * So first find out how many bars we can fit
- */
- nBars = ((rcClient.bottom - rcClient.top) - 25) / 3;
- if (CommitChargeLimit)
- nBarsUsed = (nBars * (int)((CommitChargeTotal * 100) / CommitChargeLimit)) / 100;
- nBarsFree = nBars - nBarsUsed;
- if (nBarsUsed < 0) nBarsUsed = 0;
- if (nBarsUsed > nBars) nBarsUsed = nBars;
- if (nBarsFree < 0) nBarsFree = 0;
- if (nBarsFree > nBars) nBarsFree = nBars;
- /*
- * Now draw the bar graph
- */
- rcBarLeft.left = ((rcClient.right - rcClient.left) - 33) / 2;
- rcBarLeft.right = rcBarLeft.left + 16;
- rcBarRight.left = rcBarLeft.left + 17;
- rcBarRight.right = rcBarLeft.right + 17;
- rcBarLeft.top = rcBarRight.top = 5;
- rcBarLeft.bottom = rcBarRight.bottom = 7;
-
- /*
- * Draw the "free" bars
- */
- for (i=0; i<nBarsFree; i++)
- {
- FillSolidRect(hDC, &rcBarLeft, DARK_GREEN);
- FillSolidRect(hDC, &rcBarRight, DARK_GREEN);
-
- rcBarLeft.top += 3;
- rcBarLeft.bottom += 3;
-
- rcBarRight.top += 3;
- rcBarRight.bottom += 3;
- }
-
- /*
- * Draw the "used" bars
- */
- for (i=0; i<nBarsUsed; i++)
- {
- FillSolidRect(hDC, &rcBarLeft, BRIGHT_GREEN);
- FillSolidRect(hDC, &rcBarRight, BRIGHT_GREEN);
-
- rcBarLeft.top += 3;
- rcBarLeft.bottom += 3;
-
- rcBarRight.top += 3;
- rcBarRight.bottom += 3;
- }
- }
- static void Graph_DrawMemUsageHistoryGraph(HDC hDC, HWND hWnd)
- {
- RECT rcClient;
- int i;
- static int offset = 0;
-
- if (offset++ >= 10)
- offset = 0;
-
- /*
- * Get the client area rectangle
- */
- GetClientRect(hWnd, &rcClient);
-
- /*
- * Fill it with blackness
- */
- FillSolidRect(hDC, &rcClient, RGB(0, 0, 0));
- /*
- * Draw the graph background
- *
- * Draw the horizontal bars
- */
- for (i=0; i<rcClient.bottom; i++)
- {
- if ((i % 11) == 0)
- {
- /* FillSolidRect2(hDC, 0, i, rcClient.right, 1, DARK_GREEN); */
- }
- }
- /*
- * Draw the vertical bars
- */
- for (i=11; i<rcClient.right + offset; i++)
- {
- if ((i % 11) == 0)
- {
- /* FillSolidRect2(hDC, i - offset, 0, 1, rcClient.bottom, DARK_GREEN); */
- }
- }
- /*
- * Draw the memory usage
- */
- for (i=rcClient.right; i>=0; i--)
- {
- }
- }
- INT_PTR CALLBACK
- Graph_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc;
- PAINTSTRUCT ps;
- LONG WindowId;
-
- switch (message)
- {
- case WM_ERASEBKGND:
- return TRUE;
- /*
- * Filter out mouse & keyboard messages
- */
- /* case WM_APPCOMMAND: */
- case WM_CAPTURECHANGED:
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONDBLCLK:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_MOUSEACTIVATE:
- case WM_MOUSEHOVER:
- case WM_MOUSELEAVE:
- case WM_MOUSEMOVE:
- /* case WM_MOUSEWHEEL: */
- case WM_NCHITTEST:
- case WM_NCLBUTTONDBLCLK:
- case WM_NCLBUTTONDOWN:
- case WM_NCLBUTTONUP:
- case WM_NCMBUTTONDBLCLK:
- case WM_NCMBUTTONDOWN:
- case WM_NCMBUTTONUP:
- /* case WM_NCMOUSEHOVER: */
- /* case WM_NCMOUSELEAVE: */
- case WM_NCMOUSEMOVE:
- case WM_NCRBUTTONDBLCLK:
- case WM_NCRBUTTONDOWN:
- case WM_NCRBUTTONUP:
- /* case WM_NCXBUTTONDBLCLK: */
- /* case WM_NCXBUTTONDOWN: */
- /* case WM_NCXBUTTONUP: */
- case WM_RBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- /* case WM_XBUTTONDBLCLK: */
- /* case WM_XBUTTONDOWN: */
- /* case WM_XBUTTONUP: */
- case WM_ACTIVATE:
- case WM_CHAR:
- case WM_DEADCHAR:
- case WM_GETHOTKEY:
- case WM_HOTKEY:
- case WM_KEYDOWN:
- case WM_KEYUP:
- case WM_KILLFOCUS:
- case WM_SETFOCUS:
- case WM_SETHOTKEY:
- case WM_SYSCHAR:
- case WM_SYSDEADCHAR:
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
-
- case WM_NCCALCSIZE:
- return 0;
- case WM_PAINT:
-
- hdc = BeginPaint(hWnd, &ps);
- WindowId = GetWindowLongPtrW(hWnd, GWLP_ID);
- switch (WindowId)
- {
- case IDC_CPU_USAGE_GRAPH:
- Graph_DrawCpuUsageGraph(hdc, hWnd);
- break;
- case IDC_MEM_USAGE_GRAPH:
- Graph_DrawMemUsageGraph(hdc, hWnd);
- break;
- case IDC_MEM_USAGE_HISTORY_GRAPH:
- Graph_DrawMemUsageHistoryGraph(hdc, hWnd);
- break;
- }
-
- EndPaint(hWnd, &ps);
-
- return 0;
-
- }
- /*
- * We pass on all non-handled messages
- */
- return CallWindowProcW(OldGraphWndProc, hWnd, message, wParam, lParam);
- }
|