/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: report.cpp Abstract: Implements the report view. --*/ //==========================================================================// // Includes // //==========================================================================// #include "polyline.h" #include #include #include #include "report.h" #include "grphitem.h" #include "winhelpr.h" #define eScaleValueSpace L">9999999999.0" #define szReportClass L"SysmonReport" #define szReportClassA "SysmonReport" #define HEXMASK (0x00030C00) static INT xBorderWidth = GetSystemMetrics(SM_CXBORDER); static INT yBorderHeight = GetSystemMetrics(SM_CYBORDER); static INT xColumnMargin = 10; static INT xCounterMargin = 50; static INT xObjectMargin = 25; static WCHAR LineEndStr[] = L"\n" ; static WCHAR TabStr[] = L"\t"; LRESULT APIENTRY HdrWndProc (HWND, WORD, WPARAM, LONG); //==========================================================================// // Constants // //==========================================================================// #define dwReportClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS) #define iReportWindowExtra (sizeof (PREPORT)) #define dwReportWindowStyle (WS_CHILD | WS_HSCROLL | WS_VSCROLL) #define szValuePlaceholder L"-999,999,999.999" #define szValueLargeHexPlaceholder L" xBBBBBBBBDDDDDDDD" #define dLargeValueMax ((double) 999999999.0) #define szDashLine L"---" CReport::CReport ( void ) { m_pCtrl = NULL; m_hWnd = NULL; m_yLineHeight = 0; m_xReportWidth = 0; m_yReportHeight = 0; m_pSelect = NULL; } // // Destructor // CReport::~CReport (void ) { if (m_hWnd != NULL && IsWindow(m_hWnd)) DestroyWindow(m_hWnd); } // // Initialization // BOOL CReport::Init ( PSYSMONCTRL pCtrl, HWND hWndParent ) { WNDCLASS wc ; LONG lExStyles; // Save pointer to parent control m_pCtrl = pCtrl; BEGIN_CRITICAL_SECTION // Register window class once if (pstrRegisteredClasses[REPORT_WNDCLASS] == NULL) { wc.style = dwReportClassStyle ; wc.lpfnWndProc = ReportWndProc ; wc.hInstance = g_hInstance ; wc.cbClsExtra = 0; wc.cbWndExtra = iReportWindowExtra ; wc.hIcon = NULL ; wc.hCursor = LoadCursor (NULL, IDC_ARROW) ; wc.hbrBackground = NULL ; wc.lpszMenuName = NULL ; wc.lpszClassName = szReportClass ; if (RegisterClass (&wc)) { pstrRegisteredClasses[REPORT_WNDCLASS] = szReportClass; } // Ensure controls are initialized InitCommonControls(); } END_CRITICAL_SECTION if (pstrRegisteredClasses[REPORT_WNDCLASS] == NULL) return FALSE; // Create our window m_hWnd = CreateWindow (szReportClass, // class NULL, // caption dwReportWindowStyle, // window style 0, 0, // position 0, 0, // size hWndParent, // parent window NULL, // menu g_hInstance, // program instance (LPVOID) this ); // user-supplied data if (m_hWnd == NULL) return FALSE; // Turn off layout mirroring if it is enabled lExStyles = GetWindowLong(m_hWnd, GWL_EXSTYLE); if ( 0 != ( lExStyles & WS_EX_LAYOUTRTL ) ) { lExStyles &= ~WS_EX_LAYOUTRTL; SetWindowLong(m_hWnd, GWL_EXSTYLE, lExStyles); } return TRUE; } void CReport::ChangeFont ( void ) { if (!m_bFontChange) { m_bFontChange = TRUE; if (!m_bConfigChange) { m_bConfigChange = TRUE; WindowInvalidate(m_hWnd); } } } void CReport::SizeComponents ( LPRECT pRect ) { INT xWidth; INT yHeight; m_rect = *pRect; xWidth = pRect->right - pRect->left; yHeight = pRect->bottom - pRect->top; // If no space, hide window and leave if (xWidth == 0 || yHeight == 0) { WindowShow(m_hWnd, FALSE); return; } // Show window to assigned position MoveWindow(m_hWnd, pRect->left, pRect->top, xWidth, yHeight, FALSE); WindowShow(m_hWnd, TRUE); WindowInvalidate(m_hWnd); SetScrollRanges(); } INT CReport::SetCounterPositions ( PCObjectNode pObject, HDC hDC ) { PCCounterNode pCounter; INT yPos; yPos = pObject->m_yPos + m_yLineHeight; for (pCounter = pObject->FirstCounter(); pCounter; pCounter = pCounter->Next()) { if (m_bFontChange || pCounter->m_xWidth == -1) { pCounter->m_xWidth = TextWidth(hDC, pCounter->Name()); } if (pCounter->m_xWidth > m_xMaxCounterWidth) m_xMaxCounterWidth = pCounter->m_xWidth; pCounter->m_yPos = yPos; yPos += m_yLineHeight; } return yPos; } INT CReport::SetInstancePositions ( PCObjectNode pObject, HDC hDC ) { INT xPos ; PCInstanceNode pInstance; LPWSTR szParent; LPWSTR szInstance; xPos = 0; for (pInstance = pObject->FirstInstance(); pInstance; pInstance = pInstance->Next()) { if (m_bFontChange || pInstance->m_xWidth == -1) { if (pInstance->HasParent()) { szParent = pInstance->GetParentName(); szInstance = pInstance->GetInstanceName(); pInstance->m_xWidth = max(TextWidth(hDC, szParent), TextWidth(hDC, szInstance)); } else { pInstance->m_xWidth = TextWidth(hDC, pInstance->Name()); } } pInstance->m_xPos = xPos + max(pInstance->m_xWidth, m_xValueWidth); xPos = pInstance->m_xPos + xColumnMargin; } if (xPos > m_xMaxInstancePos) m_xMaxInstancePos = xPos; return xPos; } INT CReport::SetObjectPositions ( PCMachineNode pMachine, HDC hDC ) { PCObjectNode pObject; INT yPos; INT xPos; yPos = pMachine->m_yPos + m_yLineHeight; for (pObject = pMachine->FirstObject(); pObject ; pObject = pObject->Next()) { if (m_bFontChange || pObject->m_xWidth == -1) { pObject->m_xWidth = TextWidth(hDC, pObject->Name()); } if (!pObject->FirstInstance()->HasParent()) pObject->m_yPos = yPos; else pObject->m_yPos = yPos + m_yLineHeight; yPos = SetCounterPositions (pObject, hDC) ; xPos = SetInstancePositions(pObject, hDC); yPos += m_yLineHeight; } return yPos; } INT CReport::SetMachinePositions ( PCCounterTree pTree, HDC hDC ) { PCMachineNode pMachine ; INT yPos ; yPos = m_yLineHeight; for (pMachine = pTree->FirstMachine() ; pMachine ; pMachine = pMachine->Next()) { if (m_bFontChange || pMachine->m_xWidth == -1) { pMachine->m_xWidth = TextWidth(hDC, pMachine->Name()); } pMachine->m_yPos = yPos; yPos = SetObjectPositions (pMachine, hDC); } m_yReportHeight = yPos + yBorderHeight; return yPos; } void CReport::DrawSelectRect ( HDC hDC, BOOL bState ) { BOOL bSuccess = TRUE; RECT rect = {0,0,0,0}; HBRUSH hbrush; if ( NULL != m_pSelect && NULL != hDC ) { switch ( m_nSelectType ) { case MACHINE_NODE: rect.left = xColumnMargin; rect.top = ((PCMachineNode)m_pSelect)->m_yPos; rect.right = rect.left + ((PCMachineNode)m_pSelect)->m_xWidth; rect.bottom = rect.top + m_yLineHeight; break; case OBJECT_NODE: rect.left = xObjectMargin; rect.top = ((PCObjectNode)m_pSelect)->m_yPos; rect.right = rect.left + ((PCObjectNode)m_pSelect)->m_xWidth; rect.bottom = rect.top + m_yLineHeight; break; case INSTANCE_NODE: rect.right = m_xInstanceMargin + ((PCInstanceNode)m_pSelect)->m_xPos; rect.bottom = ((PCInstanceNode)m_pSelect)->m_pObject->m_yPos + m_yLineHeight; rect.left = rect.right - ((PCInstanceNode)m_pSelect)->m_xWidth; rect.top = rect.bottom - (((PCInstanceNode)m_pSelect)->HasParent() ? (2*m_yLineHeight) : m_yLineHeight); break; case COUNTER_NODE: rect.left = xCounterMargin; rect.top = ((PCCounterNode)m_pSelect)->m_yPos; rect.right = rect.left + ((PCCounterNode)m_pSelect)->m_xWidth; rect.bottom = rect.top + m_yLineHeight; break; case ITEM_NODE: rect.right = m_xInstanceMargin + ((PCGraphItem)m_pSelect)->m_pInstance->m_xPos; rect.top = ((PCGraphItem)m_pSelect)->m_pCounter->m_yPos; rect.left = rect.right - m_xValueWidth; rect.bottom = rect.top + m_yLineHeight; break; default: bSuccess = FALSE; } if ( bSuccess ) { rect.left -= 1; rect.right += 1; hbrush = CreateSolidBrush(bState ? m_pCtrl->clrFgnd() : m_pCtrl->clrBackPlot()); if ( NULL != hbrush ) { FrameRect(hDC, &rect, hbrush); DeleteObject(hbrush); } } } return; } BOOL CReport::LargeHexValueExists ( void ) { PCMachineNode pMachine = NULL; PCObjectNode pObject = NULL; PCInstanceNode pInstance = NULL; PCCounterNode pCounter = NULL; PCGraphItem pItem = NULL; BOOL bLargeHexValueExists = FALSE; for (pMachine = m_pCtrl->CounterTree()->FirstMachine(); pMachine && !bLargeHexValueExists; pMachine = pMachine->Next()) { for (pObject = pMachine->FirstObject(); pObject && !bLargeHexValueExists; pObject = pObject->Next()) { for (pInstance = pObject->FirstInstance(); pInstance && !bLargeHexValueExists; pInstance = pInstance->Next()) { pItem = pInstance->FirstItem(); for (pCounter = pObject->FirstCounter(); pCounter && !bLargeHexValueExists; pCounter = pCounter->Next()) { PCGraphItem pCheckItem = NULL; if (pItem && pItem->m_pCounter == pCounter) { pCheckItem = pItem; pItem = pItem->m_pNextItem; } if ( pCheckItem ) { if ( !( pCheckItem->m_CounterInfo.dwType & HEXMASK ) ) { bLargeHexValueExists = pCheckItem->m_CounterInfo.dwType & PERF_SIZE_LARGE; if ( bLargeHexValueExists ) { break; } } } } } } } return bLargeHexValueExists; } void CReport::DrawReportValue ( HDC hDC, PCGraphItem pItem, INT xPos, INT yPos ) { double dMax; double dMin; double dValue = -1.0; WCHAR szValue [MAX_VALUE_LEN] = L"_" ; HRESULT hr; long lCtrStat; RECT rect ; INT iPrecision; if ( NULL != pItem && NULL != hDC ) { eReportValueTypeConstant eValueType; eValueType = m_pCtrl->ReportValueType(); if ( sysmonDefaultValue == eValueType ) { // if log source display the average value // else display the current value if (m_pCtrl->IsLogSource()) { hr = pItem->GetStatistics(&dMax, &dMin, &dValue, &lCtrStat); } else { hr = pItem->GetValue(&dValue, &lCtrStat); } } else { if ( sysmonCurrentValue == eValueType ) { hr = pItem->GetValue(&dValue, &lCtrStat); } else { double dAvg; hr = pItem->GetStatistics(&dMax, &dMin, &dAvg, &lCtrStat); switch ( eValueType ) { case sysmonAverage: dValue = dAvg; break; case sysmonMinimum: dValue = dMin; break; case sysmonMaximum: dValue = dMax; break; default: assert (FALSE); } } } if (SUCCEEDED(hr) && IsSuccessSeverity(lCtrStat)) { assert ( 0 <= dValue ); if ( ( pItem->m_CounterInfo.dwType & ( PERF_TYPE_COUNTER | PERF_TYPE_TEXT ) ) ) { (dValue > dLargeValueMax) ? iPrecision = 0 : iPrecision = 3; } else { // for Numbers, no decimal places iPrecision = 0; } if(PDH_CSTATUS_INVALID_DATA != pItem->m_CounterInfo.CStatus ) { // Check for Hex values if ( !(pItem->m_CounterInfo.dwType & HEXMASK) ) { BOOL bLarge = pItem->m_CounterInfo.dwType & PERF_SIZE_LARGE; FormatHex ( dValue, szValue, bLarge); } else { FormatNumber ( dValue, szValue, MAX_VALUE_LEN, 12, iPrecision ); } } } else { StringCchCopy(szValue, MAX_VALUE_LEN, szDashLine); } } else { StringCchCopy(szValue, MAX_VALUE_LEN, szDashLine); } rect.right = xPos - 1; rect.left = xPos - m_xValueWidth + 1; rect.top = yPos; rect.bottom = yPos + m_yLineHeight; ExtTextOut (hDC, rect.right, rect.top, ETO_CLIPPED | ETO_OPAQUE, &rect, szValue, lstrlen (szValue), NULL) ; } void CReport::DrawReportValues ( HDC hDC ) { PCMachineNode pMachine; PCObjectNode pObject; PCInstanceNode pInstance; PCCounterNode pCounter; PCGraphItem pItem; PCGraphItem pDrawItem; if ( NULL != hDC ) { SelectFont (hDC, m_pCtrl->Font()); SetTextAlign (hDC, TA_RIGHT|TA_TOP); for (pMachine = m_pCtrl->CounterTree()->FirstMachine(); pMachine; pMachine = pMachine->Next()) { for (pObject = pMachine->FirstObject(); pObject; pObject = pObject->Next()) { for (pInstance = pObject->FirstInstance(); pInstance; pInstance = pInstance->Next()) { pItem = pInstance->FirstItem(); for ( pCounter = pObject->FirstCounter(); pCounter; pCounter = pCounter->Next()) { if (pItem && pItem->m_pCounter == pCounter) { pDrawItem = pItem; pItem = pItem->m_pNextItem; } else { pDrawItem = NULL; } DrawReportValue ( hDC, pDrawItem, m_xInstanceMargin + pInstance->m_xPos, pCounter->m_yPos); } } } } } } LPWSTR GetBuffer(LPWSTR pBuffer, LONG* lBufSize, LONG lSize) { LPWSTR pNew; if (lSize < *(lBufSize)) { return pBuffer; } if (pBuffer) { delete [] pBuffer; *(lBufSize) = 0; } pNew = new WCHAR [lSize]; if (pNew == NULL) { return NULL; } *(lBufSize) = lSize; return pNew; } BOOL CReport::WriteFileReport ( HANDLE hFile ) { PCMachineNode pMachine; PCObjectNode pObject; PCInstanceNode pInstance; PCCounterNode pCounter; LPWSTR pszTemp = NULL; LONG lSize = 0; LONG lBufSize = 0; PCGraphItem pItem; BOOL bStatus = TRUE; WCHAR szValue[MAX_VALUE_LEN]; lBufSize = MAX_PATH; pszTemp = new WCHAR [lBufSize]; if (pszTemp == NULL) { return FALSE; } for (pMachine = m_pCtrl->CounterTree()->FirstMachine() ; pMachine && TRUE == bStatus; pMachine = pMachine->Next()) { lSize = 3 * lstrlen(LineEndStr) + lstrlen(ResourceString(IDS_COMPUTER)) + lstrlen(pMachine->Name()) + 1; pszTemp = GetBuffer(pszTemp, &lBufSize, lSize); if (pszTemp == NULL) { goto ErrorOut; } StringCchCopy(pszTemp, lBufSize, LineEndStr); StringCchCat(pszTemp, lBufSize, LineEndStr); StringCchCat(pszTemp, lBufSize, ResourceString(IDS_COMPUTER)); StringCchCat(pszTemp, lBufSize, pMachine->Name()); StringCchCat(pszTemp, lBufSize, LineEndStr); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); for (pObject = pMachine->FirstObject() ; pObject && TRUE == bStatus; pObject = pObject->Next()) { // Write the object name line. lSize = 2 * lstrlen(LineEndStr) + lstrlen(TabStr) + lstrlen(ResourceString(IDS_OBJECT_NAME)) + lstrlen(pObject->Name()) + 1; pszTemp = GetBuffer(pszTemp, &lBufSize, lSize); if (pszTemp == NULL) { goto ErrorOut; } StringCchCopy(pszTemp, lBufSize, LineEndStr); StringCchCat(pszTemp, lBufSize, ResourceString(IDS_OBJECT_NAME)); StringCchCat(pszTemp, lBufSize, pObject->Name()); StringCchCat(pszTemp, lBufSize, LineEndStr); // Add first tab char for instance names. StringCchCat(pszTemp, lBufSize, TabStr); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); if (!bStatus) break; // Write the first line of instance (parent) names. for (pInstance = pObject->FirstInstance(); pInstance && TRUE == bStatus; pInstance = pInstance->Next()) { // If instance has no parent, then the parent name is null, so a tab is written. lSize = lstrlen(TabStr) + lstrlen(LineEndStr) + lstrlen(pInstance->GetParentName()) + 1; pszTemp = GetBuffer(pszTemp, &lBufSize, lSize); if (pszTemp == NULL) { goto ErrorOut; } StringCchCopy(pszTemp, lBufSize, TabStr); StringCchCat(pszTemp, lBufSize, pInstance->GetParentName()); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); } if ( !bStatus ) break; StringCchCopy(pszTemp, lBufSize, LineEndStr); // Include first tab of second instance line. StringCchCat(pszTemp, lBufSize, TabStr); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); // Write the second line of instance names. for (pInstance = pObject->FirstInstance(); pInstance && TRUE == bStatus; pInstance = pInstance->Next()) { lSize = lstrlen(TabStr) + lstrlen(LineEndStr)+ lstrlen(pInstance->GetInstanceName()) + 1; pszTemp = GetBuffer(pszTemp, &lBufSize, lSize); if (pszTemp == NULL) { goto ErrorOut; } StringCchCopy(pszTemp, lBufSize, TabStr); StringCchCat(pszTemp, lBufSize, pInstance->GetInstanceName()); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); } if (!bStatus) break; StringCchCopy(pszTemp, lBufSize, LineEndStr); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); for (pCounter = pObject->FirstCounter(); pCounter && TRUE == bStatus; pCounter = pCounter->Next()) { lSize = lstrlen(TabStr) + lstrlen(LineEndStr)+ lstrlen(pCounter->Name()) + 1; pszTemp = GetBuffer(pszTemp, &lBufSize, lSize); if (pszTemp == NULL) { goto ErrorOut; } // Write counter name StringCchCopy(pszTemp, lBufSize, TabStr); StringCchCat(pszTemp, lBufSize, pCounter->Name()); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); // Write values, looping on instances for ( pInstance = pObject->FirstInstance(); pInstance && TRUE == bStatus; pInstance = pInstance->Next()) { // Loop on items to find the item that matches the counter. for ( pItem = pInstance->FirstItem(); pItem && TRUE == bStatus; pItem = pItem->m_pNextItem) { if ( pItem->m_pCounter == pCounter && pInstance) { GetReportItemValue(pItem,szValue ); lSize = lstrlen(TabStr) + lstrlen(LineEndStr)+ lstrlen(szValue) + 1; pszTemp = GetBuffer(pszTemp, &lBufSize, lSize); if (pszTemp == NULL) { goto ErrorOut; } StringCchCopy(pszTemp, lBufSize, TabStr); StringCchCat(pszTemp, lBufSize, szValue); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); } } } if (!bStatus) break; StringCchCopy(pszTemp, lBufSize, LineEndStr); bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(WCHAR) ); } } } if (pszTemp) { delete [] pszTemp; } return bStatus; ErrorOut: if (pszTemp) { delete [] pszTemp; } return FALSE; } void CReport::GetReportItemValue(PCGraphItem pItem, LPWSTR szValue) { double dMax; double dMin; double dValue = -1.0; HRESULT hr; long lCtrStat; INT iPrecision; if (pItem) { eReportValueTypeConstant eValueType; eValueType = m_pCtrl->ReportValueType(); if ( sysmonDefaultValue == eValueType ) { // if log source display the average value // else display the current value if (m_pCtrl->IsLogSource()) { hr = pItem->GetStatistics(&dMax, &dMin, &dValue, &lCtrStat); } else { hr = pItem->GetValue(&dValue, &lCtrStat); } } else { if ( sysmonCurrentValue == eValueType ) { hr = pItem->GetValue(&dValue, &lCtrStat); } else { double dAvg; hr = pItem->GetStatistics(&dMax, &dMin, &dAvg, &lCtrStat); switch ( eValueType ) { case sysmonAverage: dValue = dAvg; break; case sysmonMinimum: dValue = dMin; break; case sysmonMaximum: dValue = dMax; break; default: assert (FALSE); } } } if (SUCCEEDED(hr) && IsSuccessSeverity(lCtrStat)) { assert ( 0 <= dValue ); (dValue > dLargeValueMax) ? iPrecision = 0 : iPrecision = 3; if(PDH_CSTATUS_INVALID_DATA != pItem->m_CounterInfo.CStatus ) { // Check for Hex values if ( !(pItem->m_CounterInfo.dwType & HEXMASK) ) { BOOL bLarge = pItem->m_CounterInfo.dwType & PERF_SIZE_LARGE; FormatHex ( dValue, szValue, bLarge); } else { FormatNumber ( dValue, szValue, MAX_VALUE_LEN, 12, iPrecision ); } } } else { StringCchCopy(szValue, MAX_VALUE_LEN, szDashLine); } } else { StringCchCopy(szValue, MAX_VALUE_LEN, szDashLine); } return; } void CReport::DrawReportHeaders ( HDC hDC ) { PCMachineNode pMachine; PCObjectNode pObject; PCInstanceNode pInstance; PCCounterNode pCounter; INT cName; RECT rectMachine; RECT rectObject; RECT rectInstance; RECT rectCounter; if ( NULL != hDC ) { SetTextAlign(hDC, TA_LEFT|TA_TOP) ; rectMachine.left = xColumnMargin; rectObject.left = xObjectMargin; rectCounter.left = xCounterMargin; for ( pMachine = m_pCtrl->CounterTree()->FirstMachine() ; pMachine; pMachine = pMachine->Next()) { rectMachine.right = rectMachine.left + pMachine->m_xWidth; rectMachine.top = pMachine->m_yPos; rectMachine.bottom = pMachine->m_yPos + m_yLineHeight; ExtTextOut ( hDC, xColumnMargin, pMachine->m_yPos, ETO_OPAQUE, &rectMachine, pMachine->Name(), lstrlen(pMachine->Name()), NULL ); for ( pObject = pMachine->FirstObject() ; pObject ; pObject = pObject->Next()) { rectObject.right = rectObject.left + pObject->m_xWidth; rectObject.top = pObject->m_yPos; rectObject.bottom = pObject->m_yPos + m_yLineHeight; ExtTextOut ( hDC, xObjectMargin, pObject->m_yPos, ETO_OPAQUE, &rectObject, pObject->Name(), lstrlen (pObject->Name()), NULL); SetTextAlign (hDC, TA_RIGHT) ; for ( pInstance = pObject->FirstInstance(); pInstance; pInstance = pInstance->Next()) { rectInstance.left = m_xInstanceMargin + pInstance->m_xPos; rectInstance.right = rectInstance.left + max(pInstance->m_xWidth, m_xValueWidth); if ( pInstance->HasParent() ) { cName = lstrlen(pInstance->GetParentName()); rectInstance.top = pObject->m_yPos - m_yLineHeight; rectInstance.bottom = rectInstance.top + m_yLineHeight; ExtTextOut ( hDC, m_xInstanceMargin + pInstance->m_xPos, pObject->m_yPos - m_yLineHeight, ETO_OPAQUE, &rectInstance, pInstance->GetParentName(), cName, NULL); rectInstance.top = pObject->m_yPos; rectInstance.bottom = rectInstance.top + m_yLineHeight; cName = lstrlen(pInstance->GetInstanceName()); ExtTextOut ( hDC, m_xInstanceMargin + pInstance->m_xPos, pObject->m_yPos, ETO_OPAQUE, &rectInstance, pInstance->GetInstanceName(), cName, NULL ); } else { rectInstance.top = pObject->m_yPos; rectInstance.bottom = rectInstance.top + m_yLineHeight; ExtTextOut ( hDC, m_xInstanceMargin + pInstance->m_xPos, pObject->m_yPos, ETO_OPAQUE, &rectInstance, pInstance->Name(), lstrlen(pInstance->Name()), NULL ); } } SetTextAlign (hDC, TA_LEFT) ; for (pCounter = pObject->FirstCounter(); pCounter ; pCounter = pCounter->Next()) { rectCounter.right = rectCounter.left + pCounter->m_xWidth; rectCounter.top = pCounter->m_yPos; rectCounter.bottom = pCounter->m_yPos + m_yLineHeight; ExtTextOut ( hDC, xCounterMargin, pCounter->m_yPos, ETO_OPAQUE, &rectCounter, pCounter->Name(), lstrlen (pCounter->Name()), NULL); } } } DrawSelectRect(hDC, TRUE); } } void CReport::ApplyChanges ( HDC hDC ) { if (m_bConfigChange && NULL != hDC ) { // Selected the Bold font for font change , counter add, and counter delete. // This is used for recalculating text width. SelectFont (hDC, m_pCtrl->BoldFont()); m_yLineHeight = FontHeight (hDC, TRUE); if ( LargeHexValueExists ( ) ) { m_xValueWidth = TextWidth(hDC, szValueLargeHexPlaceholder); } else { m_xValueWidth = TextWidth(hDC, szValuePlaceholder); } m_xMaxCounterWidth = 0; m_xMaxInstancePos = 0; SetMachinePositions (m_pCtrl->CounterTree(), hDC); m_xInstanceMargin = xCounterMargin + m_xMaxCounterWidth + xColumnMargin; m_xReportWidth = m_xInstanceMargin + m_xMaxInstancePos; SetScrollRanges(); m_bConfigChange = FALSE; m_bFontChange = FALSE; } } void CReport::Render ( HDC hDC, HDC hAttribDC, BOOL /*fMetafile*/, BOOL /*fEntire*/, LPRECT prcUpdate ) { ApplyChanges(hAttribDC); if ( NULL != hDC ) { SetBkColor(hDC, m_pCtrl->clrBackPlot()); ClearRect(hDC, prcUpdate); Draw( hDC ); } } void CReport::Draw ( HDC hDC ) { // if no space assigned, return if (m_rect.top != m_rect.bottom) { if ( NULL != hDC ) { SetTextColor (hDC, m_pCtrl->clrFgnd()); SetBkColor(hDC, m_pCtrl->clrBackPlot()); SelectFont(hDC, m_pCtrl->BoldFont()); DrawReportHeaders (hDC); SelectFont (hDC, m_pCtrl->Font()); DrawReportValues (hDC); m_pCtrl->DrawBorder ( hDC ); } } } void CReport::AddItem ( PCGraphItem /* pItem */ ) { if (!m_bConfigChange) { m_bConfigChange = TRUE; WindowInvalidate(m_hWnd); } } void CReport::DeleteItem ( PCGraphItem pItem ) { // Calling procedure checks for NULL pItem assert ( NULL != pItem ); if ( NULL != m_pSelect ) { if ( SelectionDeleted ( pItem ) ) { m_pSelect = NULL; } } if (!m_bConfigChange) { m_bConfigChange = TRUE; WindowInvalidate(m_hWnd); } } void CReport::DeleteSelection ( VOID ) { if (m_pSelect == NULL) return; switch (m_nSelectType) { case MACHINE_NODE: ((PCMachineNode)m_pSelect)->DeleteNode(TRUE); break; case OBJECT_NODE: ((PCObjectNode)m_pSelect)->DeleteNode(TRUE); break; case INSTANCE_NODE: ((PCInstanceNode)m_pSelect)->DeleteNode(TRUE); break; case COUNTER_NODE: ((PCCounterNode)m_pSelect)->DeleteNode(TRUE); break; case ITEM_NODE: ((PCGraphItem)m_pSelect)->Delete(TRUE); break; default: return; } // DeleteItem sets m_pSelect to NULL and invalidates the window. assert ( NULL == m_pSelect ); } BOOL CReport::OnContextMenu ( INT x, INT y ) { HMENU hMenu; HMENU hMenuPopup; RECT clntRect; int xPos=0,yPos=0; GetWindowRect(m_hWnd,&clntRect); if (x==0){ xPos = ((clntRect.right - clntRect.left)/2) ; }else{ xPos = x - clntRect.left; } if (y==0){ yPos = ((clntRect.bottom - clntRect.top)/2) ; }else{ yPos = y - clntRect.top; } x = clntRect.left + xPos ; y = clntRect.top + yPos ; // if nothing is selected, let main window handle the menu if (m_pSelect == NULL) return FALSE; if ( m_pCtrl->ConfirmSampleDataOverwrite() ) { if ( !m_pCtrl->IsReadOnly() ) { // Get the menu for the pop-up menu from the resource file. hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_CONTEXT)); if (!hMenu) return TRUE; // Get the first submenu in it for TrackPopupMenu. hMenuPopup = GetSubMenu(hMenu, 0); // Draw and track the "floating" pop-up menu. TrackPopupMenu(hMenuPopup, TPM_RIGHTBUTTON, x, y, 0, m_hWnd, NULL); // Destroy the menu. DestroyMenu(hMenu); } } return TRUE; } void CReport::Update ( void ) { HDC hDC; hDC = GetDC(m_hWnd); if ( NULL != hDC ) { ApplyChanges(hDC); SetWindowOrgEx (hDC, GetScrollPos (m_hWnd, SB_HORZ), GetScrollPos (m_hWnd, SB_VERT), NULL) ; if ( m_rect.bottom != m_rect.top ) { SelectFont (hDC, m_pCtrl->Font()); SetTextColor (hDC, m_pCtrl->clrFgnd()); SetBkColor(hDC, m_pCtrl->clrBackPlot()); DrawReportValues(hDC); } ReleaseDC(m_hWnd,hDC); } } void CReport::OnPaint ( void ) { HDC hDC ; PAINTSTRUCT ps ; hDC = BeginPaint (m_hWnd, &ps) ; if ( NULL != hDC ) { SelectFont (hDC, m_pCtrl->Font()) ; SetWindowOrgEx ( hDC, GetScrollPos (m_hWnd, SB_HORZ), GetScrollPos (m_hWnd, SB_VERT), NULL ); SetTextColor (hDC, m_pCtrl->clrFgnd()); SetBkColor(hDC, m_pCtrl->clrBackPlot()); ApplyChanges(hDC); Draw(hDC); EndPaint (m_hWnd, &ps) ; } } void CReport::SetScrollRanges ( void ) { RECT rectClient ; INT xWidth, yHeight ; GetClientRect (m_hWnd, &rectClient) ; xWidth = rectClient.right - rectClient.left ; yHeight = rectClient.bottom - rectClient.top ; SetScrollRange (m_hWnd, SB_VERT, 0, max (0, m_yReportHeight - yHeight), TRUE) ; SetScrollRange (m_hWnd, SB_HORZ,0, max (0, m_xReportWidth - xWidth), TRUE) ; } BOOL CReport::SelectName ( INT xPos, INT yPos, void** ppSelected, INT* piSelectType ) { POINT pt; PCMachineNode pMachine; PCObjectNode pObject; PCCounterNode pCounter; PCInstanceNode pInstance; PCGraphItem pItem; // Programming error if either of these two pointers is NULL. assert ( NULL != ppSelected ); assert ( NULL != piSelectType ); // Adjust coordinates by scroll offset pt.x = xPos + GetScrollPos(m_hWnd, SB_HORZ); pt.y = yPos + GetScrollPos(m_hWnd, SB_VERT); for (pMachine = m_pCtrl->CounterTree()->FirstMachine() ; pMachine; pMachine = pMachine->Next()) { if (PtInName(pt, xColumnMargin, pMachine->m_yPos, pMachine->m_xWidth)) { *ppSelected = pMachine; *piSelectType = MACHINE_NODE; return TRUE; } for (pObject = pMachine->FirstObject() ; pObject ; pObject = pObject->Next()) { if (PtInName(pt, xObjectMargin, pObject->m_yPos, pObject->m_xWidth)) { *ppSelected = pObject; *piSelectType = OBJECT_NODE; return TRUE; } for (pCounter = pObject->FirstCounter(); pCounter ; pCounter = pCounter->Next()) { if (PtInName(pt, xCounterMargin, pCounter->m_yPos, pCounter->m_xWidth)) { *ppSelected = pCounter; *piSelectType = COUNTER_NODE; return TRUE; } } for (pInstance = pObject->FirstInstance(); pInstance ; pInstance = pInstance->Next()) { INT xInstancePos = m_xInstanceMargin + pInstance->m_xPos; if (PtInName(pt, xInstancePos - pInstance->m_xWidth, pObject->m_yPos, pInstance->m_xWidth) || (pInstance->HasParent() && PtInName(pt, xInstancePos - pInstance->m_xWidth, pObject->m_yPos - m_yLineHeight, pInstance->m_xWidth))) { *ppSelected = pInstance; *piSelectType = INSTANCE_NODE; return TRUE; } if (pt.x > xInstancePos || pt.x < xInstancePos - m_xValueWidth) continue; for (pItem = pInstance->FirstItem(); pItem; pItem = pItem->m_pNextItem) { if (pt.y > pItem->m_pCounter->m_yPos && pt.y < pItem->m_pCounter->m_yPos + m_yLineHeight) { *ppSelected = pItem; *piSelectType = ITEM_NODE; return TRUE; } } } } } *ppSelected = NULL; return FALSE; } PCGraphItem CReport::GetItem ( void *pSelected, INT nSelectType ) { PCMachineNode pMachine; PCObjectNode pObject; PCCounterNode pCounter; PCInstanceNode pInstance; PCGraphItem pItem; PCGraphItem pReturn = NULL; if ( NULL != pSelected ) { switch (nSelectType) { case MACHINE_NODE: pMachine = (PCMachineNode)pSelected; pObject = pMachine->FirstObject(); if ( NULL != pObject ) { pInstance = pObject->FirstInstance(); if ( NULL != pInstance ) { pReturn = pInstance->FirstItem(); } } break; case OBJECT_NODE: pObject = (PCObjectNode)pSelected; pInstance = pObject->FirstInstance(); if ( NULL != pInstance ) { pReturn = pInstance->FirstItem(); } break; case INSTANCE_NODE: pInstance = (PCInstanceNode)pSelected; pReturn = pInstance->FirstItem(); break; case COUNTER_NODE: pCounter = (PCCounterNode)pSelected; pObject = pCounter->m_pObject; for (pInstance = pObject->FirstInstance(); ((NULL != pInstance) && (NULL == pReturn)); pInstance = pInstance->Next()) { for (pItem = pInstance->FirstItem(); ((NULL != pItem) && (NULL == pReturn)); pItem = pItem->m_pNextItem) { if (pItem && pItem->m_pCounter == pCounter) { pReturn = pItem; } } } break; case ITEM_NODE: pReturn = (PCGraphItem)pSelected; break; default: break; } } return pReturn; } BOOL CReport::SelectionDeleted ( PCGraphItem pDeletedItem ) { BOOL bSelectionDeleted = FALSE; INT iItemCount = 0; PCMachineNode pMachine; PCObjectNode pObject; PCCounterNode pCounter; PCInstanceNode pInstance; PCGraphItem pItem; if ( NULL == m_pSelect ) return FALSE; // Delete the selection if this is the last remaining // item for the selection object. switch (m_nSelectType) { case MACHINE_NODE: // Check for multiple items for this machine. pMachine = (PCMachineNode)m_pSelect; for ( pObject = pMachine->FirstObject(); ( NULL != pObject ) && ( 2 > iItemCount ); pObject = pObject->Next()) { for ( pInstance = pObject->FirstInstance(); ( NULL != pInstance ) && ( 2 > iItemCount ); pInstance = pInstance->Next()) { for ( pItem = pInstance->FirstItem(); ( NULL != pItem ) && ( 2 > iItemCount ); pItem = pItem->m_pNextItem) { iItemCount++; } } } bSelectionDeleted = ( iItemCount < 2 ); break; case OBJECT_NODE: // Check for multiple items for this object. pObject = (PCObjectNode)m_pSelect; for ( pInstance = pObject->FirstInstance(); ( NULL != pInstance ) && ( 2 > iItemCount ); pInstance = pInstance->Next()) { for ( pItem = pInstance->FirstItem(); ( NULL != pItem ) && ( 2 > iItemCount ); pItem = pItem->m_pNextItem) { iItemCount++; } } bSelectionDeleted = ( iItemCount < 2 ); break; case INSTANCE_NODE: // Check for multiple items (counters) for this instance. pInstance = (PCInstanceNode)m_pSelect; iItemCount = 0; for ( pItem = pInstance->FirstItem(); ( NULL != pItem ) && ( 2 > iItemCount ); pItem = pItem->m_pNextItem) { iItemCount++; } bSelectionDeleted = ( iItemCount < 2 ); break; case COUNTER_NODE: // Check for multiple items (instances) for this counter. pCounter = (PCCounterNode)m_pSelect; pObject = pCounter->m_pObject; for ( pInstance = pObject->FirstInstance(); ( NULL != pInstance ) && ( 2 > iItemCount ); pInstance = pInstance->Next()) { for ( pItem = pInstance->FirstItem(); ( NULL != pItem ) && ( 2 > iItemCount ); pItem = pItem->m_pNextItem) { if (pItem && pItem->m_pCounter == pCounter) { iItemCount++; break; } } } bSelectionDeleted = ( iItemCount < 2 ); break; case ITEM_NODE: // Selection matches the deleted item. bSelectionDeleted = ( pDeletedItem == (PCGraphItem)m_pSelect ); break; default: break; } return bSelectionDeleted; } void CReport::OnLButtonDown ( INT xPos, INT yPos ) { PCGraphItem pItem; HDC hDC = GetDC(m_hWnd); if ( NULL != hDC ) { SetWindowOrgEx ( hDC, GetScrollPos (m_hWnd, SB_HORZ), GetScrollPos (m_hWnd, SB_VERT), NULL) ; DrawSelectRect(hDC, FALSE); if ( SelectName(xPos, yPos, &m_pSelect, &m_nSelectType) ) DrawSelectRect(hDC, TRUE); ReleaseDC(m_hWnd, hDC); pItem = GetItem(m_pSelect, m_nSelectType); m_pCtrl->SelectCounter(pItem); } return; } void CReport:: OnDblClick ( INT, // xPos, INT // yPos ) { PCGraphItem pItem; pItem = GetItem ( m_pSelect, m_nSelectType ); m_pCtrl->DblClickCounter ( pItem ); } void CReport::OnHScroll ( INT iScrollCode, INT iScrollNewPos ) { INT iScrollAmt, iScrollPos, iScrollRange ; INT iScrollLo ; RECT rectClient ; INT xWidth ; GetClientRect (m_hWnd, &rectClient) ; xWidth = rectClient.right - rectClient.left ; if (m_xReportWidth <= xWidth) return ; iScrollPos = GetScrollPos (m_hWnd, SB_HORZ) ; GetScrollRange (m_hWnd, SB_HORZ, &iScrollLo, &iScrollRange) ; switch (iScrollCode) { case SB_LINEUP: iScrollAmt = - m_yLineHeight ; break ; case SB_LINEDOWN: iScrollAmt = m_yLineHeight ; break ; case SB_PAGEUP: iScrollAmt = - (rectClient.right - rectClient.left) / 2 ; break ; case SB_PAGEDOWN: iScrollAmt = (rectClient.right - rectClient.left) / 2 ; break ; case SB_THUMBPOSITION: iScrollAmt = iScrollNewPos - iScrollPos ; break ; default: iScrollAmt = 0 ; } iScrollAmt = PinInclusive (iScrollAmt, -iScrollPos, iScrollRange - iScrollPos) ; if (iScrollAmt) { iScrollPos += iScrollAmt ; ScrollWindow (m_hWnd, -iScrollAmt, 0, NULL, NULL) ; SetScrollPos (m_hWnd, SB_HORZ, iScrollPos, TRUE) ; UpdateWindow (m_hWnd) ; } } void CReport::OnVScroll ( INT iScrollCode, INT iScrollNewPos ) { INT iScrollAmt, iScrollPos, iScrollRange ; INT iScrollLo ; RECT rectClient ; iScrollPos = GetScrollPos (m_hWnd, SB_VERT) ; GetScrollRange (m_hWnd, SB_VERT, &iScrollLo, &iScrollRange) ; GetClientRect (m_hWnd, &rectClient) ; switch (iScrollCode) { case SB_LINEUP: iScrollAmt = - m_yLineHeight ; break ; case SB_LINEDOWN: iScrollAmt = m_yLineHeight ; break ; case SB_PAGEUP: iScrollAmt = - (rectClient.bottom - rectClient.top) / 2 ; break ; case SB_PAGEDOWN: iScrollAmt = (rectClient.bottom - rectClient.top) / 2 ; break ; case SB_THUMBPOSITION: iScrollAmt = iScrollNewPos - iScrollPos ; break ; default: iScrollAmt = 0 ; } iScrollAmt = PinInclusive (iScrollAmt, -iScrollPos, iScrollRange - iScrollPos) ; if (iScrollAmt) { iScrollPos += iScrollAmt ; ScrollWindow (m_hWnd, 0, -iScrollAmt, NULL, NULL) ; SetScrollPos (m_hWnd, SB_VERT, iScrollPos, TRUE) ; UpdateWindow (m_hWnd) ; } } // // Window procedure // LRESULT APIENTRY ReportWndProc ( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { PREPORT pReport = NULL; BOOL bCallDefProc = TRUE; LRESULT lReturnValue = 0L; RECT rect; // hWnd is used to dispatch to window procedure, so major error if it is NULL. assert ( NULL != hWnd ); pReport = (PREPORT)GetWindowLongPtr(hWnd,0); if ( NULL == pReport ) { if ( WM_CREATE == uiMsg && NULL != lParam ) { pReport = (PREPORT)((CREATESTRUCT*)lParam)->lpCreateParams; SetWindowLongPtr(hWnd,0,(INT_PTR)pReport); } else { // Programming error assert ( FALSE ); } } else { bCallDefProc = FALSE ; switch (uiMsg) { case WM_DESTROY: break ; case WM_LBUTTONDOWN: if (!pReport->m_pCtrl->IsUIDead()) { // pReport->m_pCtrl->Activate(); // pReport->m_pCtrl->AssignFocus(); pReport->OnLButtonDown(LOWORD (lParam), HIWORD (lParam)); } break; case WM_CONTEXTMENU: if (!pReport->m_pCtrl->IsUIDead()) { // pReport->m_pCtrl->Activate(); // pReport->m_pCtrl->AssignFocus(); // *** DefWindowProc is not Smonctrl, so context menu not happening. if (LOWORD(lParam)!= 0xffff || HIWORD(lParam) != 0xffff){ // Always call the default procedure, to handle the case where the // context menu is activated from within a select rectangle. bCallDefProc = TRUE; }else { if (!pReport->OnContextMenu(0,0)) bCallDefProc = TRUE; } } break; case WM_LBUTTONDBLCLK: if (!pReport->m_pCtrl->IsUIDead()) { // pReport->m_pCtrl->Activate(); // pReport->m_pCtrl->AssignFocus(); pReport->OnDblClick(LOWORD (lParam), HIWORD (lParam)); } break; case WM_ERASEBKGND: GetClientRect(hWnd, &rect); SetBkColor((HDC)wParam, pReport->m_pCtrl->clrBackPlot()); ClearRect((HDC)wParam, &rect); lReturnValue = TRUE; break; case WM_PAINT: pReport->OnPaint () ; break ; case WM_HSCROLL: pReport->OnHScroll (LOWORD (wParam), HIWORD (wParam)) ; break ; case WM_VSCROLL: pReport->OnVScroll (LOWORD (wParam), HIWORD (wParam)) ; break ; case WM_COMMAND: if (pReport->m_pCtrl->IsUIDead()) break; switch (LOWORD(wParam)) { case IDM_REPORT_COPY: case IDM_REPORT_COPYALL: break; case IDM_REPORT_DELETE: pReport->DeleteSelection(); break; case IDM_PROPERTIES: pReport->m_pCtrl->DisplayProperties(); break; case IDM_ADDCOUNTERS: pReport->m_pCtrl->AddCounters(); break; case IDM_SAVEAS: pReport->m_pCtrl->SaveAs(); break; default: bCallDefProc = TRUE; } break; default: bCallDefProc = TRUE ; } } if (bCallDefProc) lReturnValue = DefWindowProc (hWnd, uiMsg, wParam, lParam) ; return (lReturnValue); }