www.pudn.com > PressMonitor_q.zip > 3DMeterCtrl.cpp


// 3DMeterCtrl.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "math.h" 
#include "3DMeterCtrl.h" 
#include "MemDC.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// C3DMeterCtrl 
 
C3DMeterCtrl::C3DMeterCtrl() 
{ 
	m_dCurrentValue  =  0.0 ; 
	m_dMaxValue      =  35.0 ; 
	m_dMinValue      =  0.0 ; 
 
	m_nScaleHeight = 12; 
	m_nUnitHeight = 24; 
	m_nValueHeight = 14; 
 
	m_nScaleDecimals = 0 ; 
	m_nValueDecimals = 1 ; 
	m_nFrameWidth=2; 
 
	m_strUnits.Format("MPa") ; 
 
	m_crRuler       = GetSysColor(COLOR_WINDOW) ; 
	m_crNeedle		= RGB(255, 0, 0) ; 
	m_crSectorStart  = RGB(0 ,0,255) ; 
	m_crSectorMiddle = RGB(0,  255,0) ; 
	m_crSectorEnd    = RGB(255, 0, 0) ; 
	m_crSectorFrame  = RGB(0   ,64,128) ; 
	m_crFrame		= GetSysColor(COLOR_BTNFACE); 
	m_crUnits		= RGB(0,0,0); 
	m_crValueBack	= GetSysColor(COLOR_BTNTEXT); 
	m_crValue		= RGB(255,255,0);//GetSysColor(COLOR_WINDOWTEXT); 
	m_crScale		= GetSysColor(COLOR_WINDOW); 
	m_crMeterFace	= RGB(64,128,128);//RGB(129,170,240); 
	m_crMeterBack	= RGB(64,128,128) ; 
 
	// get the relevant system crs 
	m_crWindow    = GetSysColor(COLOR_WINDOW) ; 
	m_crButton    = GetSysColor(COLOR_BTNFACE) ; 
	m_crShadow    = GetSysColor(COLOR_3DSHADOW) ; 
	m_crDkShadow  = GetSysColor(COLOR_3DDKSHADOW); 
	m_crLight     = GetSysColor(COLOR_3DLIGHT); 
	m_crHighlight = GetSysColor(COLOR_3DHIGHLIGHT) ; 
	m_crText	  = GetSysColor(COLOR_BTNTEXT) ; 
} 
 
C3DMeterCtrl::~C3DMeterCtrl() 
{ 
	if ((m_pBitmapOldBackground) &&  
		  (m_bitmapBackground.GetSafeHandle()) &&  
			(m_dcBackground.GetSafeHdc())) 
	{ 
		m_dcBackground.SelectObject(m_pBitmapOldBackground); 
		m_dcBackground.DeleteDC() ; 
		m_bitmapBackground.DeleteObject(); 
	} 
 
 } 
 
 
BEGIN_MESSAGE_MAP(C3DMeterCtrl, CStatic) 
	//{{AFX_MSG_MAP(C3DMeterCtrl) 
	ON_WM_PAINT() 
	ON_WM_SIZE() 
	ON_WM_ERASEBKGND() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// C3DMeterCtrl message handlers 
class CRotPoint : public CPoint 
{ 
public: 
	CRotPoint() : CPoint() {}; 
	CRotPoint(int xPos, int yPos) : CPoint(xPos, yPos) {}; 
 
	void Rotate(double Radians); 
	double Angle(); 
}; 
 
 
#define M_PI 3.1415926535897932384626433832795 
#define ABS(a) ( ((a)>0)?(a):(-(a)) ) 
 
double CRotPoint::Angle() 
{ 
	if (x == 0) 
		return y >= 0 ? M_PI/2 : -M_PI/2; 
 
	double AngleRad = atan2((double)y, (double)x); 
 
	if (AngleRad < 0) 
		AngleRad += M_PI*2; 
 
	return AngleRad; 
} 
 
void CRotPoint::Rotate(double Radians) 
{ 
	double StartAngle, EndAngle, Length; 
 
	StartAngle = Angle(); 
	EndAngle = StartAngle + Radians; 
 
	Length = sqrt((double)x*(double)x + (double)y*(double)y); 
 
	x = (long)(Length * cos(EndAngle) + 0.5); 
	y = (long)(Length * sin(EndAngle) + 0.5); 
} 
 
