Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1833 lines
46 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // TaskMan - NT TaskManager
  4. // Copyright (C) Microsoft
  5. //
  6. // File: perfpage.cpp
  7. //
  8. // History: Nov-10-95 DavePl Created
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "precomp.h"
  12. #define GRAPH_BRUSH BLACK_BRUSH
  13. #define GRAPH_LINE_COLOR RGB(0, 128, 64)
  14. #define GRAPH_TEXT_COLOR RGB(0, 255, 0)
  15. #define STRIP_HEIGHT 75
  16. #define STRIP_WIDTH 33
  17. LARGE_INTEGER PreviousCPUIdleTime[MAX_PROCESSOR] = {0 ,0};
  18. LARGE_INTEGER PreviousCPUTotalTime[MAX_PROCESSOR] = {0 ,0};
  19. LARGE_INTEGER PreviousCPUKernelTime[MAX_PROCESSOR] = {0 ,0};
  20. LPBYTE g_pCPUHistory[MAX_PROCESSOR] = { NULL };
  21. LPBYTE g_pKernelHistory[MAX_PROCESSOR] = { NULL };
  22. LPBYTE g_pMEMHistory = NULL;
  23. BYTE g_CPUUsage = 0;
  24. BYTE g_KernelUsage = 0;
  25. __int64 g_MEMUsage = 0;
  26. __int64 g_MEMMax = 0;
  27. DWORD g_PageSize;
  28. /*++ CPerfPage::SizePerfPage
  29. Routine Description:
  30. Sizes its children based on the size of the
  31. tab control on which it appears.
  32. Arguments:
  33. Return Value:
  34. Revision History:
  35. Nov-12-95 Davepl Created
  36. --*/
  37. static const INT aPerfControls[] =
  38. {
  39. IDC_STATIC1,
  40. IDC_STATIC2,
  41. IDC_STATIC3,
  42. IDC_STATIC4,
  43. IDC_STATIC5,
  44. IDC_STATIC6,
  45. IDC_STATIC8,
  46. IDC_STATIC9,
  47. IDC_STATIC10,
  48. IDC_STATIC11,
  49. IDC_STATIC12,
  50. IDC_STATIC13,
  51. IDC_STATIC14,
  52. IDC_STATIC15,
  53. IDC_STATIC16,
  54. IDC_STATIC17,
  55. IDC_TOTAL_PHYSICAL,
  56. IDC_AVAIL_PHYSICAL,
  57. IDC_FILE_CACHE,
  58. IDC_COMMIT_TOTAL,
  59. IDC_COMMIT_LIMIT,
  60. IDC_COMMIT_PEAK,
  61. IDC_KERNEL_TOTAL,
  62. IDC_KERNEL_PAGED,
  63. IDC_KERNEL_NONPAGED,
  64. IDC_TOTAL_HANDLES,
  65. IDC_TOTAL_THREADS,
  66. IDC_TOTAL_PROCESSES,
  67. };
  68. // Amount of spacing down from the top of a group box to the
  69. // control it contains
  70. void CPerfPage::SizePerfPage()
  71. {
  72. // Get the coords of the tab control
  73. RECT rcParent;
  74. if (g_Options.m_fNoTitle)
  75. {
  76. GetClientRect(g_hMainWnd, &rcParent);
  77. }
  78. else
  79. {
  80. GetClientRect(m_hwndTabs, &rcParent);
  81. MapWindowPoints(m_hwndTabs, m_hPage, (LPPOINT) &rcParent, 2);
  82. TabCtrl_AdjustRect(m_hwndTabs, FALSE, &rcParent);
  83. }
  84. HDWP hdwp = BeginDeferWindowPos(10);
  85. if (!hdwp)
  86. return;
  87. // Calc the deltas in the x and y positions that we need to
  88. // move each of the child controls
  89. RECT rcMaster;
  90. HWND hwndMaster = GetDlgItem(m_hPage, IDC_STATIC5);
  91. GetWindowRect(hwndMaster, &rcMaster);
  92. MapWindowPoints(HWND_DESKTOP, m_hPage, (LPPOINT) &rcMaster, 2);
  93. INT dy = ((rcParent.bottom - g_DefSpacing * 2) - rcMaster.bottom);
  94. // Move each of the child controls by the above delta
  95. for (int i = 0; i < ARRAYSIZE(aPerfControls); i++)
  96. {
  97. HWND hwndCtrl = GetDlgItem(m_hPage, aPerfControls[i]);
  98. RECT rcCtrl;
  99. GetWindowRect(hwndCtrl, &rcCtrl);
  100. MapWindowPoints(HWND_DESKTOP, m_hPage, (LPPOINT) &rcCtrl, 2);
  101. DeferWindowPos(hdwp, hwndCtrl, NULL,
  102. rcCtrl.left,
  103. rcCtrl.top + dy,
  104. 0, 0,
  105. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  106. }
  107. HWND hwndTopFrame = GetDlgItem(m_hPage, IDC_STATIC13);
  108. RECT rcTopFrame;
  109. GetWindowRect(hwndTopFrame, &rcTopFrame);
  110. MapWindowPoints(HWND_DESKTOP, m_hPage, (LPPOINT) &rcTopFrame, 2);
  111. INT yTop = rcTopFrame.top + dy;
  112. INT yHist;
  113. if (g_Options.m_fNoTitle)
  114. {
  115. yHist = rcParent.bottom - rcParent.top - g_DefSpacing * 2;
  116. }
  117. else
  118. {
  119. yHist = (yTop - g_DefSpacing * 3) / 2;
  120. }
  121. // Size the CPU history frame
  122. RECT rcFrame;
  123. HWND hwndFrame = GetDlgItem(m_hPage, IDC_CPUFRAME);
  124. GetWindowRect(hwndFrame, &rcFrame);
  125. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcFrame, 2);
  126. DeferWindowPos(hdwp, hwndFrame, NULL, 0, 0,
  127. (rcParent.right - rcFrame.left) - g_DefSpacing * 2,
  128. yHist,
  129. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  130. // Size the CPU bar graph frame
  131. RECT rcCPUFrame;
  132. HWND hwndCPUFrame = GetDlgItem(m_hPage, IDC_STATIC);
  133. GetWindowRect(hwndCPUFrame, &rcCPUFrame);
  134. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcCPUFrame, 2);
  135. DeferWindowPos(hdwp, hwndCPUFrame, NULL, 0, 0,
  136. (rcCPUFrame.right - rcCPUFrame.left),
  137. yHist,
  138. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  139. RECT rcCPUBAR;
  140. HWND hwndCPUBAR = GetDlgItem(m_hPage, IDC_CPUMETER);
  141. GetWindowRect(hwndCPUBAR, &rcCPUBAR);
  142. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcCPUBAR, 2);
  143. DeferWindowPos(hdwp, hwndCPUBAR, NULL, rcCPUFrame.left + g_InnerSpacing * 2, rcCPUFrame.top + g_TopSpacing,
  144. (rcCPUBAR.right - rcCPUBAR.left),
  145. yHist - g_TopSpacing - g_InnerSpacing * 2 ,
  146. SWP_NOZORDER | SWP_NOACTIVATE);
  147. // Size the mem bar graph frame
  148. RECT rcMEMFrame;
  149. HWND hwndMEMFrame = GetDlgItem(m_hPage, IDC_MEMBARFRAME);
  150. GetWindowRect(hwndMEMFrame, &rcMEMFrame);
  151. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcMEMFrame, 2);
  152. DeferWindowPos(hdwp, hwndMEMFrame, NULL, rcMEMFrame.left, yHist + g_DefSpacing * 2,
  153. (rcMEMFrame.right - rcMEMFrame.left),
  154. yHist,
  155. SWP_NOZORDER | SWP_NOACTIVATE);
  156. RECT rcMEMBAR;
  157. HWND hwndMEMBAR = GetDlgItem(m_hPage, IDC_MEMMETER);
  158. GetWindowRect(hwndMEMBAR, &rcMEMBAR);
  159. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcMEMBAR, 2);
  160. DeferWindowPos(hdwp, hwndMEMBAR, NULL, rcMEMBAR.left, yHist + g_DefSpacing * 2 + g_TopSpacing,
  161. (rcMEMBAR.right - rcMEMBAR.left),
  162. yHist - g_InnerSpacing * 2 - g_TopSpacing,
  163. SWP_NOZORDER | SWP_NOACTIVATE);
  164. // Size the Memory history frame
  165. RECT rcMemFrame;
  166. HWND hwndMemFrame = GetDlgItem(m_hPage, IDC_MEMFRAME);
  167. GetWindowRect(hwndMemFrame, &rcMemFrame);
  168. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcMemFrame, 2);
  169. DeferWindowPos(hdwp, hwndMemFrame, NULL, rcMemFrame.left, yHist + g_DefSpacing * 2,
  170. (rcParent.right - rcMemFrame.left) - g_DefSpacing * 2,
  171. yHist,
  172. SWP_NOZORDER | SWP_NOACTIVATE);
  173. // We have N panes, where N is 1 or g_cProcessors depending on what mode the
  174. // cpu meter is currently in
  175. INT cPanes = (CM_PANES == g_Options.m_cmHistMode) ? g_cProcessors : 1;
  176. // Total amount of room available for all of the panes
  177. INT Width = (rcParent.right - rcParent.left) - (rcFrame.left - rcParent.left) - g_DefSpacing * 2
  178. - g_InnerSpacing * 3;
  179. // Use this width to size the memory graph
  180. HWND hwndButton = GetDlgItem(m_hPage, IDC_MEMGRAPH);
  181. RECT rcButton;
  182. GetWindowRect(hwndButton, &rcButton);
  183. MapWindowPoints(NULL, m_hPage, (LPPOINT) &rcButton, 2);
  184. DeferWindowPos(hdwp, hwndButton, NULL, rcFrame.left + g_InnerSpacing * 2,
  185. yHist + g_DefSpacing * 2 + g_TopSpacing,
  186. Width - g_InnerSpacing,
  187. yHist - g_InnerSpacing * 2 - g_TopSpacing,
  188. SWP_NOZORDER | SWP_NOACTIVATE);
  189. // Total amount of room available for each CPU pane
  190. Width -= cPanes * g_InnerSpacing;
  191. Width /= cPanes;
  192. Width = Width >= 0 ? Width : 0;
  193. for (i = 0; i < cPanes; i++)
  194. {
  195. HWND hwndButton = GetDlgItem(m_hPage, IDC_CPUGRAPH + i);
  196. INT left = rcFrame.left + g_InnerSpacing * (i + 2) + Width * i;
  197. DeferWindowPos(hdwp,
  198. hwndButton,
  199. NULL,
  200. left, rcFrame.top + g_TopSpacing,
  201. Width,
  202. yHist - g_InnerSpacing * 2 -g_TopSpacing,
  203. 0 );
  204. }
  205. // Create new bitmaps to be used in the history windows
  206. EndDeferWindowPos(hdwp);
  207. GetClientRect(hwndButton, &rcButton);
  208. FreeMemoryBitmaps(); // Free any old ones
  209. CreateMemoryBitmaps(rcButton.right - rcButton.left, rcButton.bottom - rcButton.top);
  210. }
  211. /*++ CPerfPage::CreatePens
  212. Routine Description:
  213. Creates 8 different colors pens, saves them in
  214. the pen array
  215. Arguments:
  216. Return Value:
  217. Revision History:
  218. Nov-12-95 Davepl Created
  219. --*/
  220. static const COLORREF aColors[] =
  221. {
  222. RGB(000, 255, 000),
  223. RGB(255, 000, 000),
  224. RGB(255, 000, 255),
  225. RGB(000, 000, 255),
  226. RGB(000, 255, 255),
  227. RGB(255, 128, 000),
  228. RGB(255, 000, 255),
  229. RGB(000, 128, 255),
  230. // End of CPU pens
  231. #define MEM_PEN 8
  232. RGB(255, 255, 0),
  233. };
  234. void CPerfPage::CreatePens()
  235. {
  236. for (int i = 0; i < ARRAYSIZE(aColors); i++)
  237. {
  238. // Create then pen. If a failure occurs, just substitute
  239. // the white pen
  240. m_hPens[i] = CreatePen(PS_SOLID, 1, aColors[i]);
  241. if (NULL == m_hPens[i])
  242. {
  243. m_hPens[i] = (HPEN) GetStockObject(WHITE_PEN);
  244. }
  245. }
  246. }
  247. void CPerfPage::ReleasePens()
  248. {
  249. for (int i = 0; i < NUM_PENS; i++)
  250. {
  251. if (m_hPens[i])
  252. {
  253. DeleteObject(m_hPens[i]);
  254. }
  255. }
  256. }
  257. /*++ CPerfPage::DrawGraphPaper
  258. Routine Description:
  259. Draws a graph-paper-like grid into a memory bitmap
  260. Arguments:
  261. hdcGraph - HDC to draw into
  262. prcGraph - RECT describing area to draw
  263. Width - Amount, on right side, to actually draw
  264. Revision History:
  265. Jan-17-95 Davepl Created
  266. --*/
  267. static int g_Scrollamount = 0;
  268. void DrawGraphPaper(HDC hdcGraph, RECT * prcGraph, int Width)
  269. {
  270. #define GRAPHPAPERSIZE 12
  271. int Leftside = prcGraph->right - Width;
  272. // Only one of the many graphs needs to ask us to scroll
  273. HPEN hPen = CreatePen(PS_SOLID, 1, GRAPH_LINE_COLOR);
  274. HGDIOBJ hOld = SelectObject(hdcGraph, hPen);
  275. for (int i = GRAPHPAPERSIZE - 1; i < prcGraph->bottom - prcGraph->top; i+= GRAPHPAPERSIZE)
  276. {
  277. MoveToEx(hdcGraph,
  278. Leftside,
  279. i + prcGraph->top,
  280. (LPPOINT) NULL);
  281. LineTo(hdcGraph,
  282. prcGraph->right,
  283. i + prcGraph->top);
  284. }
  285. for (i = prcGraph->right - g_Scrollamount; i > Leftside; i -= GRAPHPAPERSIZE)
  286. {
  287. MoveToEx(hdcGraph,
  288. i,
  289. prcGraph->top,
  290. (LPPOINT) NULL);
  291. LineTo(hdcGraph,
  292. i,
  293. prcGraph->bottom);
  294. }
  295. if (hOld)
  296. {
  297. SelectObject(hdcGraph, hOld);
  298. }
  299. DeleteObject(hPen);
  300. }
  301. /*++ CPerfPage::TextToLegend
  302. Routine Description:
  303. Given the DC, an X, a Y, and a string, writes that string out
  304. to the legend and returns the new X.
  305. Return Value:
  306. New X pos in the legend
  307. Revision History:
  308. Jan-18-95 Davepl Created
  309. --*/
  310. int CPerfPage::TextToLegend(HDC hDC, int xPos, int yPos, LPCTSTR szCPUName)
  311. {
  312. int cchText = lstrlen(szCPUName);
  313. TextOut(hDC, xPos, yPos, szCPUName, cchText);
  314. SIZE size;
  315. GetTextExtentPoint32(hDC, szCPUName, cchText, &size);
  316. return xPos + size.cx;
  317. }
  318. /*++ CPerfPage::DrawCPUGraph
  319. Routine Description:
  320. Draws the CPU graph (which is an ownerdraw control)
  321. Arguments:
  322. lpdi - LPDRAWITEMSTRUCT describing area we need to paint
  323. iPane - Pane number to be drawn (ie: which CPU)
  324. Return Value:
  325. Revision History:
  326. Nov-12-95 Davepl Created
  327. --*/
  328. void CPerfPage::DrawCPUGraph(LPDRAWITEMSTRUCT lpdi, UINT iPane)
  329. {
  330. #define THISCPU 0
  331. if (NULL == m_hdcGraph)
  332. {
  333. return;
  334. }
  335. FillRect(m_hdcGraph, &m_rcGraph, (HBRUSH) GetStockObject(GRAPH_BRUSH));
  336. int Width = lpdi->rcItem.right - lpdi->rcItem.left;
  337. int Scale = (Width - 1) / HIST_SIZE;
  338. if (0 == Scale)
  339. {
  340. Scale = 2;
  341. }
  342. // Draw the CPU history graph
  343. DrawGraphPaper(m_hdcGraph, &m_rcGraph, Width);
  344. int GraphHeight = m_rcGraph.bottom - m_rcGraph.top - 1;
  345. // int GraphWidth = m_rcGraph.right - m_rcGraph.left + 1;
  346. if (g_Options.m_cmHistMode == CM_PANES)
  347. {
  348. // Draw the kernel times
  349. if (g_Options.m_fKernelTimes)
  350. {
  351. HGDIOBJ hOld = SelectObject(m_hdcGraph, m_hPens[1]);
  352. MoveToEx(m_hdcGraph,
  353. m_rcGraph.right,
  354. m_rcGraph.bottom - (g_pKernelHistory[iPane][0] * GraphHeight) / 100,
  355. (LPPOINT) NULL);
  356. for (int i = 0; i < HIST_SIZE && i * Scale < Width; i++)
  357. {
  358. LineTo(m_hdcGraph,
  359. m_rcGraph.right - Scale * i,
  360. m_rcGraph.bottom - (g_pKernelHistory[iPane][i] * GraphHeight) / 100);
  361. }
  362. if (hOld)
  363. SelectObject(m_hdcGraph, hOld);
  364. }
  365. // Draw a particular CPU in its pane
  366. HGDIOBJ hOld = SelectObject(m_hdcGraph, m_hPens[0]);
  367. MoveToEx(m_hdcGraph,
  368. m_rcGraph.right,
  369. m_rcGraph.bottom - (g_pCPUHistory[iPane][0] * GraphHeight) / 100,
  370. (LPPOINT) NULL);
  371. for (int i = 0; i < HIST_SIZE && i * Scale < Width; i++)
  372. {
  373. LineTo(m_hdcGraph,
  374. m_rcGraph.right - Scale * i,
  375. m_rcGraph.bottom - (g_pCPUHistory[iPane][i] * GraphHeight) / 100);
  376. }
  377. if (hOld)
  378. SelectObject(m_hdcGraph, hOld);
  379. }
  380. else
  381. {
  382. ASSERT(iPane == 0);
  383. // Draw the kernel times
  384. if (g_Options.m_fKernelTimes)
  385. {
  386. HGDIOBJ hOld = SelectObject(m_hdcGraph, m_hPens[1]);
  387. DWORD dwSum = 0;
  388. for (int iCPU = 0; iCPU < g_cProcessors; iCPU++)
  389. {
  390. dwSum += g_pKernelHistory[iCPU][0];
  391. }
  392. dwSum /= g_cProcessors;
  393. MoveToEx(m_hdcGraph,
  394. m_rcGraph.right,
  395. m_rcGraph.bottom - (dwSum * GraphHeight) / 100,
  396. (LPPOINT) NULL);
  397. for (int i = 0; i < HIST_SIZE && i * Scale < Width; i++)
  398. {
  399. dwSum = 0;
  400. for (iCPU = 0; iCPU < g_cProcessors; iCPU++)
  401. {
  402. dwSum += g_pKernelHistory[iCPU][i];
  403. }
  404. dwSum /= g_cProcessors;
  405. LineTo(m_hdcGraph,
  406. m_rcGraph.right - Scale * i,
  407. m_rcGraph.bottom - (dwSum * GraphHeight) / 100);
  408. }
  409. if (hOld)
  410. SelectObject(m_hdcGraph, hOld);
  411. }
  412. // Draw History as a sum of all CPUs
  413. HGDIOBJ hOld = SelectObject(m_hdcGraph, m_hPens[0]);
  414. DWORD dwSum = 0;
  415. for (int iCPU = 0; iCPU < g_cProcessors; iCPU++)
  416. {
  417. dwSum += g_pCPUHistory[iCPU][0];
  418. }
  419. dwSum /= g_cProcessors;
  420. MoveToEx(m_hdcGraph,
  421. m_rcGraph.right,
  422. m_rcGraph.bottom - (dwSum * GraphHeight) / 100,
  423. (LPPOINT) NULL);
  424. for (int i = 0; i < HIST_SIZE && i * Scale < Width; i++)
  425. {
  426. dwSum = 0;
  427. for (iCPU = 0; iCPU < g_cProcessors; iCPU++)
  428. {
  429. dwSum += g_pCPUHistory[iCPU][i];
  430. }
  431. dwSum /= g_cProcessors;
  432. LineTo(m_hdcGraph,
  433. m_rcGraph.right - Scale * i,
  434. m_rcGraph.bottom - (dwSum * GraphHeight) / 100);
  435. }
  436. if (hOld)
  437. SelectObject(m_hdcGraph, hOld);
  438. }
  439. // Memory bitmap could be wider than the target control, so find a delta
  440. INT xDiff = (m_rcGraph.right - m_rcGraph.left) - (lpdi->rcItem.right - lpdi->rcItem.left);
  441. BitBlt( lpdi->hDC,
  442. lpdi->rcItem.left,
  443. lpdi->rcItem.top,
  444. lpdi->rcItem.right - lpdi->rcItem.left,
  445. lpdi->rcItem.bottom - lpdi->rcItem.top,
  446. m_hdcGraph,
  447. xDiff,
  448. 0,
  449. SRCCOPY);
  450. }
  451. /*++ CPerfPage::DrawMEMGraph
  452. Routine Description:
  453. Draws the Memory history graph (which is an ownerdraw control)
  454. Arguments:
  455. lpdi - LPDRAWITEMSTRUCT describing area we need to paint
  456. Return Value:
  457. Revision History:
  458. Nov-12-95 Davepl Created
  459. --*/
  460. void CPerfPage::DrawMEMGraph(LPDRAWITEMSTRUCT lpdi)
  461. {
  462. #define THISCPU 0
  463. if (NULL == m_hdcGraph)
  464. {
  465. return;
  466. }
  467. FillRect(m_hdcGraph, &m_rcGraph, (HBRUSH) GetStockObject(GRAPH_BRUSH));
  468. int Width = lpdi->rcItem.right - lpdi->rcItem.left;
  469. DrawGraphPaper(m_hdcGraph, &m_rcGraph, Width);
  470. int Scale = (Width - 1) / HIST_SIZE;
  471. if (0 == Scale)
  472. {
  473. Scale = 2;
  474. }
  475. int GraphHeight = m_rcGraph.bottom - m_rcGraph.top - 1;
  476. HGDIOBJ hOld = SelectObject(m_hdcGraph, m_hPens[MEM_PEN]);
  477. MoveToEx(m_hdcGraph,
  478. m_rcGraph.right,
  479. m_rcGraph.bottom - (g_pMEMHistory[0] * GraphHeight) / 100,
  480. (LPPOINT) NULL);
  481. for (int i = 0; i < HIST_SIZE && i * Scale < Width - 1; i++)
  482. {
  483. if (0 == g_pMEMHistory[i])
  484. {
  485. break; // End of Data
  486. }
  487. LineTo(m_hdcGraph,
  488. m_rcGraph.right - Scale * i,
  489. m_rcGraph.bottom - (g_pMEMHistory[i] * GraphHeight) / 100);
  490. }
  491. BitBlt( lpdi->hDC,
  492. lpdi->rcItem.left,
  493. lpdi->rcItem.top,
  494. lpdi->rcItem.right - lpdi->rcItem.left,
  495. lpdi->rcItem.bottom - lpdi->rcItem.top,
  496. m_hdcGraph,
  497. 0,
  498. 0,
  499. SRCCOPY);
  500. if (hOld)
  501. SelectObject(m_hdcGraph, hOld);
  502. }
  503. /*++ CPerfPage::UpdateGraphs
  504. Routine Description:
  505. Adds and removed CPU panes as required
  506. Arguments:
  507. none
  508. Return Value:
  509. none
  510. Revision History:
  511. Dec-16-96 Davepl Create
  512. ***/
  513. // WARNING: CPU pane IDs must be contiguous in resource.h
  514. #define ID_FIRSTPANE IDC_CPUGRAPH
  515. #define ID_LASTPANE IDC_CPUGRAPH32
  516. #define NUMPANES 32
  517. void CPerfPage::UpdateGraphs()
  518. {
  519. // WARNING: CPU pane IDs must be contiguous in resource.h
  520. ASSERT(ID_LASTPANE - ID_FIRSTPANE == (NUMPANES - 1));
  521. // Turn the extra windows on or off as required
  522. for (UINT i = 1; i < g_cProcessors && i < NUMPANES; i++)
  523. {
  524. ShowWindow(GetDlgItem(m_hPage, ID_FIRSTPANE + i),
  525. CM_PANES == g_Options.m_cmHistMode ? SW_SHOW : SW_HIDE);
  526. }
  527. // Hide/show everything but the CPU meters when we're in notitle/title mode
  528. for (i = 0; i < ARRAYSIZE(aPerfControls); i++)
  529. {
  530. ShowWindow(GetDlgItem(m_hPage, aPerfControls[i]), g_Options.m_fNoTitle ? SW_HIDE : SW_SHOW);
  531. }
  532. ShowWindow(GetDlgItem(m_hPage, IDC_MEMGRAPH), g_Options.m_fNoTitle ? SW_HIDE : SW_SHOW);
  533. ShowWindow(GetDlgItem(m_hPage, IDC_MEMFRAME), g_Options.m_fNoTitle ? SW_HIDE : SW_SHOW);
  534. ShowWindow(GetDlgItem(m_hPage, IDC_MEMBARFRAME), g_Options.m_fNoTitle ? SW_HIDE : SW_SHOW);
  535. ShowWindow(GetDlgItem(m_hPage, IDC_MEMMETER), g_Options.m_fNoTitle ? SW_HIDE : SW_SHOW);
  536. SizePerfPage();
  537. }
  538. /*++ CPerfPage::DrawCPUDigits
  539. Routine Description:
  540. Draws the CPU meter and digits
  541. Arguments:
  542. lpdi - LPDRAWITEMSTRUCT describing area we need to paint
  543. Return Value:
  544. Revision History:
  545. Nov-12-95 Davepl Created
  546. --*/
  547. int GetCurFontSize(HDC hdc)
  548. {
  549. int iRet = 0;
  550. LOGFONT lf;
  551. HFONT hf = (HFONT) GetCurrentObject(hdc, OBJ_FONT);
  552. if (hf)
  553. {
  554. if (GetObject(hf, sizeof(LOGFONT), &lf))
  555. {
  556. iRet = lf.lfHeight;
  557. if (iRet < 0) iRet = (-iRet);
  558. }
  559. }
  560. return iRet;
  561. }
  562. void CPerfPage::DrawCPUDigits(LPDRAWITEMSTRUCT lpdi)
  563. {
  564. HBRUSH hBlack = (HBRUSH) GetStockObject(BLACK_BRUSH);
  565. HGDIOBJ hOld = SelectObject(lpdi->hDC, hBlack);
  566. Rectangle(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, lpdi->rcItem.right, lpdi->rcItem.bottom);
  567. // Draw the digits into the ownder draw control
  568. INT xBarOffset = ((lpdi->rcItem.right - lpdi->rcItem.left) - STRIP_WIDTH) / 2;
  569. RECT rcBar;
  570. GetWindowRect(GetDlgItem(m_hPage, IDC_MEMMETER), &rcBar);
  571. INT cBarHeight = lpdi->rcItem.bottom - lpdi->rcItem.top - (GetCurFontSize(lpdi->hDC) + g_DefSpacing * 3);
  572. if (cBarHeight <= 0)
  573. {
  574. return;
  575. }
  576. INT ctmpBarLitPixels = (g_CPUUsage * cBarHeight) / 100;
  577. INT ctmpBarRedPixels = g_Options.m_fKernelTimes ? ctmpBarRedPixels = (g_KernelUsage * cBarHeight) / 100 : 0;
  578. INT cBarUnLitPixels = cBarHeight - ctmpBarLitPixels;
  579. cBarUnLitPixels = (cBarUnLitPixels / 3) * 3;
  580. INT cBarLitPixels = cBarHeight - cBarUnLitPixels;
  581. INT cBarRedPixels = ctmpBarRedPixels;
  582. SetBkMode(lpdi->hDC, TRANSPARENT);
  583. SetTextColor(lpdi->hDC, GRAPH_TEXT_COLOR);
  584. TCHAR szBuf[8];
  585. wsprintf(szBuf, TEXT("%d %%"), g_CPUUsage);
  586. RECT rcOut = lpdi->rcItem;
  587. rcOut.bottom -= 4;
  588. DrawText(lpdi->hDC, szBuf, -1, &rcOut, DT_SINGLELINE | DT_CENTER | DT_BOTTOM);
  589. HDC hdcMem = CreateCompatibleDC(lpdi->hDC);
  590. if (hdcMem)
  591. {
  592. // Draw the CPU meter
  593. // Draw unlit portion
  594. if (cBarHeight != cBarLitPixels)
  595. {
  596. INT cUnlit = cBarHeight - cBarLitPixels;
  597. INT cOffset = 0;
  598. SelectObject(hdcMem, m_hStripUnlit);
  599. while (cUnlit > 0)
  600. {
  601. BitBlt(lpdi->hDC, xBarOffset, g_DefSpacing + cOffset,
  602. STRIP_WIDTH, min(cUnlit, STRIP_HEIGHT),
  603. hdcMem,
  604. 0, 0, SRCCOPY);
  605. cOffset += min(cUnlit, STRIP_HEIGHT);
  606. cUnlit -= min(cUnlit, STRIP_HEIGHT);
  607. }
  608. };
  609. // Draw lit portion
  610. if (0 != cBarLitPixels)
  611. {
  612. SelectObject(hdcMem, m_hStripLit);
  613. INT cOffset = 0;
  614. INT cLit = cBarLitPixels - cBarRedPixels;
  615. while (cLit > 0)
  616. {
  617. BitBlt(lpdi->hDC, xBarOffset, g_DefSpacing + (cBarHeight - cBarLitPixels) + cOffset,
  618. STRIP_WIDTH, min(STRIP_HEIGHT, cLit),
  619. hdcMem,
  620. 0, 0, SRCCOPY);
  621. cOffset += min(cLit, STRIP_HEIGHT);
  622. cLit -= min(cLit, STRIP_HEIGHT);
  623. }
  624. }
  625. if (0 != cBarRedPixels)
  626. {
  627. SelectObject(hdcMem, m_hStripLitRed);
  628. INT cOffset = 0;
  629. INT cRed = cBarRedPixels;
  630. while (cRed > 0)
  631. {
  632. BitBlt(lpdi->hDC, xBarOffset, g_DefSpacing + (cBarHeight - cBarRedPixels) + cOffset,
  633. STRIP_WIDTH, min(cRed, STRIP_HEIGHT),
  634. hdcMem,
  635. 0, 0, SRCCOPY);
  636. cOffset += min(cRed, STRIP_HEIGHT);
  637. cRed -= min(cRed, STRIP_HEIGHT);
  638. }
  639. }
  640. DeleteDC(hdcMem);
  641. }
  642. SelectObject(lpdi->hDC, hOld);
  643. }
  644. // CPerfPage::DrawMEMMeter
  645. //
  646. // Draws the memory meter
  647. void CPerfPage::DrawMEMMeter(LPDRAWITEMSTRUCT lpdi)
  648. {
  649. HBRUSH hBlack = (HBRUSH) GetStockObject(BLACK_BRUSH);
  650. HGDIOBJ hOld = SelectObject(lpdi->hDC, hBlack);
  651. Rectangle(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, lpdi->rcItem.right, lpdi->rcItem.bottom);
  652. INT xBarOffset = ((lpdi->rcItem.right - lpdi->rcItem.left) - STRIP_WIDTH) / 2;
  653. SetBkMode(lpdi->hDC, TRANSPARENT);
  654. SetTextColor(lpdi->hDC, GRAPH_TEXT_COLOR);
  655. TCHAR szBuf[32];
  656. StrFormatByteSize64( g_MEMUsage * 1024, szBuf, ARRAYSIZE(szBuf) );
  657. RECT rcOut = lpdi->rcItem;
  658. rcOut.bottom -= 4;
  659. DrawText(lpdi->hDC, szBuf, -1, &rcOut, DT_SINGLELINE | DT_CENTER | DT_BOTTOM);
  660. HDC hdcMem = CreateCompatibleDC(lpdi->hDC);
  661. if (hdcMem)
  662. {
  663. // Draw the CPU meter
  664. // Draw unlit portion
  665. INT cBarHeight = lpdi->rcItem.bottom - lpdi->rcItem.top - (GetCurFontSize(lpdi->hDC) + g_DefSpacing * 3);
  666. if (cBarHeight > 0)
  667. {
  668. INT cBarLitPixels = (INT)(( g_MEMUsage * cBarHeight ) / g_MEMMax);
  669. cBarLitPixels = (cBarLitPixels / 3) * 3;
  670. // INT cBarUnlitPixels = cBarHeight - cBarLitPixels;
  671. if (cBarHeight != cBarLitPixels)
  672. {
  673. SelectObject(hdcMem, m_hStripUnlit);
  674. INT cUnlit = cBarHeight - cBarLitPixels;
  675. INT cOffset = 0;
  676. while (cUnlit > 0)
  677. {
  678. BitBlt(lpdi->hDC, xBarOffset, g_DefSpacing + cOffset,
  679. STRIP_WIDTH, min(cUnlit, STRIP_HEIGHT),
  680. hdcMem,
  681. 0, 0, SRCCOPY);
  682. cOffset += min(cUnlit, STRIP_HEIGHT);
  683. cUnlit -= min(cUnlit, STRIP_HEIGHT);
  684. }
  685. };
  686. // Draw lit portion
  687. if (0 != cBarLitPixels)
  688. {
  689. SelectObject(hdcMem, m_hStripLit);
  690. INT cOffset = 0;
  691. INT cLit = cBarLitPixels;
  692. while (cLit > 0)
  693. {
  694. BitBlt(lpdi->hDC, xBarOffset, g_DefSpacing + (cBarHeight - cBarLitPixels) + cOffset,
  695. STRIP_WIDTH, min(STRIP_HEIGHT, cLit),
  696. hdcMem,
  697. 0, 0, SRCCOPY);
  698. cOffset += min(cLit, STRIP_HEIGHT);
  699. cLit -= min(cLit, STRIP_HEIGHT);
  700. }
  701. }
  702. }
  703. DeleteDC(hdcMem);
  704. }
  705. SelectObject(lpdi->hDC, hOld);
  706. }
  707. /*++ CPerfPage::TimerEvent
  708. Routine Description:
  709. Called by main app when the update time fires
  710. Arguments:
  711. Return Value:
  712. Revision History:
  713. Nov-12-95 Davepl Created
  714. --*/
  715. void CPerfPage::TimerEvent()
  716. {
  717. CalcCpuTime(TRUE);
  718. g_Scrollamount+=2;
  719. g_Scrollamount %= GRAPHPAPERSIZE;
  720. // Force the displays to update
  721. if (FALSE == IsIconic(g_hMainWnd))
  722. {
  723. InvalidateRect(GetDlgItem(m_hPage, IDC_CPUMETER), NULL, FALSE);
  724. UpdateWindow(GetDlgItem(m_hPage, IDC_CPUMETER));
  725. InvalidateRect(GetDlgItem(m_hPage, IDC_MEMMETER), NULL, FALSE);
  726. UpdateWindow(GetDlgItem(m_hPage, IDC_MEMMETER));
  727. for (UINT i = 0; i < g_cProcessors; i++)
  728. {
  729. InvalidateRect(GetDlgItem(m_hPage, ID_FIRSTPANE + i), NULL, FALSE);
  730. UpdateWindow(GetDlgItem(m_hPage, ID_FIRSTPANE + i));
  731. if (CM_PANES != g_Options.m_cmHistMode)
  732. {
  733. // If we're not in multipane mode, we can stop after the first graph
  734. break;
  735. }
  736. }
  737. InvalidateRect(GetDlgItem(m_hPage, IDC_MEMGRAPH), NULL, FALSE);
  738. UpdateWindow(GetDlgItem(m_hPage, IDC_MEMGRAPH));
  739. }
  740. }
  741. /*++ PerfPageProc
  742. Routine Description:
  743. Dialogproc for the performance page.
  744. Arguments:
  745. hwnd - handle to dialog box
  746. uMsg - message
  747. wParam - first message parameter
  748. lParam - second message parameter
  749. Return Value:
  750. For WM_INITDIALOG, TRUE == user32 sets focus, FALSE == we set focus
  751. For others, TRUE == this proc handles the message
  752. Revision History:
  753. Nov-12-95 Davepl Created
  754. --*/
  755. INT_PTR CALLBACK PerfPageProc(
  756. HWND hwnd, // handle to dialog box
  757. UINT uMsg, // message
  758. WPARAM wParam, // first message parameter
  759. LPARAM lParam // second message parameter
  760. )
  761. {
  762. CPerfPage * thispage = (CPerfPage *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  763. // See if the parent wants this message
  764. if (TRUE == CheckParentDeferrals(uMsg, wParam, lParam))
  765. {
  766. return TRUE;
  767. }
  768. switch(uMsg)
  769. {
  770. case WM_INITDIALOG:
  771. {
  772. SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
  773. // CPerfPage * thispage = (CPerfPage *) lParam;
  774. DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  775. dwStyle |= WS_CLIPCHILDREN;
  776. SetWindowLong(hwnd, GWL_STYLE, dwStyle);
  777. if (IS_WINDOW_RTL_MIRRORED(hwnd))
  778. {
  779. HWND hItem;
  780. LONG lExtStyle;
  781. hItem = GetDlgItem(hwnd,IDC_CPUMETER);
  782. lExtStyle = GetWindowLong(hItem,GWL_EXSTYLE);
  783. SetWindowLong(hItem,GWL_EXSTYLE, lExtStyle & ~(RTL_MIRRORED_WINDOW | RTL_NOINHERITLAYOUT));
  784. hItem = GetDlgItem(hwnd,IDC_MEMMETER);
  785. lExtStyle = GetWindowLong(hItem,GWL_EXSTYLE);
  786. SetWindowLong(hItem,GWL_EXSTYLE, lExtStyle & ~(dwExStyleRTLMirrorWnd | dwExStyleNoInheritLayout));
  787. }
  788. // We handle focus during Activate(). Return FALSE here so the
  789. // dialog manager doesn't try to set focus.
  790. return FALSE;
  791. }
  792. // We need to fake client mouse clicks in this child to appear as nonclient
  793. // (caption) clicks in the parent so that the user can drag the entire app
  794. // when the title bar is hidden by dragging the client area of this child
  795. case WM_LBUTTONUP:
  796. case WM_LBUTTONDOWN:
  797. {
  798. if (g_Options.m_fNoTitle)
  799. {
  800. SendMessage(g_hMainWnd,
  801. uMsg == WM_LBUTTONUP ? WM_NCLBUTTONUP : WM_NCLBUTTONDOWN,
  802. HTCAPTION,
  803. lParam);
  804. }
  805. break;
  806. }
  807. case WM_NCLBUTTONDBLCLK:
  808. case WM_LBUTTONDBLCLK:
  809. {
  810. SendMessage(g_hMainWnd, uMsg, wParam, lParam);
  811. break;
  812. }
  813. case WM_CTLCOLORBTN:
  814. {
  815. const static int rgGraphs[] =
  816. {
  817. IDC_MEMGRAPH,
  818. IDC_MEMMETER,
  819. IDC_CPUMETER
  820. };
  821. for (int i = 0; i < ARRAYSIZE(rgGraphs); i++)
  822. {
  823. if (lParam == (LPARAM) GetDlgItem(hwnd, rgGraphs[i]))
  824. {
  825. return (INT_PTR) GetStockObject(GRAPH_BRUSH);
  826. }
  827. }
  828. // All CPU graphs should use the GRAPH_BRUSH
  829. if (GetDlgCtrlID((HWND)lParam) >= ID_FIRSTPANE && GetDlgCtrlID((HWND)lParam) <= ID_LASTPANE)
  830. return (INT_PTR) GetStockObject(GRAPH_BRUSH);
  831. break;
  832. }
  833. // Size our kids
  834. case WM_SIZE:
  835. thispage->SizePerfPage();
  836. return FALSE;
  837. // Draw one of our owner draw controls
  838. case WM_DRAWITEM:
  839. {
  840. if (wParam >= ID_FIRSTPANE && wParam <= ID_LASTPANE)
  841. {
  842. thispage->DrawCPUGraph( (LPDRAWITEMSTRUCT) lParam, (UINT)wParam - ID_FIRSTPANE);
  843. return TRUE;
  844. }
  845. else if (IDC_CPUMETER == wParam)
  846. {
  847. thispage->DrawCPUDigits( (LPDRAWITEMSTRUCT) lParam);
  848. return TRUE;
  849. }
  850. else if (IDC_MEMMETER == wParam)
  851. {
  852. thispage->DrawMEMMeter( (LPDRAWITEMSTRUCT) lParam);
  853. return TRUE;
  854. }
  855. else if (IDC_MEMGRAPH == wParam)
  856. {
  857. thispage->DrawMEMGraph( (LPDRAWITEMSTRUCT) lParam);
  858. return TRUE;
  859. }
  860. break;
  861. }
  862. default:
  863. return FALSE;
  864. }
  865. return FALSE;
  866. }
  867. /*++ CPerfPage::GetTitle
  868. Routine Description:
  869. Copies the title of this page to the caller-supplied buffer
  870. Arguments:
  871. pszText - the buffer to copy to
  872. bufsize - size of buffer, in characters
  873. Return Value:
  874. Revision History:
  875. Nov-12-95 Davepl Created
  876. --*/
  877. void CPerfPage::GetTitle(LPTSTR pszText, size_t bufsize)
  878. {
  879. LoadString(g_hInstance, IDS_PERFPAGETITLE, pszText, static_cast<int>(bufsize));
  880. }
  881. /*++ CPerfPage::Activate
  882. Routine Description:
  883. Brings this page to the front, sets its initial position,
  884. and shows it
  885. Arguments:
  886. Return Value:
  887. HRESULT (S_OK on success)
  888. Revision History:
  889. Nov-12-95 Davepl Created
  890. --*/
  891. HRESULT CPerfPage::Activate()
  892. {
  893. // Adjust the size and position of our dialog relative
  894. // to the tab control which "owns" us
  895. RECT rcParent;
  896. GetClientRect(m_hwndTabs, &rcParent);
  897. MapWindowPoints(m_hwndTabs, g_hMainWnd, (LPPOINT) &rcParent, 2);
  898. TabCtrl_AdjustRect(m_hwndTabs, FALSE, &rcParent);
  899. SetWindowPos(m_hPage,
  900. HWND_TOP,
  901. rcParent.left, rcParent.top,
  902. rcParent.right - rcParent.left, rcParent.bottom - rcParent.top,
  903. 0);
  904. // Make this page visible
  905. ShowWindow(m_hPage, SW_SHOW);
  906. // Make the CPU graphs visible or invisible depending on its current mode
  907. UpdateGraphs();
  908. // Change the menu bar to be the menu for this page
  909. HMENU hMenuOld = GetMenu(g_hMainWnd);
  910. HMENU hMenuNew = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MAINMENU_PERF));
  911. AdjustMenuBar(hMenuNew);
  912. if (hMenuNew && SHRestricted(REST_NORUN))
  913. {
  914. DeleteMenu(hMenuNew, IDM_RUN, MF_BYCOMMAND);
  915. }
  916. g_hMenu = hMenuNew;
  917. if (g_Options.m_fNoTitle == FALSE)
  918. {
  919. SetMenu(g_hMainWnd, hMenuNew);
  920. }
  921. if (hMenuOld)
  922. {
  923. DestroyMenu(hMenuOld);
  924. }
  925. // There are no tabstops on this page, but we have to set focus somewhere.
  926. // If we don't, it may stay on the previous page, now hidden, which can
  927. // confuse the dialog manager and may cause us to hang.
  928. SetFocus(m_hwndTabs);
  929. return S_OK;
  930. }
  931. /*++ CPerfPage::Initialize
  932. Routine Description:
  933. Loads the resources we need for this page, creates the inmemory DCs
  934. and bitmaps for the charts, and creates the actual window (a dialog)
  935. that represents this page
  936. Arguments:
  937. hwndParent - Parent on which to base sizing on: not used for creation,
  938. since the main app window is always used as the parent in
  939. order to keep tab order correct
  940. Return Value:
  941. Revision History:
  942. Nov-12-95 Davepl Created
  943. --*/
  944. HRESULT CPerfPage::Initialize(HWND hwndParent)
  945. {
  946. // Our pseudo-parent is the tab contrl, and is what we base our
  947. // sizing on. However, in order to keep tab order right among
  948. // the controls, we actually create ourselves with the main
  949. // window as the parent
  950. m_hwndTabs = hwndParent;
  951. // Create the color pens
  952. CreatePens();
  953. m_hStripLit = (HBITMAP) LoadImage(g_hInstance, MAKEINTRESOURCE(LED_STRIP_LIT),
  954. IMAGE_BITMAP,
  955. 0, 0,
  956. LR_DEFAULTCOLOR);
  957. m_hStripLitRed = (HBITMAP) LoadImage(g_hInstance, MAKEINTRESOURCE(LED_STRIP_LIT_RED),
  958. IMAGE_BITMAP,
  959. 0, 0,
  960. LR_DEFAULTCOLOR);
  961. m_hStripUnlit = (HBITMAP) LoadImage(g_hInstance, MAKEINTRESOURCE(LED_STRIP_UNLIT),
  962. IMAGE_BITMAP,
  963. 0, 0,
  964. LR_DEFAULTCOLOR);
  965. //
  966. // Create the dialog which represents the body of this page
  967. //
  968. m_hPage = CreateDialogParam(
  969. g_hInstance, // handle to application instance
  970. MAKEINTRESOURCE(IDD_PERFPAGE), // identifies dialog box template name
  971. g_hMainWnd, // handle to owner window
  972. PerfPageProc, // pointer to dialog box procedure
  973. (LPARAM) this ); // User data (our this pointer)
  974. if (NULL == m_hPage)
  975. {
  976. return GetLastHRESULT();
  977. }
  978. return S_OK;
  979. }
  980. /*++ CPerfPage::CreateMemoryBitmaps
  981. Routine Description:
  982. Creates the inmemory bitmaps used to draw the history graphics
  983. Arguments:
  984. x, y - size of bitmap to create
  985. Return Value:
  986. Revision History:
  987. Nov-12-95 Davepl Created
  988. --*/
  989. static HGDIOBJ hOld;
  990. HRESULT CPerfPage::CreateMemoryBitmaps(int x, int y)
  991. {
  992. //
  993. // Create the inmemory bitmaps and DCs that we will use
  994. //
  995. HDC hdcPage = GetDC(m_hPage);
  996. m_hdcGraph = CreateCompatibleDC(hdcPage);
  997. if (NULL == m_hdcGraph)
  998. {
  999. ReleaseDC(m_hPage, hdcPage);
  1000. return GetLastHRESULT();
  1001. }
  1002. m_rcGraph.left = 0;
  1003. m_rcGraph.top = 0;
  1004. m_rcGraph.right = x;
  1005. m_rcGraph.bottom = y;
  1006. m_hbmpGraph = CreateCompatibleBitmap(hdcPage, x, y);
  1007. ReleaseDC(m_hPage, hdcPage);
  1008. if (NULL == m_hbmpGraph)
  1009. {
  1010. HRESULT hr = GetLastHRESULT();
  1011. DeleteDC(m_hdcGraph);
  1012. m_hdcGraph = NULL;
  1013. return hr;
  1014. }
  1015. // Select the bitmap into the DC
  1016. hOld = SelectObject(m_hdcGraph, m_hbmpGraph);
  1017. return S_OK;
  1018. }
  1019. /*++ CPerfPage::FreeMemoryBitmaps
  1020. Routine Description:
  1021. Frees the inmemory bitmaps used to drag the history graphs
  1022. Arguments:
  1023. Return Value:
  1024. Revision History:
  1025. Nov-12-95 Davepl Created
  1026. --*/
  1027. void CPerfPage::FreeMemoryBitmaps()
  1028. {
  1029. if (m_hdcGraph)
  1030. {
  1031. if (hOld)
  1032. SelectObject(m_hdcGraph, m_hbmpGraph);
  1033. DeleteDC(m_hdcGraph);
  1034. }
  1035. if (m_hbmpGraph)
  1036. {
  1037. DeleteObject(m_hbmpGraph);
  1038. }
  1039. }
  1040. /*++ CPerfPage::Deactivate
  1041. Routine Description:
  1042. Called when this page is losing its place up front
  1043. Arguments:
  1044. Return Value:
  1045. Revision History:
  1046. Nov-16-95 Davepl Created
  1047. --*/
  1048. void CPerfPage::Deactivate()
  1049. {
  1050. if (m_hPage)
  1051. {
  1052. ShowWindow(m_hPage, SW_HIDE);
  1053. }
  1054. }
  1055. /*++ CPerfPage::Destroy
  1056. Routine Description:
  1057. Frees whatever has been allocated by the Initialize call
  1058. Arguments:
  1059. Return Value:
  1060. Revision History:
  1061. Nov-12-95 Davepl Created
  1062. --*/
  1063. HRESULT CPerfPage::Destroy()
  1064. {
  1065. //
  1066. // When we are being destroyed, kill off our dialog
  1067. //
  1068. ReleasePens();
  1069. if (m_hPage)
  1070. {
  1071. DestroyWindow(m_hPage);
  1072. m_hPage = NULL;
  1073. }
  1074. if (m_hStripLit)
  1075. {
  1076. DeleteObject(m_hStripLit);
  1077. m_hStripLit = NULL;
  1078. }
  1079. if (m_hStripUnlit)
  1080. {
  1081. DeleteObject(m_hStripUnlit);
  1082. m_hStripUnlit = NULL;
  1083. }
  1084. if (m_hStripLitRed)
  1085. {
  1086. DeleteObject(m_hStripLitRed);
  1087. m_hStripLitRed = NULL;
  1088. }
  1089. if (m_hbmpGraph)
  1090. {
  1091. DeleteObject(m_hbmpGraph);
  1092. m_hbmpGraph = NULL;
  1093. }
  1094. if (m_hdcGraph)
  1095. {
  1096. DeleteDC(m_hdcGraph);
  1097. m_hdcGraph = NULL;
  1098. }
  1099. return S_OK;
  1100. }
  1101. /*++
  1102. Routine Description:
  1103. Initialize data for perf measurements
  1104. Arguments:
  1105. None
  1106. Return Value:
  1107. Number of system processors (0 if error)
  1108. Revision History:
  1109. 10-13-95 Modified from WPERF
  1110. --*/
  1111. BYTE InitPerfInfo()
  1112. {
  1113. SYSTEM_BASIC_INFORMATION BasicInfo;
  1114. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PPerfInfo;
  1115. SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfo[MAX_PROCESSOR];
  1116. int i;
  1117. NTSTATUS Status = NtQuerySystemInformation(
  1118. SystemBasicInformation,
  1119. &BasicInfo,
  1120. sizeof(BasicInfo),
  1121. NULL
  1122. );
  1123. if (!NT_SUCCESS(Status))
  1124. {
  1125. return 0;
  1126. }
  1127. g_PageSize = BasicInfo.PageSize;
  1128. g_cProcessors = BasicInfo.NumberOfProcessors;
  1129. if (g_cProcessors > MAX_PROCESSOR) {
  1130. return(0);
  1131. }
  1132. for (i = 0; i < g_cProcessors; i++)
  1133. {
  1134. g_pCPUHistory[i] = (LPBYTE) LocalAlloc(LPTR, HIST_SIZE * sizeof(LPBYTE));
  1135. if (NULL == g_pCPUHistory[i])
  1136. {
  1137. return 0;
  1138. }
  1139. g_pKernelHistory[i] = (LPBYTE) LocalAlloc(LPTR, HIST_SIZE * sizeof(LPBYTE));
  1140. if (NULL == g_pKernelHistory[i])
  1141. {
  1142. return 0;
  1143. }
  1144. }
  1145. g_pMEMHistory = (LPBYTE) LocalAlloc(LPTR, HIST_SIZE * sizeof(LPBYTE));
  1146. if (NULL == g_pMEMHistory)
  1147. {
  1148. return 0;
  1149. }
  1150. Status = NtQuerySystemInformation(
  1151. SystemProcessorPerformanceInformation,
  1152. ProcessorInfo,
  1153. sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSOR,
  1154. NULL
  1155. );
  1156. if (!NT_SUCCESS(Status))
  1157. {
  1158. return 0;
  1159. }
  1160. PPerfInfo = ProcessorInfo;
  1161. for (i=0; i < g_cProcessors; i++)
  1162. {
  1163. PreviousCPUIdleTime[i] = PPerfInfo->IdleTime;
  1164. PreviousCPUTotalTime[i].QuadPart = PPerfInfo->UserTime.QuadPart +
  1165. PPerfInfo->KernelTime.QuadPart;
  1166. PreviousCPUKernelTime[i].QuadPart = PPerfInfo->KernelTime.QuadPart +
  1167. PPerfInfo->IdleTime.QuadPart;
  1168. // PPerfInfo->IdleTime.QuadPart;
  1169. PPerfInfo++;
  1170. }
  1171. //
  1172. // Get the maximum commit limit
  1173. //
  1174. SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
  1175. Status = NtQuerySystemInformation(
  1176. SystemPerformanceInformation,
  1177. &PerfInfo,
  1178. sizeof(PerfInfo),
  1179. NULL);
  1180. if (!NT_SUCCESS(Status))
  1181. {
  1182. return 0;
  1183. }
  1184. g_MEMMax = PerfInfo.CommitLimit * ( g_PageSize / 1024 );
  1185. return(g_cProcessors);
  1186. }
  1187. /*++ ReleasePerfInfo
  1188. Routine Description:
  1189. Frees the history buffers
  1190. Arguments:
  1191. Return Value:
  1192. Revision History:
  1193. Nov-13-95 DavePl Created
  1194. --*/
  1195. void ReleasePerfInfo()
  1196. {
  1197. for (int i = 0; i < g_cProcessors; i++)
  1198. {
  1199. if (g_pCPUHistory[i])
  1200. {
  1201. LocalFree(g_pCPUHistory[i]);
  1202. g_pCPUHistory[i] = NULL;
  1203. }
  1204. if (g_pKernelHistory[i])
  1205. {
  1206. LocalFree(g_pKernelHistory[i]);
  1207. g_pKernelHistory[i] = NULL;
  1208. }
  1209. }
  1210. if (g_pMEMHistory)
  1211. {
  1212. LocalFree(g_pMEMHistory);
  1213. }
  1214. }
  1215. /*++ CalcCpuTime
  1216. Routine Description:
  1217. calculate and return %cpu time and time periods
  1218. Arguments:
  1219. None
  1220. Notes:
  1221. Revision History:
  1222. Nov-13-95 DavePl Created
  1223. --*/
  1224. void CalcCpuTime(BOOL fUpdateHistory)
  1225. {
  1226. SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfo[MAX_PROCESSOR];
  1227. LARGE_INTEGER CPUIdleTime[MAX_PROCESSOR];
  1228. LARGE_INTEGER CPUTotalTime[MAX_PROCESSOR];
  1229. LARGE_INTEGER CPUKernelTime[MAX_PROCESSOR];
  1230. LARGE_INTEGER SumIdleTime = { 0 ,0 };
  1231. LARGE_INTEGER SumTotalTime = { 0, 0 };
  1232. LARGE_INTEGER SumKernelTime = { 0, 0 };
  1233. NTSTATUS Status;
  1234. Status = NtQuerySystemInformation(
  1235. SystemProcessorPerformanceInformation,
  1236. ProcessorInfo,
  1237. sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSOR,
  1238. NULL
  1239. );
  1240. if (!NT_SUCCESS(Status))
  1241. {
  1242. return;
  1243. }
  1244. //
  1245. // Walk through the info for each CPU, and compile
  1246. //
  1247. // - Amount of time each CPU has spent idle (since last check)
  1248. // - Amount of time each CPU has spent entirely (since last check)
  1249. //
  1250. // In addition to keeping per-CPU stats, compile a sum for
  1251. //
  1252. // - Amount of time system has spent idle (since last check)
  1253. // - Amount of time that has elapsed, in total (since last check)
  1254. //
  1255. for (int ListIndex = 0; ListIndex < g_cProcessors; ListIndex++)
  1256. {
  1257. LARGE_INTEGER DeltaCPUIdleTime;
  1258. LARGE_INTEGER DeltaCPUTotalTime;
  1259. LARGE_INTEGER DeltaCPUKernelTime;
  1260. CPUIdleTime[ListIndex].QuadPart = ProcessorInfo[ListIndex].IdleTime.QuadPart;
  1261. CPUKernelTime[ListIndex].QuadPart= ProcessorInfo[ListIndex].KernelTime.QuadPart-
  1262. ProcessorInfo[ListIndex].IdleTime.QuadPart;
  1263. CPUTotalTime[ListIndex].QuadPart = ProcessorInfo[ListIndex].KernelTime.QuadPart +
  1264. ProcessorInfo[ListIndex].UserTime.QuadPart;// +
  1265. //ProcessorInfo[ListIndex].IdleTime.QuadPart;
  1266. DeltaCPUIdleTime.QuadPart = CPUIdleTime[ListIndex].QuadPart -
  1267. PreviousCPUIdleTime[ListIndex].QuadPart;
  1268. DeltaCPUKernelTime.QuadPart = CPUKernelTime[ListIndex].QuadPart -
  1269. PreviousCPUKernelTime[ListIndex].QuadPart;
  1270. DeltaCPUTotalTime.QuadPart = CPUTotalTime[ListIndex].QuadPart -
  1271. PreviousCPUTotalTime[ListIndex].QuadPart;
  1272. SumIdleTime.QuadPart += DeltaCPUIdleTime.QuadPart;
  1273. SumTotalTime.QuadPart += DeltaCPUTotalTime.QuadPart;
  1274. SumKernelTime.QuadPart += DeltaCPUKernelTime.QuadPart;
  1275. // Calc CPU Usage % for this processor, scroll the history buffer, and store
  1276. // the newly calced value at the head of the history buffer
  1277. BYTE ThisCPU;
  1278. if (DeltaCPUTotalTime.QuadPart != 0)
  1279. {
  1280. ThisCPU = static_cast<BYTE>(100 - ((DeltaCPUIdleTime.QuadPart * 100) / DeltaCPUTotalTime.QuadPart));
  1281. }
  1282. else
  1283. {
  1284. ThisCPU = 0;
  1285. }
  1286. BYTE * pbHistory = g_pCPUHistory[ListIndex];
  1287. MoveMemory((LPVOID) (pbHistory + 1),
  1288. (LPVOID) (pbHistory),
  1289. sizeof(BYTE) * (HIST_SIZE - 1) );
  1290. pbHistory[0] = ThisCPU;
  1291. BYTE ThisKernel;
  1292. if (DeltaCPUTotalTime.QuadPart != 0)
  1293. {
  1294. ThisKernel = static_cast<BYTE>(((DeltaCPUKernelTime.QuadPart * 100) / DeltaCPUTotalTime.QuadPart));
  1295. }
  1296. else
  1297. {
  1298. ThisKernel = 0;
  1299. }
  1300. pbHistory = g_pKernelHistory[ListIndex];
  1301. MoveMemory((LPVOID) (pbHistory + 1),
  1302. (LPVOID) (pbHistory),
  1303. sizeof(BYTE) * (HIST_SIZE - 1) );
  1304. pbHistory[0] = ThisKernel;
  1305. PreviousCPUTotalTime[ListIndex].QuadPart = CPUTotalTime[ListIndex].QuadPart;
  1306. PreviousCPUIdleTime[ListIndex].QuadPart = CPUIdleTime[ListIndex].QuadPart;
  1307. PreviousCPUKernelTime[ListIndex].QuadPart = CPUKernelTime[ListIndex].QuadPart;
  1308. }
  1309. if (SumTotalTime.QuadPart != 0)
  1310. {
  1311. g_CPUUsage = (BYTE) (100 - ((SumIdleTime.QuadPart * 100) / SumTotalTime.QuadPart));
  1312. }
  1313. else
  1314. {
  1315. g_CPUUsage = 0;
  1316. }
  1317. if (fUpdateHistory)
  1318. {
  1319. if (SumTotalTime.QuadPart != 0)
  1320. {
  1321. g_KernelUsage = (BYTE) ((SumKernelTime.QuadPart * 100) / SumTotalTime.QuadPart);
  1322. }
  1323. else
  1324. {
  1325. g_KernelUsage = 0;
  1326. }
  1327. //
  1328. // Get the commit size
  1329. //
  1330. SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
  1331. Status = NtQuerySystemInformation(
  1332. SystemPerformanceInformation,
  1333. &PerfInfo,
  1334. sizeof(PerfInfo),
  1335. NULL);
  1336. if (!NT_SUCCESS(Status))
  1337. {
  1338. return;
  1339. }
  1340. g_MEMUsage = PerfInfo.CommittedPages * (g_PageSize / 1024);
  1341. MoveMemory((LPVOID) (g_pMEMHistory + 1),
  1342. (LPVOID) (g_pMEMHistory),
  1343. sizeof(BYTE) * (HIST_SIZE - 1) );
  1344. g_pMEMHistory[0] = (BYTE) (( g_MEMUsage * 100 ) / g_MEMMax );
  1345. }
  1346. }