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.
1845 lines
53 KiB
1845 lines
53 KiB
/*++
|
|
|
|
Copyright (C) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
report.cpp
|
|
|
|
Abstract:
|
|
|
|
Implements the report view.
|
|
|
|
--*/
|
|
|
|
//==========================================================================//
|
|
// Includes //
|
|
//==========================================================================//
|
|
|
|
#include "polyline.h"
|
|
#include <strsafe.h>
|
|
#include <commctrl.h>
|
|
#include <pdhmsg.h>
|
|
#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);
|
|
}
|