BOOL C3DMeterCtrl::OnEraseBkgnd(CDC* pDC)  
{ 
	// TODO: Add your message handler code here and/or call default 
	 
	return TRUE; 
} 
 
 
void C3DMeterCtrl::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
		 
	// Find out how big we are 
	GetClientRect (&m_rectCtrl) ; 
/* 
	CDC memDC; 
	CBitmap Bitmap; 
	memDC.CreateCompatibleDC(&dc) ; 
	Bitmap.CreateCompatibleBitmap(&dc, m_rectCtrl.Width(), m_rectCtrl.Height()) ; 
	CBitmap *pOldBitmap=memDC.SelectObject(&Bitmap) ; 
*/ 
	// make a memory dc 
	CMemDC memDC(&dc, &m_rectCtrl); 
 
	// set up a memory dc for the background stuff  
	// if one isn't being used 
	if ((m_dcBackground.GetSafeHdc() == NULL) || (m_bitmapBackground.m_hObject == NULL)) 
	{ 
		m_dcBackground.CreateCompatibleDC(&dc) ; 
		m_bitmapBackground.CreateCompatibleBitmap(&dc, m_rectCtrl.Width(), m_rectCtrl.Height()) ; 
		m_pBitmapOldBackground = m_dcBackground.SelectObject(&m_bitmapBackground) ; 
 
		// Fill this bitmap with the background. 
 
		// Note: This requires some serious drawing and calculating,  
		// therefore it is drawn "once" to a bitmap and  
		// the bitmap is stored and blt'd when needed. 
		DrawFrame(&m_dcBackground); 
		DrawRuler(&m_dcBackground); 
		DrawColorCirque(&m_dcBackground); 
		DrawScale(&m_dcBackground); 
		DrawUnit(&m_dcBackground); 
	} 
 
	// drop in the background 
	memDC.BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(),  
			           &m_dcBackground, 0, 0, SRCCOPY) ; 
 
/* 
		DrawFrame(&memDC); 
		DrawRuler(&memDC); 
		DrawColorCirque(&memDC); 
		DrawScale(&memDC); 
		DrawUnit(&memDC); 
*/ 
	// add the value to the background 
	DrawValue(&memDC) ; 
 
	// add the needle to the background 
	DrawNeedle(&memDC) ; 
/* 
	dc.BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(),  
			           &memDC, 0, 0, SRCCOPY) ; 
 
	memDC.SelectObject(pOldBitmap) ; 
*/ 
} 
 
void C3DMeterCtrl::DrawValue(CDC *pDC) 
{ 
	CString strTemp ; 
 
	CFont fontUse,*pFontOld ; 
	fontUse.CreateFont (m_nValueHeight, 0, 0, 0, 300, 
												  FALSE, FALSE, 0, ANSI_CHARSET, 
												  OUT_DEFAULT_PRECIS,  
												  CLIP_DEFAULT_PRECIS, 
												  DEFAULT_QUALITY,  
												  DEFAULT_PITCH|FF_SWISS, "Times New Roman") ; 
 
	pFontOld = pDC->SelectObject(&fontUse) ; 
	int nMode=pDC->SetBkMode(TRANSPARENT); 
	// set the crs based on the system crs 
	pDC->SetTextColor(m_crValue) ; 
 
	// draw the text in the recessed rectangle 
	strTemp.Format("%.*f", m_nValueDecimals, m_dCurrentValue) ; 
	pDC->DrawText(strTemp,m_rectValue,DT_CENTER|DT_VCENTER|DT_SINGLELINE) ; 
 
	// restore the color and the font 
	pDC->SelectObject(pFontOld) ; 
	pDC->SetBkMode(nMode); 
 
} 
 
void C3DMeterCtrl::UpdateNeedle(double dValue) 
{ 
	m_dCurrentValue = dValue ; 
	Invalidate() ; 
 
} 
 
