Reactos
at master 412 lines 11 kB view raw
1/* 2 * PROJECT: ReactOS Task Manager 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Graph Plotting controls. 5 * COPYRIGHT: Copyright 2002 Robert Dickenson <robd@reactos.org> 6 * Copyright 2021 Wu Haotian <rigoligo03@gmail.com> 7 * Copyright 2021 Valerij Zaporogeci <vlrzprgts@gmail.com> 8 */ 9 10#include "precomp.h" 11 12#include <math.h> 13 14WNDPROC OldGraphCtrlWndProc; 15 16BOOL 17GraphCtrl_Create(PTM_GRAPH_CONTROL inst, HWND hWnd, HWND hParentWnd, PTM_FORMAT fmt) 18{ 19 HDC hdc, hdcg; 20 HBITMAP hbmOld; 21 UINT Size; 22 INT p; 23 RECT rc; 24 25 inst->hParentWnd = hParentWnd; 26 inst->hWnd = hWnd; 27 28 Size = GetSystemMetrics(SM_CXSCREEN); 29 inst->BitmapWidth = Size; 30 Size /= PLOT_SHIFT; 31 inst->PointBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size * NUM_PLOTS); 32 if (!inst->PointBuffer) 33 { 34 goto fail; 35 } 36 37 inst->NumberOfPoints = Size; 38 inst->CurrIndex = 0; 39 40 /* Styling */ 41 inst->hPenGrid = CreatePen(PS_SOLID, 0, fmt->clrGrid); 42 inst->hPen0 = CreatePen(PS_SOLID, 0, fmt->clrPlot0); 43 inst->hPen1 = CreatePen(PS_SOLID, 0, fmt->clrPlot1); 44 inst->hBrushBack = CreateSolidBrush(fmt->clrBack); 45 46 if (!inst->hPenGrid || 47 !inst->hPen0 || 48 !inst->hPen1 || 49 !inst->hBrushBack) 50 { 51 goto fail; 52 } 53 54 if (fmt->GridCellWidth >= PLOT_SHIFT << 2) 55 inst->GridCellWidth = fmt->GridCellWidth; 56 else 57 inst->GridCellWidth = PLOT_SHIFT << 2; 58 if (fmt->GridCellHeight >= PLOT_SHIFT << 2) 59 inst->GridCellHeight = fmt->GridCellHeight; 60 else 61 inst->GridCellHeight = PLOT_SHIFT << 2; 62 63 inst->DrawSecondaryPlot = fmt->DrawSecondaryPlot; 64 65 GetClientRect(hWnd, &rc); 66 inst->BitmapHeight = rc.bottom; 67 inst->ftPixelsPerPercent = (FLOAT)(inst->BitmapHeight) / 100.00f; 68 69 hdc = GetDC(hParentWnd); 70 if (!hdc) 71 goto fail; 72 73 inst->hdcGraph = hdcg = CreateCompatibleDC(hdc); 74 inst->hbmGraph = CreateCompatibleBitmap(hdc, inst->BitmapWidth, inst->BitmapHeight); 75 ReleaseDC(hParentWnd, hdc); 76 if (!hdcg || !inst->hbmGraph) 77 goto fail; 78 79 hbmOld = (HBITMAP)SelectObject(hdcg, inst->hbmGraph); 80 DeleteObject(hbmOld); 81 82 SetBkColor(hdcg, fmt->clrBack); 83 rc.right = inst->BitmapWidth; 84 FillRect(hdcg, &rc, inst->hBrushBack); 85 86 inst->CurrShift = 0; 87 SelectObject(hdcg, inst->hPenGrid); 88 for (p = inst->GridCellHeight - 1; 89 p < inst->BitmapHeight; 90 p += inst->GridCellHeight) 91 { 92 MoveToEx(hdcg, 0, p, NULL); 93 LineTo(hdcg, inst->BitmapWidth, p); 94 } 95 for (p = inst->BitmapWidth - 1; 96 p > 0; 97 p -= inst->GridCellWidth) 98 { 99 MoveToEx(hdcg, p, 0, NULL); 100 LineTo(hdcg, p, inst->BitmapHeight); 101 } 102 SelectObject(hdcg, inst->hPen0); 103 104 return TRUE; 105 106fail: 107 GraphCtrl_Dispose(inst); 108 return FALSE; 109} 110 111void 112GraphCtrl_Dispose(PTM_GRAPH_CONTROL inst) 113{ 114 if (inst->PointBuffer) 115 HeapFree(GetProcessHeap(), 0, inst->PointBuffer); 116 117 if (inst->hdcGraph) 118 DeleteDC(inst->hdcGraph); 119 120 if (inst->hPenGrid) 121 DeleteObject(inst->hPenGrid); 122 123 if (inst->hPen0) 124 DeleteObject(inst->hPen0); 125 126 if (inst->hPen1) 127 DeleteObject(inst->hPen1); 128 129 if (inst->hBrushBack) 130 DeleteObject(inst->hBrushBack); 131 132 if (inst->hbmGraph) 133 DeleteObject(inst->hbmGraph); 134} 135 136void 137GraphCtrl_AddPoint(PTM_GRAPH_CONTROL inst, BYTE val0, BYTE val1) 138{ 139 HDC hdcg; 140 PBYTE t; 141 RECT rcDirt; 142 143 UINT Prev0, Prev1, RetainingWidth; 144 INT PrevY, CurrY, p, v; 145 146 hdcg = inst->hdcGraph; 147 RetainingWidth = inst->BitmapWidth - PLOT_SHIFT; 148 t = inst->PointBuffer; 149 Prev0 = *(t + inst->CurrIndex); 150 Prev1 = *(t + inst->CurrIndex + inst->NumberOfPoints); 151 if (inst->CurrIndex < inst->NumberOfPoints - 1) 152 { 153 inst->CurrIndex++; 154 } 155 else 156 { 157 inst->CurrIndex = 0; 158 } 159 *(t + inst->CurrIndex) = val0; 160 *(t + inst->CurrIndex + inst->NumberOfPoints) = val1; 161 162 /* Drawing points, first shifting the plot left */ 163 BitBlt(hdcg, 0, 0, RetainingWidth, inst->BitmapHeight, hdcg, PLOT_SHIFT, 0, SRCCOPY); 164 165 rcDirt.left = RetainingWidth; 166 rcDirt.top = 0; 167 rcDirt.right = inst->BitmapWidth; 168 rcDirt.bottom = inst->BitmapHeight; 169 FillRect(hdcg, &rcDirt, inst->hBrushBack); 170 171 SelectObject(hdcg, inst->hPenGrid); 172 for (p = inst->GridCellHeight - 1; 173 p < inst->BitmapHeight; 174 p += inst->GridCellHeight) 175 { 176 MoveToEx(hdcg, RetainingWidth, p, NULL); 177 LineTo(hdcg, inst->BitmapWidth, p); 178 } 179 v = inst->CurrShift + PLOT_SHIFT; 180 if (v >= inst->GridCellWidth) 181 { 182 v -= inst->GridCellWidth; 183 p = inst->BitmapWidth - v - 1; 184 MoveToEx(hdcg, p, 0, NULL); 185 LineTo(hdcg, p, inst->BitmapHeight); 186 } 187 inst->CurrShift = v; 188 189 if (inst->DrawSecondaryPlot) 190 { 191 SelectObject(inst->hdcGraph, inst->hPen1); 192 193 PrevY = inst->BitmapHeight - Prev1 * inst->ftPixelsPerPercent; 194 MoveToEx(inst->hdcGraph, RetainingWidth - 1, PrevY, NULL); 195 CurrY = inst->BitmapHeight - val1 * inst->ftPixelsPerPercent; 196 LineTo(inst->hdcGraph, inst->BitmapWidth - 1, CurrY); 197 } 198 199 SelectObject(inst->hdcGraph, inst->hPen0); 200 PrevY = inst->BitmapHeight - Prev0 * inst->ftPixelsPerPercent; 201 MoveToEx(inst->hdcGraph, RetainingWidth - 1, PrevY, NULL); 202 CurrY = inst->BitmapHeight - val0 * inst->ftPixelsPerPercent; 203 LineTo(inst->hdcGraph, inst->BitmapWidth - 1, CurrY); 204} 205 206inline void 207GraphCtrl_RedrawBitmap(PTM_GRAPH_CONTROL inst, INT h) 208{ 209 HDC hdcg; 210 PBYTE t; 211 RECT rc; 212 INT i, j, y, x, p; 213 FLOAT coef; 214 215 hdcg = inst->hdcGraph; 216 rc.left = 0; rc.top = 0; 217 rc.right = inst->BitmapWidth; rc.bottom = h; 218 FillRect(hdcg, &rc, inst->hBrushBack); 219 220 SelectObject(hdcg, inst->hPenGrid); 221 222 for (p = inst->GridCellHeight - 1; 223 p < inst->BitmapHeight; 224 p += inst->GridCellHeight) 225 { 226 MoveToEx(hdcg, 0, p, NULL); 227 LineTo(hdcg, inst->BitmapWidth, p); 228 } 229 230 for (p = inst->BitmapWidth - inst->CurrShift - 1; 231 p > 0; 232 p -= inst->GridCellWidth) 233 { 234 MoveToEx(hdcg, p, 0, NULL); 235 LineTo(hdcg, p, inst->BitmapHeight); 236 } 237 238 coef = inst->ftPixelsPerPercent; 239 240 if (inst->DrawSecondaryPlot) 241 { 242 SelectObject(hdcg, inst->hPen1); 243 t = inst->PointBuffer + inst->NumberOfPoints; 244 x = inst->BitmapWidth - 1; 245 j = inst->CurrIndex; 246 y = h - *(t + j) * coef; 247 MoveToEx(hdcg, x, y, NULL); 248 for (i = 0; i < inst->NumberOfPoints; i++) 249 { 250 j = (j ? j : inst->NumberOfPoints) - 1; 251 y = h - *(t + j) * coef; 252 x -= PLOT_SHIFT; 253 LineTo(hdcg, x, y); 254 } 255 } 256 257 SelectObject(hdcg, inst->hPen0); 258 t = inst->PointBuffer; 259 x = inst->BitmapWidth - 1; 260 j = inst->CurrIndex; 261 y = h - *(t + j) * coef; 262 MoveToEx(hdcg, x, y, NULL); 263 264 for (i = 0; i < inst->NumberOfPoints; i++) 265 { 266 j = (j ? j : inst->NumberOfPoints) - 1; 267 y = h - *(t + j) * coef; 268 x -= PLOT_SHIFT; 269 LineTo(hdcg, x, y); 270 } 271} 272 273inline void 274GraphCtrl_RedrawOnHeightChange(PTM_GRAPH_CONTROL inst, INT nh) 275{ 276 HDC hdc; 277 HBITMAP hbmOld; 278 279 inst->BitmapHeight = nh; 280 inst->ftPixelsPerPercent = (FLOAT)nh / 100.00f; 281 282 hdc = GetDC(inst->hParentWnd); 283 hbmOld = inst->hbmGraph; 284 inst->hbmGraph = CreateCompatibleBitmap(hdc, inst->BitmapWidth, nh); 285 SelectObject(inst->hdcGraph, inst->hbmGraph); 286 DeleteObject(hbmOld); 287 ReleaseDC(inst->hParentWnd, hdc); 288 289 GraphCtrl_RedrawBitmap(inst, nh); 290} 291 292extern TM_GRAPH_CONTROL PerformancePageCpuUsageHistoryGraph; 293extern TM_GRAPH_CONTROL PerformancePageMemUsageHistoryGraph; 294extern HWND hPerformancePageCpuUsageHistoryGraph; 295extern HWND hPerformancePageMemUsageHistoryGraph; 296 297INT_PTR CALLBACK 298GraphCtrl_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 299{ 300 PTM_GRAPH_CONTROL graph; 301 302 switch (message) 303 { 304 case WM_ERASEBKGND: 305 return TRUE; 306 /* 307 * Filter out mouse & keyboard messages 308 */ 309 // case WM_APPCOMMAND: 310 case WM_CAPTURECHANGED: 311 case WM_LBUTTONDBLCLK: 312 case WM_LBUTTONDOWN: 313 case WM_LBUTTONUP: 314 case WM_MBUTTONDBLCLK: 315 case WM_MBUTTONDOWN: 316 case WM_MBUTTONUP: 317 case WM_MOUSEACTIVATE: 318 case WM_MOUSEHOVER: 319 case WM_MOUSELEAVE: 320 case WM_MOUSEMOVE: 321 // case WM_MOUSEWHEEL: 322 case WM_NCHITTEST: 323 case WM_NCLBUTTONDBLCLK: 324 case WM_NCLBUTTONDOWN: 325 case WM_NCLBUTTONUP: 326 case WM_NCMBUTTONDBLCLK: 327 case WM_NCMBUTTONDOWN: 328 case WM_NCMBUTTONUP: 329 // case WM_NCMOUSEHOVER: 330 // case WM_NCMOUSELEAVE: 331 case WM_NCMOUSEMOVE: 332 case WM_NCRBUTTONDBLCLK: 333 case WM_NCRBUTTONDOWN: 334 case WM_NCRBUTTONUP: 335 // case WM_NCXBUTTONDBLCLK: 336 // case WM_NCXBUTTONDOWN: 337 // case WM_NCXBUTTONUP: 338 case WM_RBUTTONDBLCLK: 339 case WM_RBUTTONDOWN: 340 case WM_RBUTTONUP: 341 // case WM_XBUTTONDBLCLK: 342 // case WM_XBUTTONDOWN: 343 // case WM_XBUTTONUP: 344 case WM_ACTIVATE: 345 case WM_CHAR: 346 case WM_DEADCHAR: 347 case WM_GETHOTKEY: 348 case WM_HOTKEY: 349 case WM_KEYDOWN: 350 case WM_KEYUP: 351 case WM_KILLFOCUS: 352 case WM_SETFOCUS: 353 case WM_SETHOTKEY: 354 case WM_SYSCHAR: 355 case WM_SYSDEADCHAR: 356 case WM_SYSKEYDOWN: 357 case WM_SYSKEYUP: 358 return 0; 359 360 case WM_NCCALCSIZE: 361 return 0; 362 363 case WM_SIZE: 364 { 365 if (hWnd == hPerformancePageCpuUsageHistoryGraph) 366 graph = &PerformancePageCpuUsageHistoryGraph; 367 else if (hWnd == hPerformancePageMemUsageHistoryGraph) 368 graph = &PerformancePageMemUsageHistoryGraph; 369 else 370 return 0; 371 372 if (HIWORD(lParam) != graph->BitmapHeight) 373 { 374 GraphCtrl_RedrawOnHeightChange(graph, HIWORD(lParam)); 375 } 376 InvalidateRect(hWnd, NULL, FALSE); 377 378 return 0; 379 } 380 381 case WM_PAINT: 382 { 383 RECT rcClient; 384 HDC hdc; 385 PAINTSTRUCT ps; 386 387 if (hWnd == hPerformancePageCpuUsageHistoryGraph) 388 graph = &PerformancePageCpuUsageHistoryGraph; 389 else if (hWnd == hPerformancePageMemUsageHistoryGraph) 390 graph = &PerformancePageMemUsageHistoryGraph; 391 else 392 return 0; 393 394 hdc = BeginPaint(hWnd, &ps); 395 GetClientRect(hWnd, &rcClient); 396 BitBlt(hdc, 0, 0, 397 rcClient.right, 398 rcClient.bottom, 399 graph->hdcGraph, 400 graph->BitmapWidth - rcClient.right, 401 0, 402 SRCCOPY); 403 EndPaint(hWnd, &ps); 404 return 0; 405 } 406 } 407 408 /* 409 * We pass on all non-handled messages 410 */ 411 return CallWindowProcW(OldGraphCtrlWndProc, hWnd, message, wParam, lParam); 412}