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