void C3DMeterCtrl::DrawNeedle(CDC *pDC) 
{ 
	// create a pen and brush based on the needle color 
	CPen penAxes,*pPenOld; 
	penAxes.CreatePen(PS_SOLID,1,m_crText); 
 
	CBrush brushShadow,brushNeedle; 
	brushShadow.CreateSolidBrush(RGB(255,0,0)) ; 
	brushNeedle.CreateSolidBrush(m_crNeedle) ; 
 
	double dAngleRad ; 
	CRect rectAxes(m_nMeterCX-3,m_nMeterCY-3,m_nMeterCX+3,m_nMeterCY+3); 
	static CRotPoint North[] = 
	{ 
		CRotPoint(-8,1), 
		CRotPoint(-7,3), 
		CRotPoint(-5,5), 
		CRotPoint(-4,7), 
		CRotPoint(-2,7), 
		CRotPoint(-1,8), 
		CRotPoint(1,8), 
		CRotPoint(2,7), 
		CRotPoint(4,7), 
		CRotPoint(5,5), 
		CRotPoint(7,3), 
		CRotPoint(8,1), 
		CRotPoint(0,-m_nBottomRadius), 
	}; 
 
 
#define NORTH_LEN (sizeof(North)/sizeof(North[0])) 
	CRotPoint pointNeedle[NORTH_LEN]; 
 
	// calculate the angle for the tip of the needle 
	dAngleRad = (m_dCurrentValue-m_dMinValue)*(m_dEndAngleRad-m_dStartAngleRad)/ 
		          (m_dMaxValue-m_dMinValue) ; 
 
	// if the angle is beyond the meter, draw the needle 
	// at the limit (as if it is "pegged") 
	if(m_dCurrentValuem_dMaxValue) 
		dAngleRad=m_dEndAngleRad-m_dStartAngleRad; 
 
 
#define SHADOW_OFFSET	1 
 
	int i; 
	// 
	//	Draw the shadow 
	// 
	for (i = 0; i < NORTH_LEN; i++) 
	{ 
		pointNeedle[i] = North[i]; 
		pointNeedle[i].Rotate(m_dEndAngleRad+dAngleRad); 
		pointNeedle[i].Offset(m_nMeterCX+SHADOW_OFFSET, m_nMeterCY+SHADOW_OFFSET); 
	} 
 
	{ 
		CRgn NeedleRgn; 
		NeedleRgn.CreatePolygonRgn(pointNeedle, NORTH_LEN, ALTERNATE); 
		pDC->FillRgn(&NeedleRgn, &brushShadow); 
	} 
 
	// draw the needle 
	for (i = 0; i < NORTH_LEN; i++) 
	{ 
		pointNeedle[i] = North[i]; 
		pointNeedle[i].Rotate(m_dEndAngleRad+dAngleRad); 
		pointNeedle[i].Offset(m_nMeterCX-1, m_nMeterCY-1); 
	} 
 
	{ 
		CRgn NeedleRgn; 
		NeedleRgn.CreatePolygonRgn(pointNeedle, NORTH_LEN, ALTERNATE); 
		pDC->FillRgn(&NeedleRgn, &brushNeedle); 
	} 
 
	pPenOld=pDC->SelectObject(&penAxes); 
 
	pDC->Ellipse(rectAxes); 
 
	pDC->SelectObject(pPenOld); 
 
} 
 
void C3DMeterCtrl::OnSize(UINT nType, int cx, int cy)  
{ 
	CStatic::OnSize(nType, cx, cy); 
	 
	ReconstructControl() ; 
 
} 
 
void C3DMeterCtrl::ReconstructControl()  
{ 
	// if we've got a stored background - remove it! 
	if ((m_pBitmapOldBackground) &&  
		  (m_bitmapBackground.GetSafeHandle()) &&  
			(m_dcBackground.GetSafeHdc())) 
	{ 
			m_dcBackground.SelectObject(m_pBitmapOldBackground); 
			m_dcBackground.DeleteDC() ; 
			m_bitmapBackground.DeleteObject(); 
			m_bitmapBackground.Detach(); 
	} 
 
	Invalidate () ; 
 
} 
 
void C3DMeterCtrl::SetRange(double dMin, double dMax)  
{ 
	m_dMaxValue = dMax ; 
	m_dMinValue = dMin ; 
	ReconstructControl() ; 
} 
 
void C3DMeterCtrl::SetScaleDecimals(int nDecimals)  
{ 
	m_nScaleDecimals = nDecimals ; 
	ReconstructControl() ; 
} 
 
void C3DMeterCtrl::SetValueDecimals(int nDecimals)  
{ 
	m_nValueDecimals = nDecimals ; 
	ReconstructControl() ; 
} 
 
