windows-nt/Source/XPSP1/NT/admin/controls/smonctrl/report.cpp
2020-09-26 16:20:57 +08:00

1773 lines
49 KiB
C++

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
report.cpp
Abstract:
Implements the report view.
--*/
//==========================================================================//
// Includes //
//==========================================================================//
#include <assert.h>
#include <stdio.h> // for sprintf
#include <pdhmsg.h>
#include "polyline.h"
#include "commctrl.h"
#include "winhelpr.h"
#define eScaleValueSpace _T(">9999999999.0")
#define szReportClass _T("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 TCHAR LineEndStr[] = TEXT("\n") ;
static TCHAR TabStr[] = TEXT("\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 TEXT("-999,999,999.999")
#define szValueLargeHexPlaceholder TEXT(" xBBBBBBBBDDDDDDDD")
#define dLargeValueMax ((double) 999999999.0)
#define szDashLine TEXT("---")
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 = (WNDPROC) 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;
TCHAR szParent[MAX_PATH];
TCHAR szInstance[MAX_PATH];
szParent[0] = _T('\0');
szInstance[0] = _T('\0');
xPos = 0;
for (pInstance = pObject->FirstInstance();
pInstance;
pInstance = pInstance->Next()) {
if (m_bFontChange || pInstance->m_xWidth == -1) {
if (pInstance->HasParent()) {
pInstance->GetParentName(szParent);
pInstance->GetInstanceName(szInstance);
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 )
{
TCHAR szValue [20] = TEXT("_") ;
double dMax;
double dMin;
double dValue = -1.0;
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,
20,
12,
iPrecision );
}
}
}
else {
lstrcpy(szValue, szDashLine);
}
}
else {
lstrcpy(szValue, 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);
}
}
}
}
}
}
BOOL
CReport::WriteFileReport ( HANDLE hFile )
{
PCMachineNode pMachine;
PCObjectNode pObject;
PCInstanceNode pInstance;
PCCounterNode pCounter;
TCHAR szName[MAX_PATH];
TCHAR pszTemp[2*MAX_PATH];
PCGraphItem pItem;
BOOL bStatus = TRUE;
TCHAR szValue[20];
for (pMachine = m_pCtrl->CounterTree()->FirstMachine() ;
pMachine && TRUE == bStatus;
pMachine = pMachine->Next()) {
lstrcpy(pszTemp,LineEndStr);
lstrcat(pszTemp,LineEndStr);
lstrcat(pszTemp,ResourceString(IDS_COMPUTER));
lstrcat(pszTemp,pMachine->Name());
lstrcat(pszTemp,LineEndStr);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
for (pObject = pMachine->FirstObject() ;
pObject && TRUE == bStatus;
pObject = pObject->Next()) {
// Write the object name line.
lstrcpy(pszTemp,LineEndStr);
lstrcat(pszTemp,ResourceString(IDS_OBJECT_NAME));
lstrcat(pszTemp,pObject->Name());
lstrcat(pszTemp,LineEndStr);
// Add first tab char for instance names.
lstrcat(pszTemp,TabStr);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
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.
pInstance->GetParentName(szName);
lstrcpy(pszTemp,TabStr);
lstrcat(pszTemp,szName);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
}
if ( !bStatus )
break;
lstrcpy(pszTemp,LineEndStr);
// Include first tab of second instance line.
lstrcat(pszTemp,TabStr);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
// Write the second line of instance names.
for (pInstance = pObject->FirstInstance();
pInstance && TRUE == bStatus;
pInstance = pInstance->Next()) {
pInstance->GetInstanceName(szName);
lstrcpy(pszTemp,TabStr);
lstrcat(pszTemp,szName);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
}
if (!bStatus)
break;
lstrcpy(pszTemp,LineEndStr);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
for (pCounter = pObject->FirstCounter();
pCounter && TRUE == bStatus;
pCounter = pCounter->Next()) {
// Write counter name
lstrcpy(pszTemp,TabStr);
lstrcat(pszTemp,pCounter->Name());
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
// 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 );
lstrcpy(pszTemp,TabStr);
lstrcat (pszTemp,szValue);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
}
}
}
if (!bStatus)
break;
lstrcpy(pszTemp,LineEndStr);
bStatus = FileWrite ( hFile, pszTemp, lstrlen (pszTemp) * sizeof(TCHAR) );
}
}
}
return bStatus;
}
void
CReport::GetReportItemValue(PCGraphItem pItem, LPTSTR 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,
20,
12,
iPrecision );
}
}
} else {
lstrcpy(szValue, szDashLine);
}
} else {
lstrcpy(szValue, szDashLine);
}
return;
}
void
CReport::DrawReportHeaders (
HDC hDC )
{
PCMachineNode pMachine;
PCObjectNode pObject;
PCInstanceNode pInstance;
PCCounterNode pCounter;
TCHAR szName[MAX_PATH];
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 = pInstance->GetParentName(szName);
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,
szName,
cName,
NULL);
rectInstance.top = pObject->m_yPos;
rectInstance.bottom = rectInstance.top + m_yLineHeight;
cName = pInstance->GetInstanceName(szName);
ExtTextOut (
hDC,
m_xInstanceMargin + pInstance->m_xPos,
pObject->m_yPos,
ETO_OPAQUE,
&rectInstance,
szName,
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 ;
if ( m_pCtrl->DisplayMissedSampleMessage() ) {
MessageBox(m_hWnd, ResourceString(IDS_SAMPLE_DATA_MISSING), ResourceString(IDS_APP_NAME),
MB_OK | MB_ICONINFORMATION);
}
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);
}