WindowsXP-SP1/admin/controls/smonctrl/scale.cpp
2020-09-30 16:53:49 +02:00

220 lines
5.1 KiB
C++

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
scale.cpp
Abstract:
Implements display of the scale numbers on the graph y-axis.
--*/
#include "polyline.h"
#include <stdio.h>
#define SCALE_MARGIN 10
CGraphScale::CGraphScale( void )
: m_iMaxValue(100),
m_iMinValue(0),
m_nTics(0),
m_iTextHeight(0)
{
}
CGraphScale::~CGraphScale( void )
{
}
void CGraphScale::SetRect( PRECT pRect )
{
m_Rect = *pRect;
SetTicPositions();
}
void CGraphScale::SetMaxValue( INT iMaxValue )
{
m_iMaxValue = iMaxValue;
SetTicPositions();
}
void CGraphScale::SetMinValue( INT iMinValue )
{
m_iMinValue = iMinValue;
SetTicPositions();
}
void CGraphScale::SetTicPositions( void )
{
INT iHeight;
INT nMaxTics;
INT i;
CStepper stepper;
static INT aiTicTable[] = {25,20,10,5,4,2,1,0};
iHeight = m_Rect.bottom - m_Rect.top;
if (!(iHeight > 0 && m_iTextHeight > 0)) {
m_nTics = 0;
return;
}
// Determine number of labels that will fit
nMaxTics = iHeight / (m_iTextHeight + m_iTextHeight/2);
for (i=0; nMaxTics < aiTicTable[i]; i++) {};
m_nTics = aiTicTable[i];
// Don't have more labels than values
if (m_iMaxValue - m_iMinValue < m_nTics)
m_nTics = m_iMaxValue - m_iMinValue;
// Locate equally spaced tic marks
if (m_nTics > 0)
{
m_aiTicPos[0] = 0;
stepper.Init(iHeight,m_nTics);
for (i = 1; i <= m_nTics; i++)
{
m_aiTicPos[i] = stepper.NextPosition();
}
}
}
INT CGraphScale::GetTicPositions( INT **piTics )
{
*piTics = m_aiTicPos;
return m_nTics;
}
INT CGraphScale::GetWidth (HDC hDC)
{
TCHAR szMaxValue [20] ;
SIZE Size;
INT iWidth;
// compute size of largest possible numerical label plus space
if ( 0 != FormatNumber (
(double)m_iMaxValue,
szMaxValue,
20,
eMinimumWidth,
eFloatPrecision) ) {
GetTextExtentPoint32(hDC, szMaxValue, lstrlen(szMaxValue), &Size);
// Save Text height for tic calculations
m_iTextHeight = Size.cy;
iWidth = Size.cx + SCALE_MARGIN;
} else {
iWidth = 0;
}
return iWidth;
}
void CGraphScale::Draw (HDC hDC)
{
TCHAR szScale [20] ;
INT iRetChars,
i,
iUnitsPerLine ;
INT iRange;
FLOAT ePercentOfTotal ;
FLOAT eDiff ;
BOOL bUseFloatingPt = FALSE ;
RECT rectClip;
// nTicks may be zero if the screen size if getting too small
if (m_nTics < 1 || m_iMaxValue <= m_iMinValue)
return;
iRange = m_iMaxValue - m_iMinValue;
// Calculate what percentage of the total each line represents.
ePercentOfTotal = ((FLOAT) 1.0) / ((FLOAT) m_nTics) ;
// Calculate the amount (number of units) of the Vertical max each
// each line in the graph represents.
iUnitsPerLine = (INT) ((FLOAT) iRange * ePercentOfTotal) ;
ePercentOfTotal *= (FLOAT) iRange;
eDiff = (FLOAT)iUnitsPerLine - ePercentOfTotal ;
if (eDiff < (FLOAT) 0.0)
eDiff = -eDiff ;
if ( (iUnitsPerLine < 100)
&& (eDiff > (FLOAT) 0.1) ) {
bUseFloatingPt = TRUE ;
}
SetTextAlign (hDC, TA_TOP | TA_RIGHT) ;
rectClip.left = m_Rect.left;
rectClip.right = m_Rect.right - SCALE_MARGIN;
// Now Output each string.
for (i = 0; i < m_nTics; i++) {
if (bUseFloatingPt) {
FLOAT fValue = (FLOAT)m_iMaxValue - ((FLOAT)i * ePercentOfTotal);
iRetChars = FormatNumber (
(double)fValue,
szScale,
20,
eMinimumWidth,
eFloatPrecision);
} else {
iRetChars = _stprintf (szScale, TEXT("%d"),
m_iMaxValue - (i * iUnitsPerLine)) ;
}
rectClip.top = m_aiTicPos[i] + m_Rect.top - m_iTextHeight/2;
rectClip.bottom = rectClip.top + m_iTextHeight;
ExtTextOut (
hDC,
rectClip.right,
rectClip.top,
0,
&rectClip,
szScale,
lstrlen(szScale),
NULL );
}
// Make sure the last value is the specified Minimum.
if (bUseFloatingPt) {
iRetChars = FormatNumber (
(double)m_iMinValue,
szScale,
20,
eMinimumWidth,
eFloatPrecision);
} else {
iRetChars = _stprintf (szScale, TEXT("%d"), m_iMinValue) ;
}
rectClip.top = m_aiTicPos[i] + m_Rect.top - m_iTextHeight/2;
rectClip.bottom = rectClip.top + m_iTextHeight;
ExtTextOut (
hDC,
rectClip.right,
rectClip.top,
0,
&rectClip,
szScale,
lstrlen(szScale),
NULL);
}