void C3DMeterCtrl::SetUnits(CString &strUnits)  
{ 
	m_strUnits = strUnits ; 
	ReconstructControl() ; 
} 
 
void C3DMeterCtrl::SetNeedleColor (COLORREF crNeedle) 
{ 
	m_crNeedle = crNeedle ; 
	ReconstructControl() ; 
} 
 
 
 
 
void C3DMeterCtrl::DrawFrame(CDC *pDC) 
{ 
	CPen penFrame,penHighlight,penDkShadow,*pPenOld; 
	penFrame.CreatePen(PS_SOLID, m_nFrameWidth*2,m_crFrame) ; 
	penHighlight.CreatePen(PS_SOLID, 1, m_crHighlight) ; 
	penDkShadow.CreatePen(PS_SOLID, 1, m_crDkShadow) ; 
 
    CBrush brushBack,*pBrushOld; 
	brushBack.CreateSolidBrush(m_crMeterBack) ; 
 
// »­Íâ±ß¿ò 
	pPenOld = pDC->SelectObject(&penFrame) ; 
	pBrushOld = pDC->SelectObject(&brushBack) ; 
 
	pDC->Rectangle(m_rectCtrl) ; 
/* 
	// draw the left and top sides with the highlight 
	pDC->SelectObject(&penHighlight) ; 
	pDC->MoveTo(m_rectCtrl.left, m_rectCtrl.bottom) ; 
	pDC->LineTo(m_rectCtrl.left, m_rectCtrl.top) ; 
	pDC->LineTo(m_rectCtrl.right-1, m_rectCtrl.top) ; 
 
	// draw the right and bottom sides with the shadow 
	pDC->SelectObject(&penDkShadow) ; 
	pDC->LineTo(m_rectCtrl.right-1, m_rectCtrl.bottom-1) ; 
	pDC->LineTo(m_rectCtrl.left, m_rectCtrl.bottom-1) ; 
 
*/ 
	// draw the left and top sides with the shadow 
	pDC->SelectObject(&penDkShadow) ; 
	pDC->MoveTo(m_rectPane.left, m_rectPane.bottom) ; 
	pDC->LineTo(m_rectPane.left, m_rectPane.top) ; 
	pDC->LineTo(m_rectPane.right-1, m_rectPane.top) ; 
 
	// draw the right and bottom sides with the highlight 
	pDC->SelectObject(&penHighlight) ; 
	pDC->LineTo(m_rectPane.right-1, m_rectPane.bottom-1) ; 
	pDC->LineTo(m_rectPane.left, m_rectPane.bottom-1) ; 
 
	pDC->SelectObject(pPenOld); 
	pDC->SelectObject(pBrushOld); 
} 
 
