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.

1772 lines
49 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. report.cpp
  5. Abstract:
  6. Implements the report view.
  7. --*/
  8. //==========================================================================//
  9. // Includes //
  10. //==========================================================================//
  11. #include <assert.h>
  12. #include <stdio.h> // for sprintf
  13. #include <pdhmsg.h>
  14. #include "polyline.h"
  15. #include "commctrl.h"
  16. #include "winhelpr.h"
  17. #define eScaleValueSpace _T(">9999999999.0")
  18. #define szReportClass _T("SysmonReport")
  19. #define szReportClassA "SysmonReport"
  20. #define HEXMASK (0x00030C00)
  21. static INT xBorderWidth = GetSystemMetrics(SM_CXBORDER);
  22. static INT yBorderHeight = GetSystemMetrics(SM_CYBORDER);
  23. static INT xColumnMargin = 10;
  24. static INT xCounterMargin = 50;
  25. static INT xObjectMargin = 25;
  26. static TCHAR LineEndStr[] = TEXT("\n") ;
  27. static TCHAR TabStr[] = TEXT("\t");
  28. LRESULT APIENTRY HdrWndProc (HWND, WORD, WPARAM, LONG);
  29. //==========================================================================//
  30. // Constants //
  31. //==========================================================================//
  32. #define dwReportClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
  33. #define iReportWindowExtra (sizeof (PREPORT))
  34. #define dwReportWindowStyle (WS_CHILD | WS_HSCROLL | WS_VSCROLL)
  35. #define szValuePlaceholder TEXT("-999,999,999.999")
  36. #define szValueLargeHexPlaceholder TEXT(" xBBBBBBBBDDDDDDDD")
  37. #define dLargeValueMax ((double) 999999999.0)
  38. #define szDashLine TEXT("---")
  39. CReport::CReport (
  40. void
  41. )
  42. {
  43. m_pCtrl = NULL;
  44. m_hWnd = NULL;
  45. m_yLineHeight = 0;
  46. m_xReportWidth = 0;
  47. m_yReportHeight = 0;
  48. m_pSelect = NULL;
  49. }
  50. //
  51. // Destructor
  52. //
  53. CReport::~CReport (void )
  54. {
  55. if (m_hWnd != NULL && IsWindow(m_hWnd))
  56. DestroyWindow(m_hWnd);
  57. }
  58. //
  59. // Initialization
  60. //
  61. BOOL CReport::Init ( PSYSMONCTRL pCtrl, HWND hWndParent )
  62. {
  63. WNDCLASS wc ;
  64. LONG lExStyles;
  65. // Save pointer to parent control
  66. m_pCtrl = pCtrl;
  67. BEGIN_CRITICAL_SECTION
  68. // Register window class once
  69. if (pstrRegisteredClasses[REPORT_WNDCLASS] == NULL) {
  70. wc.style = dwReportClassStyle ;
  71. wc.lpfnWndProc = (WNDPROC) ReportWndProc ;
  72. wc.hInstance = g_hInstance ;
  73. wc.cbClsExtra = 0;
  74. wc.cbWndExtra = iReportWindowExtra ;
  75. wc.hIcon = NULL ;
  76. wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
  77. wc.hbrBackground = NULL ;
  78. wc.lpszMenuName = NULL ;
  79. wc.lpszClassName = szReportClass ;
  80. if (RegisterClass (&wc)) {
  81. pstrRegisteredClasses[REPORT_WNDCLASS] = szReportClass;
  82. }
  83. // Ensure controls are initialized
  84. InitCommonControls();
  85. }
  86. END_CRITICAL_SECTION
  87. if (pstrRegisteredClasses[REPORT_WNDCLASS] == NULL)
  88. return FALSE;
  89. // Create our window
  90. m_hWnd = CreateWindow (szReportClass, // class
  91. NULL, // caption
  92. dwReportWindowStyle, // window style
  93. 0, 0, // position
  94. 0, 0, // size
  95. hWndParent, // parent window
  96. NULL, // menu
  97. g_hInstance, // program instance
  98. (LPVOID) this ); // user-supplied data
  99. if (m_hWnd == NULL)
  100. return FALSE;
  101. // Turn off layout mirroring if it is enabled
  102. lExStyles = GetWindowLong(m_hWnd, GWL_EXSTYLE);
  103. if ( 0 != ( lExStyles & WS_EX_LAYOUTRTL ) ) {
  104. lExStyles &= ~WS_EX_LAYOUTRTL;
  105. SetWindowLong(m_hWnd, GWL_EXSTYLE, lExStyles);
  106. }
  107. return TRUE;
  108. }
  109. void CReport::ChangeFont (
  110. void
  111. )
  112. {
  113. if (!m_bFontChange) {
  114. m_bFontChange = TRUE;
  115. if (!m_bConfigChange) {
  116. m_bConfigChange = TRUE;
  117. WindowInvalidate(m_hWnd);
  118. }
  119. }
  120. }
  121. void
  122. CReport::SizeComponents (
  123. LPRECT pRect )
  124. {
  125. INT xWidth;
  126. INT yHeight;
  127. m_rect = *pRect;
  128. xWidth = pRect->right - pRect->left;
  129. yHeight = pRect->bottom - pRect->top;
  130. // If no space, hide window and leave
  131. if (xWidth == 0 || yHeight == 0) {
  132. WindowShow(m_hWnd, FALSE);
  133. return;
  134. }
  135. // Show window to assigned position
  136. MoveWindow(m_hWnd, pRect->left, pRect->top, xWidth, yHeight, FALSE);
  137. WindowShow(m_hWnd, TRUE);
  138. WindowInvalidate(m_hWnd);
  139. SetScrollRanges();
  140. }
  141. INT
  142. CReport::SetCounterPositions (
  143. PCObjectNode pObject,
  144. HDC hDC )
  145. {
  146. PCCounterNode pCounter;
  147. INT yPos;
  148. yPos = pObject->m_yPos + m_yLineHeight;
  149. for (pCounter = pObject->FirstCounter();
  150. pCounter;
  151. pCounter = pCounter->Next()) {
  152. if (m_bFontChange || pCounter->m_xWidth == -1) {
  153. pCounter->m_xWidth = TextWidth(hDC, pCounter->Name());
  154. }
  155. if (pCounter->m_xWidth > m_xMaxCounterWidth)
  156. m_xMaxCounterWidth = pCounter->m_xWidth;
  157. pCounter->m_yPos = yPos;
  158. yPos += m_yLineHeight;
  159. }
  160. return yPos;
  161. }
  162. INT
  163. CReport::SetInstancePositions (
  164. PCObjectNode pObject,
  165. HDC hDC )
  166. {
  167. INT xPos ;
  168. PCInstanceNode pInstance;
  169. TCHAR szParent[MAX_PATH];
  170. TCHAR szInstance[MAX_PATH];
  171. szParent[0] = _T('\0');
  172. szInstance[0] = _T('\0');
  173. xPos = 0;
  174. for (pInstance = pObject->FirstInstance();
  175. pInstance;
  176. pInstance = pInstance->Next()) {
  177. if (m_bFontChange || pInstance->m_xWidth == -1) {
  178. if (pInstance->HasParent()) {
  179. pInstance->GetParentName(szParent);
  180. pInstance->GetInstanceName(szInstance);
  181. pInstance->m_xWidth = max(TextWidth(hDC, szParent), TextWidth(hDC, szInstance));
  182. } else {
  183. pInstance->m_xWidth = TextWidth(hDC, pInstance->Name());
  184. }
  185. }
  186. pInstance->m_xPos = xPos + max(pInstance->m_xWidth, m_xValueWidth);
  187. xPos = pInstance->m_xPos + xColumnMargin;
  188. }
  189. if (xPos > m_xMaxInstancePos)
  190. m_xMaxInstancePos = xPos;
  191. return xPos;
  192. }
  193. INT
  194. CReport::SetObjectPositions (
  195. PCMachineNode pMachine,
  196. HDC hDC
  197. )
  198. {
  199. PCObjectNode pObject;
  200. INT yPos;
  201. INT xPos;
  202. yPos = pMachine->m_yPos + m_yLineHeight;
  203. for (pObject = pMachine->FirstObject();
  204. pObject ;
  205. pObject = pObject->Next()) {
  206. if (m_bFontChange || pObject->m_xWidth == -1) {
  207. pObject->m_xWidth = TextWidth(hDC, pObject->Name());
  208. }
  209. if (!pObject->FirstInstance()->HasParent())
  210. pObject->m_yPos = yPos;
  211. else
  212. pObject->m_yPos = yPos + m_yLineHeight;
  213. yPos = SetCounterPositions (pObject, hDC) ;
  214. xPos = SetInstancePositions(pObject, hDC);
  215. yPos += m_yLineHeight;
  216. }
  217. return yPos;
  218. }
  219. INT
  220. CReport::SetMachinePositions (
  221. PCCounterTree pTree,
  222. HDC hDC
  223. )
  224. {
  225. PCMachineNode pMachine ;
  226. INT yPos ;
  227. yPos = m_yLineHeight;
  228. for (pMachine = pTree->FirstMachine() ;
  229. pMachine ;
  230. pMachine = pMachine->Next()) {
  231. if (m_bFontChange || pMachine->m_xWidth == -1) {
  232. pMachine->m_xWidth = TextWidth(hDC, pMachine->Name());
  233. }
  234. pMachine->m_yPos = yPos;
  235. yPos = SetObjectPositions (pMachine, hDC);
  236. }
  237. m_yReportHeight = yPos + yBorderHeight;
  238. return yPos;
  239. }
  240. void
  241. CReport::DrawSelectRect (
  242. HDC hDC,
  243. BOOL bState
  244. )
  245. {
  246. BOOL bSuccess = TRUE;
  247. RECT rect = {0,0,0,0};
  248. HBRUSH hbrush;
  249. if ( NULL != m_pSelect && NULL != hDC ) {
  250. switch ( m_nSelectType ) {
  251. case MACHINE_NODE:
  252. rect.left = xColumnMargin;
  253. rect.top = ((PCMachineNode)m_pSelect)->m_yPos;
  254. rect.right = rect.left + ((PCMachineNode)m_pSelect)->m_xWidth;
  255. rect.bottom = rect.top + m_yLineHeight;
  256. break;
  257. case OBJECT_NODE:
  258. rect.left = xObjectMargin;
  259. rect.top = ((PCObjectNode)m_pSelect)->m_yPos;
  260. rect.right = rect.left + ((PCObjectNode)m_pSelect)->m_xWidth;
  261. rect.bottom = rect.top + m_yLineHeight;
  262. break;
  263. case INSTANCE_NODE:
  264. rect.right = m_xInstanceMargin + ((PCInstanceNode)m_pSelect)->m_xPos;
  265. rect.bottom = ((PCInstanceNode)m_pSelect)->m_pObject->m_yPos + m_yLineHeight;
  266. rect.left = rect.right - ((PCInstanceNode)m_pSelect)->m_xWidth;
  267. rect.top = rect.bottom -
  268. (((PCInstanceNode)m_pSelect)->HasParent() ? (2*m_yLineHeight) : m_yLineHeight);
  269. break;
  270. case COUNTER_NODE:
  271. rect.left = xCounterMargin;
  272. rect.top = ((PCCounterNode)m_pSelect)->m_yPos;
  273. rect.right = rect.left + ((PCCounterNode)m_pSelect)->m_xWidth;
  274. rect.bottom = rect.top + m_yLineHeight;
  275. break;
  276. case ITEM_NODE:
  277. rect.right = m_xInstanceMargin + ((PCGraphItem)m_pSelect)->m_pInstance->m_xPos;
  278. rect.top = ((PCGraphItem)m_pSelect)->m_pCounter->m_yPos;
  279. rect.left = rect.right - m_xValueWidth;
  280. rect.bottom = rect.top + m_yLineHeight;
  281. break;
  282. default:
  283. bSuccess = FALSE;
  284. }
  285. if ( bSuccess ) {
  286. rect.left -= 1;
  287. rect.right += 1;
  288. hbrush = CreateSolidBrush(bState ? m_pCtrl->clrFgnd() : m_pCtrl->clrBackPlot());
  289. if ( NULL != hbrush ) {
  290. FrameRect(hDC, &rect, hbrush);
  291. DeleteObject(hbrush);
  292. }
  293. }
  294. }
  295. return;
  296. }
  297. BOOL
  298. CReport::LargeHexValueExists ( void )
  299. {
  300. PCMachineNode pMachine = NULL;
  301. PCObjectNode pObject = NULL;
  302. PCInstanceNode pInstance = NULL;
  303. PCCounterNode pCounter = NULL;
  304. PCGraphItem pItem = NULL;
  305. BOOL bLargeHexValueExists = FALSE;
  306. for (pMachine = m_pCtrl->CounterTree()->FirstMachine();
  307. pMachine && !bLargeHexValueExists;
  308. pMachine = pMachine->Next()) {
  309. for (pObject = pMachine->FirstObject();
  310. pObject && !bLargeHexValueExists;
  311. pObject = pObject->Next()) {
  312. for (pInstance = pObject->FirstInstance();
  313. pInstance && !bLargeHexValueExists;
  314. pInstance = pInstance->Next()) {
  315. pItem = pInstance->FirstItem();
  316. for (pCounter = pObject->FirstCounter();
  317. pCounter && !bLargeHexValueExists;
  318. pCounter = pCounter->Next()) {
  319. PCGraphItem pCheckItem = NULL;
  320. if (pItem && pItem->m_pCounter == pCounter) {
  321. pCheckItem = pItem;
  322. pItem = pItem->m_pNextItem;
  323. }
  324. if ( pCheckItem ) {
  325. if ( !( pCheckItem->m_CounterInfo.dwType & HEXMASK ) ) {
  326. bLargeHexValueExists = pCheckItem->m_CounterInfo.dwType & PERF_SIZE_LARGE;
  327. if ( bLargeHexValueExists ) {
  328. break;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. }
  336. return bLargeHexValueExists;
  337. }
  338. void
  339. CReport::DrawReportValue (
  340. HDC hDC,
  341. PCGraphItem pItem,
  342. INT xPos,
  343. INT yPos )
  344. {
  345. TCHAR szValue [20] = TEXT("_") ;
  346. double dMax;
  347. double dMin;
  348. double dValue = -1.0;
  349. HRESULT hr;
  350. long lCtrStat;
  351. RECT rect ;
  352. INT iPrecision;
  353. if ( NULL != pItem && NULL != hDC ) {
  354. eReportValueTypeConstant eValueType;
  355. eValueType = m_pCtrl->ReportValueType();
  356. if ( sysmonDefaultValue == eValueType ) {
  357. // if log source display the average value
  358. // else display the current value
  359. if (m_pCtrl->IsLogSource()) {
  360. hr = pItem->GetStatistics(&dMax, &dMin, &dValue, &lCtrStat);
  361. } else {
  362. hr = pItem->GetValue(&dValue, &lCtrStat);
  363. }
  364. } else {
  365. if ( sysmonCurrentValue == eValueType ) {
  366. hr = pItem->GetValue(&dValue, &lCtrStat);
  367. } else {
  368. double dAvg;
  369. hr = pItem->GetStatistics(&dMax, &dMin, &dAvg, &lCtrStat);
  370. switch ( eValueType ) {
  371. case sysmonAverage:
  372. dValue = dAvg;
  373. break;
  374. case sysmonMinimum:
  375. dValue = dMin;
  376. break;
  377. case sysmonMaximum:
  378. dValue = dMax;
  379. break;
  380. default:
  381. assert (FALSE);
  382. }
  383. }
  384. }
  385. if (SUCCEEDED(hr) && IsSuccessSeverity(lCtrStat)) {
  386. assert ( 0 <= dValue );
  387. if ( ( pItem->m_CounterInfo.dwType & ( PERF_TYPE_COUNTER | PERF_TYPE_TEXT ) ) ) {
  388. (dValue > dLargeValueMax) ? iPrecision = 0 : iPrecision = 3;
  389. } else {
  390. // for Numbers, no decimal places
  391. iPrecision = 0;
  392. }
  393. if(PDH_CSTATUS_INVALID_DATA != pItem->m_CounterInfo.CStatus ) {
  394. // Check for Hex values
  395. if ( !(pItem->m_CounterInfo.dwType & HEXMASK) ) {
  396. BOOL bLarge = pItem->m_CounterInfo.dwType & PERF_SIZE_LARGE;
  397. FormatHex (
  398. dValue,
  399. szValue,
  400. bLarge);
  401. } else {
  402. FormatNumber (
  403. dValue,
  404. szValue,
  405. 20,
  406. 12,
  407. iPrecision );
  408. }
  409. }
  410. }
  411. else {
  412. lstrcpy(szValue, szDashLine);
  413. }
  414. }
  415. else {
  416. lstrcpy(szValue, szDashLine);
  417. }
  418. rect.right = xPos - 1;
  419. rect.left = xPos - m_xValueWidth + 1;
  420. rect.top = yPos;
  421. rect.bottom = yPos + m_yLineHeight;
  422. ExtTextOut (hDC, rect.right, rect.top, ETO_CLIPPED | ETO_OPAQUE,
  423. &rect, szValue, lstrlen (szValue), NULL) ;
  424. }
  425. void
  426. CReport::DrawReportValues (
  427. HDC hDC )
  428. {
  429. PCMachineNode pMachine;
  430. PCObjectNode pObject;
  431. PCInstanceNode pInstance;
  432. PCCounterNode pCounter;
  433. PCGraphItem pItem;
  434. PCGraphItem pDrawItem;
  435. if ( NULL != hDC ) {
  436. SelectFont (hDC, m_pCtrl->Font());
  437. SetTextAlign (hDC, TA_RIGHT|TA_TOP);
  438. for (pMachine = m_pCtrl->CounterTree()->FirstMachine();
  439. pMachine;
  440. pMachine = pMachine->Next()) {
  441. for (pObject = pMachine->FirstObject();
  442. pObject;
  443. pObject = pObject->Next()) {
  444. for (pInstance = pObject->FirstInstance();
  445. pInstance;
  446. pInstance = pInstance->Next()) {
  447. pItem = pInstance->FirstItem();
  448. for ( pCounter = pObject->FirstCounter();
  449. pCounter;
  450. pCounter = pCounter->Next()) {
  451. if (pItem && pItem->m_pCounter == pCounter) {
  452. pDrawItem = pItem;
  453. pItem = pItem->m_pNextItem;
  454. } else {
  455. pDrawItem = NULL;
  456. }
  457. DrawReportValue (
  458. hDC,
  459. pDrawItem,
  460. m_xInstanceMargin + pInstance->m_xPos,
  461. pCounter->m_yPos);
  462. }
  463. }
  464. }
  465. }
  466. }
  467. }
  468. BOOL
  469. CReport::WriteFileReport ( HANDLE hFile )
  470. {
  471. PCMachineNode pMachine;
  472. PCObjectNode pObject;
  473. PCInstanceNode pInstance;
  474. PCCounterNode pCounter;
  475. TCHAR szName[MAX_PATH];
  476. TCHAR pszTemp[2*MAX_PATH];
  477. PCGraphItem pItem;
  478. BOOL bStatus = TRUE;
  479. TCHAR szValue[20];
  480. for (pMachine = m_pCtrl->CounterTree()->FirstMachine() ;
  481. pMachine && TRUE == bStatus;
  482. pMachine = pMachine->Next()) {
  483. lstrcpy(pszTemp,LineEndStr);
  484. lstrcat(pszTemp,LineEndStr);
  485. lstrcat(pszTemp,ResourceString(IDS_COMPUTER));
  486. lstrcat(pszTemp,pMachine->Name());
  487. lstrcat(pszTemp,LineEndStr);
  488. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  489. for (pObject = pMachine->FirstObject() ;
  490. pObject && TRUE == bStatus;
  491. pObject = pObject->Next()) {
  492. // Write the object name line.
  493. lstrcpy(pszTemp,LineEndStr);
  494. lstrcat(pszTemp,ResourceString(IDS_OBJECT_NAME));
  495. lstrcat(pszTemp,pObject->Name());
  496. lstrcat(pszTemp,LineEndStr);
  497. // Add first tab char for instance names.
  498. lstrcat(pszTemp,TabStr);
  499. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  500. if (!bStatus)
  501. break;
  502. // Write the first line of instance (parent) names.
  503. for (pInstance = pObject->FirstInstance();
  504. pInstance && TRUE == bStatus;
  505. pInstance = pInstance->Next()) {
  506. // If instance has no parent, then the parent name is null, so a tab is written.
  507. pInstance->GetParentName(szName);
  508. lstrcpy(pszTemp,TabStr);
  509. lstrcat(pszTemp,szName);
  510. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  511. }
  512. if ( !bStatus )
  513. break;
  514. lstrcpy(pszTemp,LineEndStr);
  515. // Include first tab of second instance line.
  516. lstrcat(pszTemp,TabStr);
  517. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  518. // Write the second line of instance names.
  519. for (pInstance = pObject->FirstInstance();
  520. pInstance && TRUE == bStatus;
  521. pInstance = pInstance->Next()) {
  522. pInstance->GetInstanceName(szName);
  523. lstrcpy(pszTemp,TabStr);
  524. lstrcat(pszTemp,szName);
  525. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  526. }
  527. if (!bStatus)
  528. break;
  529. lstrcpy(pszTemp,LineEndStr);
  530. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  531. for (pCounter = pObject->FirstCounter();
  532. pCounter && TRUE == bStatus;
  533. pCounter = pCounter->Next()) {
  534. // Write counter name
  535. lstrcpy(pszTemp,TabStr);
  536. lstrcat(pszTemp,pCounter->Name());
  537. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  538. // Write values, looping on instances
  539. for ( pInstance = pObject->FirstInstance();
  540. pInstance && TRUE == bStatus;
  541. pInstance = pInstance->Next()) {
  542. // Loop on items to find the item that matches the counter.
  543. for ( pItem = pInstance->FirstItem();
  544. pItem && TRUE == bStatus;
  545. pItem = pItem->m_pNextItem) {
  546. if ( pItem->m_pCounter == pCounter && pInstance) {
  547. GetReportItemValue(pItem,szValue );
  548. lstrcpy(pszTemp,TabStr);
  549. lstrcat (pszTemp,szValue);
  550. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  551. }
  552. }
  553. }
  554. if (!bStatus)
  555. break;
  556. lstrcpy(pszTemp,LineEndStr);
  557. bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
  558. }
  559. }
  560. }
  561. return bStatus;
  562. }
  563. void
  564. CReport::GetReportItemValue(PCGraphItem pItem, LPTSTR szValue){
  565. double dMax;
  566. double dMin;
  567. double dValue = -1.0;
  568. HRESULT hr;
  569. long lCtrStat;
  570. INT iPrecision;
  571. if (pItem) {
  572. eReportValueTypeConstant eValueType;
  573. eValueType = m_pCtrl->ReportValueType();
  574. if ( sysmonDefaultValue == eValueType ) {
  575. // if log source display the average value
  576. // else display the current value
  577. if (m_pCtrl->IsLogSource()) {
  578. hr = pItem->GetStatistics(&dMax, &dMin, &dValue, &lCtrStat);
  579. } else {
  580. hr = pItem->GetValue(&dValue, &lCtrStat);
  581. }
  582. } else {
  583. if ( sysmonCurrentValue == eValueType ) {
  584. hr = pItem->GetValue(&dValue, &lCtrStat);
  585. } else {
  586. double dAvg;
  587. hr = pItem->GetStatistics(&dMax, &dMin, &dAvg, &lCtrStat);
  588. switch ( eValueType ) {
  589. case sysmonAverage:
  590. dValue = dAvg;
  591. break;
  592. case sysmonMinimum:
  593. dValue = dMin;
  594. break;
  595. case sysmonMaximum:
  596. dValue = dMax;
  597. break;
  598. default:
  599. assert (FALSE);
  600. }
  601. }
  602. }
  603. if (SUCCEEDED(hr) && IsSuccessSeverity(lCtrStat)) {
  604. assert ( 0 <= dValue );
  605. (dValue > dLargeValueMax) ? iPrecision = 0 : iPrecision = 3;
  606. if(PDH_CSTATUS_INVALID_DATA != pItem->m_CounterInfo.CStatus ) {
  607. // Check for Hex values
  608. if ( !(pItem->m_CounterInfo.dwType & HEXMASK) ) {
  609. BOOL bLarge = pItem->m_CounterInfo.dwType & PERF_SIZE_LARGE;
  610. FormatHex (
  611. dValue,
  612. szValue,
  613. bLarge);
  614. } else {
  615. FormatNumber (
  616. dValue,
  617. szValue,
  618. 20,
  619. 12,
  620. iPrecision );
  621. }
  622. }
  623. } else {
  624. lstrcpy(szValue, szDashLine);
  625. }
  626. } else {
  627. lstrcpy(szValue, szDashLine);
  628. }
  629. return;
  630. }
  631. void
  632. CReport::DrawReportHeaders (
  633. HDC hDC )
  634. {
  635. PCMachineNode pMachine;
  636. PCObjectNode pObject;
  637. PCInstanceNode pInstance;
  638. PCCounterNode pCounter;
  639. TCHAR szName[MAX_PATH];
  640. INT cName;
  641. RECT rectMachine;
  642. RECT rectObject;
  643. RECT rectInstance;
  644. RECT rectCounter;
  645. if ( NULL != hDC ) {
  646. SetTextAlign(hDC, TA_LEFT|TA_TOP) ;
  647. rectMachine.left = xColumnMargin;
  648. rectObject.left = xObjectMargin;
  649. rectCounter.left = xCounterMargin;
  650. for ( pMachine = m_pCtrl->CounterTree()->FirstMachine() ;
  651. pMachine;
  652. pMachine = pMachine->Next()) {
  653. rectMachine.right = rectMachine.left + pMachine->m_xWidth;
  654. rectMachine.top = pMachine->m_yPos;
  655. rectMachine.bottom = pMachine->m_yPos + m_yLineHeight;
  656. ExtTextOut (
  657. hDC,
  658. xColumnMargin,
  659. pMachine->m_yPos,
  660. ETO_OPAQUE,
  661. &rectMachine,
  662. pMachine->Name(),
  663. lstrlen(pMachine->Name()),
  664. NULL );
  665. for ( pObject = pMachine->FirstObject() ;
  666. pObject ;
  667. pObject = pObject->Next()) {
  668. rectObject.right = rectObject.left + pObject->m_xWidth;
  669. rectObject.top = pObject->m_yPos;
  670. rectObject.bottom = pObject->m_yPos + m_yLineHeight;
  671. ExtTextOut (
  672. hDC,
  673. xObjectMargin,
  674. pObject->m_yPos,
  675. ETO_OPAQUE,
  676. &rectObject,
  677. pObject->Name(),
  678. lstrlen (pObject->Name()),
  679. NULL);
  680. SetTextAlign (hDC, TA_RIGHT) ;
  681. for ( pInstance = pObject->FirstInstance();
  682. pInstance;
  683. pInstance = pInstance->Next()) {
  684. rectInstance.left = m_xInstanceMargin + pInstance->m_xPos;
  685. rectInstance.right = rectInstance.left + max(pInstance->m_xWidth, m_xValueWidth);
  686. if ( pInstance->HasParent() ) {
  687. cName = pInstance->GetParentName(szName);
  688. rectInstance.top = pObject->m_yPos - m_yLineHeight;
  689. rectInstance.bottom = rectInstance.top + m_yLineHeight;
  690. ExtTextOut (
  691. hDC,
  692. m_xInstanceMargin + pInstance->m_xPos,
  693. pObject->m_yPos - m_yLineHeight,
  694. ETO_OPAQUE,
  695. &rectInstance,
  696. szName,
  697. cName,
  698. NULL);
  699. rectInstance.top = pObject->m_yPos;
  700. rectInstance.bottom = rectInstance.top + m_yLineHeight;
  701. cName = pInstance->GetInstanceName(szName);
  702. ExtTextOut (
  703. hDC,
  704. m_xInstanceMargin + pInstance->m_xPos,
  705. pObject->m_yPos,
  706. ETO_OPAQUE,
  707. &rectInstance,
  708. szName,
  709. cName,
  710. NULL );
  711. } else {
  712. rectInstance.top = pObject->m_yPos;
  713. rectInstance.bottom = rectInstance.top + m_yLineHeight;
  714. ExtTextOut (
  715. hDC,
  716. m_xInstanceMargin + pInstance->m_xPos,
  717. pObject->m_yPos,
  718. ETO_OPAQUE,
  719. &rectInstance,
  720. pInstance->Name(),
  721. lstrlen(pInstance->Name()),
  722. NULL );
  723. }
  724. }
  725. SetTextAlign (hDC, TA_LEFT) ;
  726. for (pCounter = pObject->FirstCounter();
  727. pCounter ;
  728. pCounter = pCounter->Next()) {
  729. rectCounter.right = rectCounter.left + pCounter->m_xWidth;
  730. rectCounter.top = pCounter->m_yPos;
  731. rectCounter.bottom = pCounter->m_yPos + m_yLineHeight;
  732. ExtTextOut (
  733. hDC,
  734. xCounterMargin,
  735. pCounter->m_yPos,
  736. ETO_OPAQUE,
  737. &rectCounter,
  738. pCounter->Name(),
  739. lstrlen (pCounter->Name()),
  740. NULL);
  741. }
  742. }
  743. }
  744. DrawSelectRect(hDC, TRUE);
  745. }
  746. }
  747. void
  748. CReport::ApplyChanges (
  749. HDC hDC )
  750. {
  751. if (m_bConfigChange && NULL != hDC ) {
  752. // Selected the Bold font for font change , counter add, and counter delete.
  753. // This is used for recalculating text width.
  754. SelectFont (hDC, m_pCtrl->BoldFont());
  755. m_yLineHeight = FontHeight (hDC, TRUE);
  756. if ( LargeHexValueExists ( ) ) {
  757. m_xValueWidth = TextWidth(hDC, szValueLargeHexPlaceholder);
  758. } else {
  759. m_xValueWidth = TextWidth(hDC, szValuePlaceholder);
  760. }
  761. m_xMaxCounterWidth = 0;
  762. m_xMaxInstancePos = 0;
  763. SetMachinePositions (m_pCtrl->CounterTree(), hDC);
  764. m_xInstanceMargin = xCounterMargin + m_xMaxCounterWidth + xColumnMargin;
  765. m_xReportWidth = m_xInstanceMargin + m_xMaxInstancePos;
  766. SetScrollRanges();
  767. m_bConfigChange = FALSE;
  768. m_bFontChange = FALSE;
  769. }
  770. }
  771. void
  772. CReport::Render (
  773. HDC hDC,
  774. HDC hAttribDC,
  775. BOOL /*fMetafile*/,
  776. BOOL /*fEntire*/,
  777. LPRECT prcUpdate )
  778. {
  779. ApplyChanges(hAttribDC);
  780. if ( NULL != hDC ) {
  781. SetBkColor(hDC, m_pCtrl->clrBackPlot());
  782. ClearRect(hDC, prcUpdate);
  783. Draw( hDC );
  784. }
  785. }
  786. void
  787. CReport::Draw (
  788. HDC hDC )
  789. {
  790. // if no space assigned, return
  791. if (m_rect.top != m_rect.bottom) {
  792. if ( NULL != hDC ) {
  793. SetTextColor (hDC, m_pCtrl->clrFgnd());
  794. SetBkColor(hDC, m_pCtrl->clrBackPlot());
  795. SelectFont(hDC, m_pCtrl->BoldFont());
  796. DrawReportHeaders (hDC);
  797. SelectFont (hDC, m_pCtrl->Font());
  798. DrawReportValues (hDC);
  799. m_pCtrl->DrawBorder ( hDC );
  800. }
  801. }
  802. }
  803. void
  804. CReport::AddItem (
  805. PCGraphItem /* pItem */ )
  806. {
  807. if (!m_bConfigChange) {
  808. m_bConfigChange = TRUE;
  809. WindowInvalidate(m_hWnd);
  810. }
  811. }
  812. void
  813. CReport::DeleteItem (
  814. PCGraphItem pItem )
  815. {
  816. // Calling procedure checks for NULL pItem
  817. assert ( NULL != pItem );
  818. if ( NULL != m_pSelect ) {
  819. if ( SelectionDeleted ( pItem ) ) {
  820. m_pSelect = NULL;
  821. }
  822. }
  823. if (!m_bConfigChange) {
  824. m_bConfigChange = TRUE;
  825. WindowInvalidate(m_hWnd);
  826. }
  827. }
  828. void
  829. CReport::DeleteSelection (
  830. VOID )
  831. {
  832. if (m_pSelect == NULL)
  833. return;
  834. switch (m_nSelectType) {
  835. case MACHINE_NODE:
  836. ((PCMachineNode)m_pSelect)->DeleteNode(TRUE);
  837. break;
  838. case OBJECT_NODE:
  839. ((PCObjectNode)m_pSelect)->DeleteNode(TRUE);
  840. break;
  841. case INSTANCE_NODE:
  842. ((PCInstanceNode)m_pSelect)->DeleteNode(TRUE);
  843. break;
  844. case COUNTER_NODE:
  845. ((PCCounterNode)m_pSelect)->DeleteNode(TRUE);
  846. break;
  847. case ITEM_NODE:
  848. ((PCGraphItem)m_pSelect)->Delete(TRUE);
  849. break;
  850. default:
  851. return;
  852. }
  853. // DeleteItem sets m_pSelect to NULL and invalidates the window.
  854. assert ( NULL == m_pSelect );
  855. }
  856. BOOL
  857. CReport::OnContextMenu (
  858. INT x,
  859. INT y )
  860. {
  861. HMENU hMenu;
  862. HMENU hMenuPopup;
  863. RECT clntRect;
  864. int xPos=0,yPos=0;
  865. GetWindowRect(m_hWnd,&clntRect);
  866. if (x==0){
  867. xPos = ((clntRect.right - clntRect.left)/2) ;
  868. }else{
  869. xPos = x - clntRect.left;
  870. }
  871. if (y==0){
  872. yPos = ((clntRect.bottom - clntRect.top)/2) ;
  873. }else{
  874. yPos = y - clntRect.top;
  875. }
  876. x = clntRect.left + xPos ;
  877. y = clntRect.top + yPos ;
  878. // if nothing is selected, let main window handle the menu
  879. if (m_pSelect == NULL)
  880. return FALSE;
  881. if ( m_pCtrl->ConfirmSampleDataOverwrite() ) {
  882. if ( !m_pCtrl->IsReadOnly() ) {
  883. // Get the menu for the pop-up menu from the resource file.
  884. hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_CONTEXT));
  885. if (!hMenu)
  886. return TRUE;
  887. // Get the first submenu in it for TrackPopupMenu.
  888. hMenuPopup = GetSubMenu(hMenu, 0);
  889. // Draw and track the "floating" pop-up menu.
  890. TrackPopupMenu(hMenuPopup, TPM_RIGHTBUTTON, x, y, 0, m_hWnd, NULL);
  891. // Destroy the menu.
  892. DestroyMenu(hMenu);
  893. }
  894. }
  895. return TRUE;
  896. }
  897. void
  898. CReport::Update (
  899. void )
  900. {
  901. HDC hDC;
  902. hDC = GetDC(m_hWnd);
  903. if ( NULL != hDC ) {
  904. ApplyChanges(hDC);
  905. SetWindowOrgEx (hDC,
  906. GetScrollPos (m_hWnd, SB_HORZ),
  907. GetScrollPos (m_hWnd, SB_VERT),
  908. NULL) ;
  909. if ( m_rect.bottom != m_rect.top ) {
  910. SelectFont (hDC, m_pCtrl->Font());
  911. SetTextColor (hDC, m_pCtrl->clrFgnd());
  912. SetBkColor(hDC, m_pCtrl->clrBackPlot());
  913. DrawReportValues(hDC);
  914. }
  915. ReleaseDC(m_hWnd,hDC);
  916. }
  917. }
  918. void
  919. CReport::OnPaint (
  920. void
  921. )
  922. {
  923. HDC hDC ;
  924. PAINTSTRUCT ps ;
  925. if ( m_pCtrl->DisplayMissedSampleMessage() ) {
  926. MessageBox(m_hWnd, ResourceString(IDS_SAMPLE_DATA_MISSING), ResourceString(IDS_APP_NAME),
  927. MB_OK | MB_ICONINFORMATION);
  928. }
  929. hDC = BeginPaint (m_hWnd, &ps) ;
  930. if ( NULL != hDC ) {
  931. SelectFont (hDC, m_pCtrl->Font()) ;
  932. SetWindowOrgEx (
  933. hDC,
  934. GetScrollPos (m_hWnd, SB_HORZ),
  935. GetScrollPos (m_hWnd, SB_VERT),
  936. NULL );
  937. SetTextColor (hDC, m_pCtrl->clrFgnd());
  938. SetBkColor(hDC, m_pCtrl->clrBackPlot());
  939. ApplyChanges(hDC);
  940. Draw(hDC);
  941. EndPaint (m_hWnd, &ps) ;
  942. }
  943. }
  944. void
  945. CReport::SetScrollRanges (
  946. void )
  947. {
  948. RECT rectClient ;
  949. INT xWidth, yHeight ;
  950. GetClientRect (m_hWnd, &rectClient) ;
  951. xWidth = rectClient.right - rectClient.left ;
  952. yHeight = rectClient.bottom - rectClient.top ;
  953. SetScrollRange (m_hWnd, SB_VERT, 0, max (0, m_yReportHeight - yHeight), TRUE) ;
  954. SetScrollRange (m_hWnd, SB_HORZ,0, max (0, m_xReportWidth - xWidth), TRUE) ;
  955. }
  956. BOOL
  957. CReport::SelectName (
  958. INT xPos,
  959. INT yPos,
  960. void** ppSelected,
  961. INT* piSelectType )
  962. {
  963. POINT pt;
  964. PCMachineNode pMachine;
  965. PCObjectNode pObject;
  966. PCCounterNode pCounter;
  967. PCInstanceNode pInstance;
  968. PCGraphItem pItem;
  969. // Programming error if either of these two pointers is NULL.
  970. assert ( NULL != ppSelected );
  971. assert ( NULL != piSelectType );
  972. // Adjust coordinates by scroll offset
  973. pt.x = xPos + GetScrollPos(m_hWnd, SB_HORZ);
  974. pt.y = yPos + GetScrollPos(m_hWnd, SB_VERT);
  975. for (pMachine = m_pCtrl->CounterTree()->FirstMachine() ;
  976. pMachine;
  977. pMachine = pMachine->Next()) {
  978. if (PtInName(pt, xColumnMargin, pMachine->m_yPos, pMachine->m_xWidth)) {
  979. *ppSelected = pMachine;
  980. *piSelectType = MACHINE_NODE;
  981. return TRUE;
  982. }
  983. for (pObject = pMachine->FirstObject() ;
  984. pObject ;
  985. pObject = pObject->Next()) {
  986. if (PtInName(pt, xObjectMargin, pObject->m_yPos, pObject->m_xWidth)) {
  987. *ppSelected = pObject;
  988. *piSelectType = OBJECT_NODE;
  989. return TRUE;
  990. }
  991. for (pCounter = pObject->FirstCounter();
  992. pCounter ;
  993. pCounter = pCounter->Next()) {
  994. if (PtInName(pt, xCounterMargin, pCounter->m_yPos, pCounter->m_xWidth)) {
  995. *ppSelected = pCounter;
  996. *piSelectType = COUNTER_NODE;
  997. return TRUE;
  998. }
  999. }
  1000. for (pInstance = pObject->FirstInstance();
  1001. pInstance ;
  1002. pInstance = pInstance->Next()) {
  1003. INT xInstancePos = m_xInstanceMargin + pInstance->m_xPos;
  1004. if (PtInName(pt, xInstancePos - pInstance->m_xWidth, pObject->m_yPos, pInstance->m_xWidth) ||
  1005. (pInstance->HasParent() &&
  1006. PtInName(pt, xInstancePos - pInstance->m_xWidth, pObject->m_yPos - m_yLineHeight, pInstance->m_xWidth))) {
  1007. *ppSelected = pInstance;
  1008. *piSelectType = INSTANCE_NODE;
  1009. return TRUE;
  1010. }
  1011. if (pt.x > xInstancePos || pt.x < xInstancePos - m_xValueWidth)
  1012. continue;
  1013. for (pItem = pInstance->FirstItem();
  1014. pItem;
  1015. pItem = pItem->m_pNextItem) {
  1016. if (pt.y > pItem->m_pCounter->m_yPos && pt.y < pItem->m_pCounter->m_yPos + m_yLineHeight) {
  1017. *ppSelected = pItem;
  1018. *piSelectType = ITEM_NODE;
  1019. return TRUE;
  1020. }
  1021. }
  1022. }
  1023. }
  1024. }
  1025. *ppSelected = NULL;
  1026. return FALSE;
  1027. }
  1028. PCGraphItem
  1029. CReport::GetItem (
  1030. void *pSelected,
  1031. INT nSelectType )
  1032. {
  1033. PCMachineNode pMachine;
  1034. PCObjectNode pObject;
  1035. PCCounterNode pCounter;
  1036. PCInstanceNode pInstance;
  1037. PCGraphItem pItem;
  1038. PCGraphItem pReturn = NULL;
  1039. if ( NULL != pSelected ) {
  1040. switch (nSelectType) {
  1041. case MACHINE_NODE:
  1042. pMachine = (PCMachineNode)pSelected;
  1043. pObject = pMachine->FirstObject();
  1044. if ( NULL != pObject ) {
  1045. pInstance = pObject->FirstInstance();
  1046. if ( NULL != pInstance ) {
  1047. pReturn = pInstance->FirstItem();
  1048. }
  1049. }
  1050. break;
  1051. case OBJECT_NODE:
  1052. pObject = (PCObjectNode)pSelected;
  1053. pInstance = pObject->FirstInstance();
  1054. if ( NULL != pInstance ) {
  1055. pReturn = pInstance->FirstItem();
  1056. }
  1057. break;
  1058. case INSTANCE_NODE:
  1059. pInstance = (PCInstanceNode)pSelected;
  1060. pReturn = pInstance->FirstItem();
  1061. break;
  1062. case COUNTER_NODE:
  1063. pCounter = (PCCounterNode)pSelected;
  1064. pObject = pCounter->m_pObject;
  1065. for (pInstance = pObject->FirstInstance();
  1066. ((NULL != pInstance) && (NULL == pReturn));
  1067. pInstance = pInstance->Next()) {
  1068. for (pItem = pInstance->FirstItem();
  1069. ((NULL != pItem) && (NULL == pReturn));
  1070. pItem = pItem->m_pNextItem) {
  1071. if (pItem && pItem->m_pCounter == pCounter) {
  1072. pReturn = pItem;
  1073. }
  1074. }
  1075. }
  1076. break;
  1077. case ITEM_NODE:
  1078. pReturn = (PCGraphItem)pSelected;
  1079. break;
  1080. default:
  1081. break;
  1082. }
  1083. }
  1084. return pReturn;
  1085. }
  1086. BOOL
  1087. CReport::SelectionDeleted (
  1088. PCGraphItem pDeletedItem )
  1089. {
  1090. BOOL bSelectionDeleted = FALSE;
  1091. INT iItemCount = 0;
  1092. PCMachineNode pMachine;
  1093. PCObjectNode pObject;
  1094. PCCounterNode pCounter;
  1095. PCInstanceNode pInstance;
  1096. PCGraphItem pItem;
  1097. if ( NULL == m_pSelect )
  1098. return FALSE;
  1099. // Delete the selection if this is the last remaining
  1100. // item for the selection object.
  1101. switch (m_nSelectType) {
  1102. case MACHINE_NODE:
  1103. // Check for multiple items for this machine.
  1104. pMachine = (PCMachineNode)m_pSelect;
  1105. for ( pObject = pMachine->FirstObject();
  1106. ( NULL != pObject ) && ( 2 > iItemCount );
  1107. pObject = pObject->Next()) {
  1108. for ( pInstance = pObject->FirstInstance();
  1109. ( NULL != pInstance ) && ( 2 > iItemCount );
  1110. pInstance = pInstance->Next()) {
  1111. for ( pItem = pInstance->FirstItem();
  1112. ( NULL != pItem ) && ( 2 > iItemCount );
  1113. pItem = pItem->m_pNextItem) {
  1114. iItemCount++;
  1115. }
  1116. }
  1117. }
  1118. bSelectionDeleted = ( iItemCount < 2 );
  1119. break;
  1120. case OBJECT_NODE:
  1121. // Check for multiple items for this object.
  1122. pObject = (PCObjectNode)m_pSelect;
  1123. for ( pInstance = pObject->FirstInstance();
  1124. ( NULL != pInstance ) && ( 2 > iItemCount );
  1125. pInstance = pInstance->Next()) {
  1126. for ( pItem = pInstance->FirstItem();
  1127. ( NULL != pItem ) && ( 2 > iItemCount );
  1128. pItem = pItem->m_pNextItem) {
  1129. iItemCount++;
  1130. }
  1131. }
  1132. bSelectionDeleted = ( iItemCount < 2 );
  1133. break;
  1134. case INSTANCE_NODE:
  1135. // Check for multiple items (counters) for this instance.
  1136. pInstance = (PCInstanceNode)m_pSelect;
  1137. iItemCount = 0;
  1138. for ( pItem = pInstance->FirstItem();
  1139. ( NULL != pItem ) && ( 2 > iItemCount );
  1140. pItem = pItem->m_pNextItem) {
  1141. iItemCount++;
  1142. }
  1143. bSelectionDeleted = ( iItemCount < 2 );
  1144. break;
  1145. case COUNTER_NODE:
  1146. // Check for multiple items (instances) for this counter.
  1147. pCounter = (PCCounterNode)m_pSelect;
  1148. pObject = pCounter->m_pObject;
  1149. for ( pInstance = pObject->FirstInstance();
  1150. ( NULL != pInstance ) && ( 2 > iItemCount );
  1151. pInstance = pInstance->Next()) {
  1152. for ( pItem = pInstance->FirstItem();
  1153. ( NULL != pItem ) && ( 2 > iItemCount );
  1154. pItem = pItem->m_pNextItem) {
  1155. if (pItem && pItem->m_pCounter == pCounter) {
  1156. iItemCount++;
  1157. break;
  1158. }
  1159. }
  1160. }
  1161. bSelectionDeleted = ( iItemCount < 2 );
  1162. break;
  1163. case ITEM_NODE:
  1164. // Selection matches the deleted item.
  1165. bSelectionDeleted = ( pDeletedItem == (PCGraphItem)m_pSelect );
  1166. break;
  1167. default:
  1168. break;
  1169. }
  1170. return bSelectionDeleted;
  1171. }
  1172. void
  1173. CReport::OnLButtonDown (
  1174. INT xPos,
  1175. INT yPos )
  1176. {
  1177. PCGraphItem pItem;
  1178. HDC hDC = GetDC(m_hWnd);
  1179. if ( NULL != hDC ) {
  1180. SetWindowOrgEx (
  1181. hDC,
  1182. GetScrollPos (m_hWnd, SB_HORZ),
  1183. GetScrollPos (m_hWnd, SB_VERT),
  1184. NULL) ;
  1185. DrawSelectRect(hDC, FALSE);
  1186. if ( SelectName(xPos, yPos, &m_pSelect, &m_nSelectType) )
  1187. DrawSelectRect(hDC, TRUE);
  1188. ReleaseDC(m_hWnd, hDC);
  1189. pItem = GetItem(m_pSelect, m_nSelectType);
  1190. m_pCtrl->SelectCounter(pItem);
  1191. }
  1192. return;
  1193. }
  1194. void
  1195. CReport:: OnDblClick (
  1196. INT, // xPos,
  1197. INT // yPos
  1198. )
  1199. {
  1200. PCGraphItem pItem;
  1201. pItem = GetItem ( m_pSelect, m_nSelectType );
  1202. m_pCtrl->DblClickCounter ( pItem );
  1203. }
  1204. void
  1205. CReport::OnHScroll (
  1206. INT iScrollCode,
  1207. INT iScrollNewPos )
  1208. {
  1209. INT iScrollAmt, iScrollPos, iScrollRange ;
  1210. INT iScrollLo ;
  1211. RECT rectClient ;
  1212. INT xWidth ;
  1213. GetClientRect (m_hWnd, &rectClient) ;
  1214. xWidth = rectClient.right - rectClient.left ;
  1215. if (m_xReportWidth <= xWidth)
  1216. return ;
  1217. iScrollPos = GetScrollPos (m_hWnd, SB_HORZ) ;
  1218. GetScrollRange (m_hWnd, SB_HORZ, &iScrollLo, &iScrollRange) ;
  1219. switch (iScrollCode)
  1220. {
  1221. case SB_LINEUP:
  1222. iScrollAmt = - m_yLineHeight ;
  1223. break ;
  1224. case SB_LINEDOWN:
  1225. iScrollAmt = m_yLineHeight ;
  1226. break ;
  1227. case SB_PAGEUP:
  1228. iScrollAmt = - (rectClient.right - rectClient.left) / 2 ;
  1229. break ;
  1230. case SB_PAGEDOWN:
  1231. iScrollAmt = (rectClient.right - rectClient.left) / 2 ;
  1232. break ;
  1233. case SB_THUMBPOSITION:
  1234. iScrollAmt = iScrollNewPos - iScrollPos ;
  1235. break ;
  1236. default:
  1237. iScrollAmt = 0 ;
  1238. }
  1239. iScrollAmt = PinInclusive (iScrollAmt,
  1240. -iScrollPos,
  1241. iScrollRange - iScrollPos) ;
  1242. if (iScrollAmt) {
  1243. iScrollPos += iScrollAmt ;
  1244. ScrollWindow (m_hWnd, -iScrollAmt, 0, NULL, NULL) ;
  1245. SetScrollPos (m_hWnd, SB_HORZ, iScrollPos, TRUE) ;
  1246. UpdateWindow (m_hWnd) ;
  1247. }
  1248. }
  1249. void
  1250. CReport::OnVScroll (
  1251. INT iScrollCode,
  1252. INT iScrollNewPos
  1253. )
  1254. {
  1255. INT iScrollAmt, iScrollPos, iScrollRange ;
  1256. INT iScrollLo ;
  1257. RECT rectClient ;
  1258. iScrollPos = GetScrollPos (m_hWnd, SB_VERT) ;
  1259. GetScrollRange (m_hWnd, SB_VERT, &iScrollLo, &iScrollRange) ;
  1260. GetClientRect (m_hWnd, &rectClient) ;
  1261. switch (iScrollCode) {
  1262. case SB_LINEUP:
  1263. iScrollAmt = - m_yLineHeight ;
  1264. break ;
  1265. case SB_LINEDOWN:
  1266. iScrollAmt = m_yLineHeight ;
  1267. break ;
  1268. case SB_PAGEUP:
  1269. iScrollAmt = - (rectClient.bottom - rectClient.top) / 2 ;
  1270. break ;
  1271. case SB_PAGEDOWN:
  1272. iScrollAmt = (rectClient.bottom - rectClient.top) / 2 ;
  1273. break ;
  1274. case SB_THUMBPOSITION:
  1275. iScrollAmt = iScrollNewPos - iScrollPos ;
  1276. break ;
  1277. default:
  1278. iScrollAmt = 0 ;
  1279. }
  1280. iScrollAmt = PinInclusive (iScrollAmt, -iScrollPos, iScrollRange - iScrollPos) ;
  1281. if (iScrollAmt) {
  1282. iScrollPos += iScrollAmt ;
  1283. ScrollWindow (m_hWnd, 0, -iScrollAmt, NULL, NULL) ;
  1284. SetScrollPos (m_hWnd, SB_VERT, iScrollPos, TRUE) ;
  1285. UpdateWindow (m_hWnd) ;
  1286. }
  1287. }
  1288. //
  1289. // Window procedure
  1290. //
  1291. LRESULT APIENTRY
  1292. ReportWndProc (
  1293. HWND hWnd,
  1294. UINT uiMsg,
  1295. WPARAM wParam,
  1296. LPARAM lParam )
  1297. {
  1298. PREPORT pReport = NULL;
  1299. BOOL bCallDefProc = TRUE;
  1300. LRESULT lReturnValue = 0L;
  1301. RECT rect;
  1302. // hWnd is used to dispatch to window procedure, so major error if it is NULL.
  1303. assert ( NULL != hWnd );
  1304. pReport = (PREPORT)GetWindowLongPtr(hWnd,0);
  1305. if ( NULL == pReport ) {
  1306. if ( WM_CREATE == uiMsg && NULL != lParam ) {
  1307. pReport = (PREPORT)((CREATESTRUCT*)lParam)->lpCreateParams;
  1308. SetWindowLongPtr(hWnd,0,(INT_PTR)pReport);
  1309. } else {
  1310. // Programming error
  1311. assert ( FALSE );
  1312. }
  1313. } else {
  1314. bCallDefProc = FALSE ;
  1315. switch (uiMsg) {
  1316. case WM_DESTROY:
  1317. break ;
  1318. case WM_LBUTTONDOWN:
  1319. if (!pReport->m_pCtrl->IsUIDead()) {
  1320. // pReport->m_pCtrl->Activate();
  1321. // pReport->m_pCtrl->AssignFocus();
  1322. pReport->OnLButtonDown(LOWORD (lParam), HIWORD (lParam));
  1323. }
  1324. break;
  1325. case WM_CONTEXTMENU:
  1326. if (!pReport->m_pCtrl->IsUIDead()) {
  1327. // pReport->m_pCtrl->Activate();
  1328. // pReport->m_pCtrl->AssignFocus();
  1329. // *** DefWindowProc is not Smonctrl, so context menu not happening.
  1330. if (LOWORD(lParam)!= 0xffff || HIWORD(lParam) != 0xffff){
  1331. // Always call the default procedure, to handle the case where the
  1332. // context menu is activated from within a select rectangle.
  1333. bCallDefProc = TRUE;
  1334. }else {
  1335. if (!pReport->OnContextMenu(0,0))
  1336. bCallDefProc = TRUE;
  1337. }
  1338. }
  1339. break;
  1340. case WM_LBUTTONDBLCLK:
  1341. if (!pReport->m_pCtrl->IsUIDead()) {
  1342. // pReport->m_pCtrl->Activate();
  1343. // pReport->m_pCtrl->AssignFocus();
  1344. pReport->OnDblClick(LOWORD (lParam), HIWORD (lParam));
  1345. }
  1346. break;
  1347. case WM_ERASEBKGND:
  1348. GetClientRect(hWnd, &rect);
  1349. SetBkColor((HDC)wParam, pReport->m_pCtrl->clrBackPlot());
  1350. ClearRect((HDC)wParam, &rect);
  1351. lReturnValue = TRUE;
  1352. break;
  1353. case WM_PAINT:
  1354. pReport->OnPaint () ;
  1355. break ;
  1356. case WM_HSCROLL:
  1357. pReport->OnHScroll (LOWORD (wParam), HIWORD (wParam)) ;
  1358. break ;
  1359. case WM_VSCROLL:
  1360. pReport->OnVScroll (LOWORD (wParam), HIWORD (wParam)) ;
  1361. break ;
  1362. case WM_COMMAND:
  1363. if (pReport->m_pCtrl->IsUIDead())
  1364. break;
  1365. switch (LOWORD(wParam)) {
  1366. case IDM_REPORT_COPY:
  1367. case IDM_REPORT_COPYALL:
  1368. break;
  1369. case IDM_REPORT_DELETE:
  1370. pReport->DeleteSelection();
  1371. break;
  1372. case IDM_PROPERTIES:
  1373. pReport->m_pCtrl->DisplayProperties();
  1374. break;
  1375. case IDM_ADDCOUNTERS:
  1376. pReport->m_pCtrl->AddCounters();
  1377. break;
  1378. case IDM_SAVEAS:
  1379. pReport->m_pCtrl->SaveAs();
  1380. break;
  1381. default:
  1382. bCallDefProc = TRUE;
  1383. }
  1384. break;
  1385. default:
  1386. bCallDefProc = TRUE ;
  1387. }
  1388. }
  1389. if (bCallDefProc)
  1390. lReturnValue = DefWindowProc (hWnd, uiMsg, wParam, lParam) ;
  1391. return (lReturnValue);
  1392. }