void C3DMeterCtrl::DrawRuler(CDC *pDC) 
{ 
	CPen penRuler1,penRuler2,penRuler3,*pPenOld; 
	penRuler1.CreatePen(PS_SOLID, 4, m_crRuler) ; 
	penRuler2.CreatePen(PS_SOLID, 2, m_crRuler) ; 
	penRuler3.CreatePen(PS_SOLID, 1, m_crRuler) ; 
 
	CRect rectTemp; 
	double dX,dY,dX1,dY1; 
	int nAngleDeg; 
	double dAngleRad; 
	double 	dRadPerDeg = 4.0*atan(1.0)/180.0 ; 
	int nRadius=m_nBottomRadius-10; 
////////////////////////////////////////////»­ÄÚȦ 
	pPenOld=pDC->SelectObject(&penRuler1) ; 
 
	rectTemp.left=m_nMeterCX-nRadius; 
	rectTemp.right=m_nMeterCX+nRadius; 
	rectTemp.top=m_nMeterCY-nRadius; 
	rectTemp.bottom=m_nMeterCY+nRadius; 
 
	dX=m_nMeterCX+nRadius*cos(m_dStartAngleRad); 
	dY=m_nMeterCY-nRadius*sin(m_dStartAngleRad); 
	dX1=m_nMeterCX+nRadius*cos(m_dEndAngleRad); 
	dY1=m_nMeterCY-nRadius*sin(m_dEndAngleRad); 
 
	pDC->MoveTo(CPoint(ROUND(dX),ROUND(dY))); 
	pDC->Arc(rectTemp,CPoint(ROUND(dX),ROUND(dY)),CPoint(ROUND(dX1),ROUND(dY1) )); 
 
//draw ruler 
	pDC->SelectObject(&penRuler2) ; 
 
	for (nAngleDeg=m_nStartAngleDeg; nAngleDeg<=m_nEndAngleDeg; nAngleDeg+=m_nTickAngleDeg) 
	{ 
 
		// move to the top of the tick mark 
		dX = m_nMeterCX + nRadius*cos(nAngleDeg*dRadPerDeg) ; 
		dY = m_nMeterCY - nRadius*sin(nAngleDeg*dRadPerDeg) ; 
		pDC->MoveTo(ROUND(dX), ROUND(dY)) ; 
 
		// move to the bottom of the tick mark 
		dX = m_nMeterCX + (nRadius+10)*cos(nAngleDeg*dRadPerDeg) ; 
		dY = m_nMeterCY - (nRadius+10)*sin(nAngleDeg*dRadPerDeg) ; 
		pDC->LineTo(ROUND(dX), ROUND(dY)) ; 
	} 
 
	pDC->SelectObject(&penRuler3) ; 
 
	for (dAngleRad=m_dStartAngleRad; dAngleRad<=m_dEndAngleRad; dAngleRad+=m_dTickAngleRad/10) 
	{ 
 
		// move to the top of the tick mark 
		dX = m_nMeterCX + (nRadius+4)*cos(dAngleRad) ; 
		dY = m_nMeterCY - (nRadius+4)*sin(dAngleRad) ; 
		pDC->MoveTo(ROUND(dX), ROUND(dY)) ; 
 
		// move to the bottom of the tick mark 
		dX = m_nMeterCX + (nRadius+8)*cos(dAngleRad) ; 
		dY = m_nMeterCY - (nRadius+8)*sin(dAngleRad) ; 
		pDC->LineTo(ROUND(dX), ROUND(dY)) ; 
	} 
 
	pDC->SelectObject(pPenOld); 
 
} 
 
void C3DMeterCtrl::DrawScale(CDC *pDC) 
{ 
	int nAngleDeg,i; 
	double 	dRadPerDeg = 4.0*atan(1.0)/180.0 ; 
	double dTemp; 
	double dX,dY; 
	CString strTemp; 
	int nRadius=m_nBottomRadius-30; 
 
//draw scale 
	CFont fontUse,*pFontOld; 
	fontUse.CreateFont (m_nScaleHeight, 0, 0, 0, 600, 
												  FALSE, FALSE, 0, ANSI_CHARSET, 
												  OUT_DEFAULT_PRECIS,  
												  CLIP_DEFAULT_PRECIS, 
												  DEFAULT_QUALITY,  
												  DEFAULT_PITCH|FF_SWISS, "Times New Roman") ; 
 
	pFontOld=pDC->SelectObject(&fontUse) ; 
	int nMode=pDC->SetBkMode(TRANSPARENT); 
	pDC->SetTextColor(m_crScale) ; 
 
	for (nAngleDeg=m_nStartAngleDeg; nAngleDeg<=m_nEndAngleDeg; nAngleDeg+=2*m_nTickAngleDeg) 
	{ 
		dTemp=m_dMaxValue-(nAngleDeg-m_nStartAngleDeg)*(m_dMaxValue-m_dMinValue)/(m_nEndAngleDeg-m_nStartAngleDeg); 
		strTemp.Format("%.*f",m_nScaleDecimals,dTemp); 
		i=(nAngleDeg-m_nStartAngleDeg)/(2*m_nTickAngleDeg); 
 
		switch(i) 
		{ 
		case 0: 
			dX = m_nMeterCX + (nRadius)*cos(nAngleDeg*dRadPerDeg) ; 
			dY = m_nMeterCY - (nRadius)*sin(nAngleDeg*dRadPerDeg) ; 
			break; 
 
		case 1: 
			dX = m_nMeterCX + (nRadius)*cos(nAngleDeg*dRadPerDeg) ; 
			dY = m_nMeterCY - (nRadius)*sin(nAngleDeg*dRadPerDeg)-m_nScaleHeight/2 ; 
			break; 
 
		case 2: 
			dX = m_nMeterCX + (nRadius)*cos(nAngleDeg*dRadPerDeg) ; 
			dY = m_nMeterCY - (nRadius)*sin(nAngleDeg*dRadPerDeg)-m_nScaleHeight ; 
			break; 
 
		case 3: 
			dX = m_nMeterCX + (nRadius)*cos(nAngleDeg*dRadPerDeg)-m_nScaleHeight ; 
			dY = m_nMeterCY - (nRadius)*sin(nAngleDeg*dRadPerDeg)-m_nScaleHeight ; 
			break; 
 
		case 4: 
			dX = m_nMeterCX + (nRadius)*cos(nAngleDeg*dRadPerDeg)-m_nScaleHeight ; 
			dY = m_nMeterCY - (nRadius)*sin(nAngleDeg*dRadPerDeg)-m_nScaleHeight/2; 
			break; 
 
		case 5: 
			dX = m_nMeterCX + (nRadius)*cos(nAngleDeg*dRadPerDeg)-m_nScaleHeight ; 
			dY = m_nMeterCY - (nRadius)*sin(nAngleDeg*dRadPerDeg) ; 
			break; 
 
		} 
		pDC->TextOut(ROUND(dX),ROUND(dY),strTemp) ; 
 
	} 
	pDC->SelectObject(pFontOld) ; 
	pDC->SetBkMode(nMode); 
} 
 
void C3DMeterCtrl::DrawUnit(CDC *pDC) 
{ 
//draw unit////////////////////////////////////// 
	// determine the font size 
	CFont fontUse,*pFontOld; 
	fontUse.CreateFont (m_nUnitHeight, 0, 0, 0, 400, 
												  FALSE, FALSE, 0, ANSI_CHARSET, 
												  OUT_DEFAULT_PRECIS,  
												  CLIP_DEFAULT_PRECIS, 
												  DEFAULT_QUALITY,  
												  DEFAULT_PITCH|FF_SWISS, "Monotype Corsiva") ; 
 
	pFontOld=pDC->SelectObject(&fontUse) ; 
  
	int nMode=pDC->SetBkMode(TRANSPARENT); 
	// set the colors (based on system colors) 
	pDC->SetTextColor(m_crUnits) ; 
 
	// draw the units below the meter face 
	pDC->SetTextAlign(TA_CENTER|TA_BASELINE) ; 
	pDC->TextOut(m_nMeterCX, m_nMeterCY - m_nBottomRadius/4,m_strUnits) ; 
 
	pDC->SelectObject(pFontOld); 
	pDC->SetBkMode(nMode); 
} 
 
BOOL C3DMeterCtrl::ReCalculating() 
{ 
 
	double dRadPerDeg ; 
 
 
    GetClientRect(&m_rectCtrl); 
	// determine the centerpoint of the radii for 
	// the meter face. 
	m_nMeterCX = m_rectCtrl.left+m_rectCtrl.Width()/2 ; 
	m_nMeterCY = m_rectCtrl.top+m_rectCtrl.Height()*35/64 ; 
 
	// determine the radii for the top of the meter 
	// and the bottom of the meter 
	m_nTopRadius = m_rectCtrl.Width()*17/36 ; 
	m_nBottomRadius = m_nTopRadius*14/15 ; 
 
	// Radians per Degree 
	// This helps me lay things out in degrees 
	// which are more intuitive than radians. 
	dRadPerDeg = 4.0*atan(1.0)/180.0 ; 
 
	// set the left and right limits for the meter face 
	m_nStartAngleDeg =  -45 ; 
	m_nEndAngleDeg   = 225 ; 
	m_nTickAngleDeg       =  27 ; 
 
	// this is the density of points along the arcs 
 
	// convert these to radians  
	// for computer (rather than human) use! 
 
	m_dStartAngleRad = m_nStartAngleDeg*dRadPerDeg ; 
	m_dEndAngleRad = m_nEndAngleDeg*dRadPerDeg ; 
	m_dTickAngleRad = m_nTickAngleDeg*dRadPerDeg ; 
 
	m_rectPane=m_rectCtrl; 
	m_rectPane.DeflateRect(m_nFrameWidth,m_nFrameWidth,m_nFrameWidth,m_nFrameWidth); 
 
	m_rectValue.left = m_nMeterCX - m_rectCtrl.Width()*10/64 ; 
	m_rectValue.right = m_nMeterCX + m_rectCtrl.Width()*10/64 ; 
	m_rectValue.top = m_nMeterCY + m_rectCtrl.Height()*1/8 ; 
	m_rectValue.bottom = m_nMeterCY + m_rectCtrl.Height()*2/8; 
 
	m_nScaleHeight=(int)(m_nBottomRadius*0.24) ; 
	m_nUnitHeight=(int)(m_nBottomRadius*0.35) ; 
	m_nValueHeight=(int)(m_rectValue.Height()) ; 
 
 
 
	return TRUE; 
} 
 
BOOL C3DMeterCtrl::Initialize() 
{ 
	CString strTemp; 
	SetRange(0,35); 
	strTemp.Format("MPa"); 
	SetUnits(strTemp); 
    return ReCalculating(); 
} 
 
 
 
void C3DMeterCtrl::DrawColorCirque(CDC *pDC) 
{ 
	int nRad; 
	nRad=(m_nTopRadius+m_nBottomRadius)/2; 
	PaintGradiantCirque(pDC,m_nTopRadius,nRad,m_crSectorStart,RGB(255,255,255),false); 
	PaintGradiantCirque(pDC,nRad,m_nBottomRadius,m_crSectorStart,RGB(255,255,255),true); 
 
} 
 
void C3DMeterCtrl::PaintGradiantCirque(CDC *pDC, int nRadTop, int nRadBottom, COLORREF clrFrom, COLORREF clrTo,BOOL ascend ) 
{ 
	int x,y,x1,y1; 
	CRect rectTemp; 
	int nRadius; 
 
	int radCap = nRadTop - nRadBottom; 
 
	// Get the intensity values for the ending color 
	int r1 = GetRValue(clrTo); // red 
	int g1 = GetGValue(clrTo); // green 
	int b1 = GetBValue(clrTo); // blue 
	 
	// Get the intensity values for the begining color 
	int r2 = GetRValue(clrFrom); // red 
	int g2 = GetGValue(clrFrom); // green 
	int b2 = GetBValue(clrFrom); // blue 
 
	int r, g, b; 
 
	int rad = radCap; 
	int w = radCap;			// radius of area to shade 
	int radDelta= 1;	// radius of one shade band 
 
	while (rad >= 0)  
	{ 
		if (r1 > r2) 
			r = r1 - (r1-r2)*(w-rad)/w; 
		else 
			r = r1 + (r2-r1)*(w-rad)/w; 
 
		if (g1 > g2) 
			g = g1 - (g1-g2)*(w-rad)/w; 
		else 
			g = g1 + (g2-g1)*(w-rad)/w; 
 
		if (b1 > b2) 
			b = b1 - (b1-b2)*(w-rad)/w; 
		else 
			b = b1 + (b2-b1)*(w-rad)/w; 
 
        if(ascend) // Paint from  left to right; 
			nRadius=nRadBottom+rad; 
        else               // Paint from  right to left; 
			nRadius=nRadTop-rad; 
 
		rectTemp.left=m_nMeterCX-nRadius; 
		rectTemp.right=m_nMeterCX+nRadius; 
		rectTemp.top=m_nMeterCY-nRadius; 
		rectTemp.bottom=m_nMeterCY+nRadius; 
 
		x=m_nMeterCX+(int)(nRadius*cos(m_dStartAngleRad)); 
		y=m_nMeterCY-(int)(nRadius*sin(m_dStartAngleRad)); 
		x1=m_nMeterCX+(int)(nRadius*cos(m_dEndAngleRad)); 
		y1=m_nMeterCY-(int)(nRadius*sin(m_dEndAngleRad)); 
			 
		DrawArc(pDC,rectTemp,CPoint(x,y),CPoint(x1,y1),RGB(r,g,b)); 
 
		rad -= radDelta; 
	} 
	 
} 
 
void C3DMeterCtrl::DrawArc(CDC *pDC, CRect& rect, CPoint ptStart, CPoint ptEnd,COLORREF clr) 
{ 
	CPen penArc,*pPenOld; 
	penArc.CreatePen(PS_SOLID,1,clr); 
	pPenOld=pDC->SelectObject(&penArc); 
 
	pDC->MoveTo(ptStart.x,ptStart.y); 
	pDC->Arc(rect,ptStart,ptEnd); 
 
	pDC->SelectObject(pPenOld); 
}