www.pudn.com > testthermometer.rar > ThermoMeter.cpp


#include "stdafx.h" 
#include "ThermoMeter.h" 
#include "MemDC.h" 
 
CScaleUnit::CScaleUnit() 
{ 
	m_BackColor = RGB( 33, 177, 138); 
} 
 
CScaleUnit::~CScaleUnit() 
{ 
 
} 
 
void CScaleUnit::Draw(CDC *pDC) 
{ 
	CPoint ptRgn[3]; 
	ptRgn[0].x = m_rectClient.left; 
	ptRgn[0].y = m_rectClient.top; 
	ptRgn[1].x = m_rectClient.left; 
	ptRgn[1].y = m_rectClient.bottom; 
	ptRgn[2].x = m_rectClient.right; 
	ptRgn[2].y = m_rectClient.top + (m_rectClient.bottom - m_rectClient.top) / 2; 
	 
	CBrush pBackBrush, *pOldBrush; 
	pBackBrush.CreateSolidBrush(m_BackColor); 
	pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); 
	pDC->SetPolyFillMode(WINDING); 
	pDC->Polygon(ptRgn, 3); 
	pDC->SelectObject(pOldBrush); 
	pBackBrush.DeleteObject(); 
} 
 
//--------------------------------------------------------- 
CThermoMeter::CThermoMeter() 
{ 
	m_BackColor = RGB( 192, 192, 192); 
	m_dMinValue = 0;  
	m_dMaxValue = 100;   
	m_dCurrentValue = 0.00f; 
	m_nTicks = 5;						//大格个数 
	m_nSubTicks = 5;					//大格中小格个数 
 
	memset(m_strUnits, 0, sizeof(m_strUnits)); 
	strcpy(m_strUnits, "温度");			//表单位 
} 
 
CThermoMeter::~CThermoMeter() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CThermoMeter, CStatic) 
	//{{AFX_MSG_MAP(CThermoMeter) 
	ON_WM_PAINT() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
 
void CThermoMeter::PreSubclassWindow()  
{ 
	CStatic::PreSubclassWindow(); 
} 
 
void CThermoMeter::OnPaint()  
{ 
	CPaintDC dc(this);  
 
	// 获得控件区域 
	GetClientRect (&m_rectCtrl); 
 
	CMemDC memDC(&dc, &m_rectCtrl); 
 
	//绘制仪表盘 
	if (m_dcMeterPlate.GetSafeHdc() == NULL || (m_bitmapMeterPlate.m_hObject == NULL)) 
	{ 
		m_dcMeterPlate.CreateCompatibleDC(&dc); 
		m_bitmapMeterPlate.CreateCompatibleBitmap(&dc, m_rectCtrl.Width(), 																					m_rectCtrl.Height()) ; 
		m_pbitmapOldMeterPlate = m_dcMeterPlate.SelectObject(&m_bitmapMeterPlate) ; 
		DrawMeterBackground(&m_dcMeterPlate, m_rectCtrl); 
 
	} 
	memDC.BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(),  
			           &m_dcMeterPlate, 0, 0, SRCCOPY); 
 
	DrawScale(&memDC); 
	m_ctrlUnit.Draw(&memDC); 
} 
 
//绘制仪表背景 
void CThermoMeter::DrawMeterBackground(CDC *pDC, CRect &rect) 
{ 
	CString strScale; 
	CFont fScaleFont, *pOldFont; 
	CPen penThick, penThin, penShadow, penScale, *pOldPen;  
	CBrush m_brushBack, pBackBrush, *pOldBrush; 
	pDC->SetBkColor(m_BackColor); 
	m_brushBack.CreateSolidBrush(m_BackColor); 
	pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);	 
	pDC->FillRect(rect, &m_brushBack);   //绘制背景 
	pDC->SelectObject(pOldBrush); 
	m_brushBack.DeleteObject(); 
 
	//绘制边框的立体效果	 
	penThick.CreatePen(PS_SOLID, 1, RGB(172, 168, 153)); 
	penThin.CreatePen(PS_SOLID, 1, RGB(113, 111, 110)); 
	penShadow.CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); 
	pOldPen = (CPen *)pDC->SelectObject(&penShadow); 
	pDC->MoveTo(rect.left, rect.top); 
	pDC->LineTo(rect.right - 1, rect.top); 
	pDC->MoveTo(rect.left + 1, rect.top + 1); 
	pDC->LineTo(rect.right - 2, rect.top + 1); 
	pDC->MoveTo(rect.left, rect.top); 
	pDC->LineTo(rect.left, rect.bottom - 1); 
	pDC->MoveTo(rect.left + 1, rect.top + 1); 
	pDC->LineTo(rect.left + 1, rect.bottom - 2); 
	pDC->SelectObject(&penThick); 
	pDC->MoveTo(rect.left + 1, rect.bottom - 1); 
	pDC->LineTo(rect.right - 1, rect.bottom - 1); 
	pDC->LineTo(rect.right - 1, rect.top + 1); 
	pDC->SelectObject(&penThin); 
	pDC->MoveTo(rect.left, rect.bottom); 
	pDC->LineTo(rect.right, rect.bottom); 
	pDC->LineTo(rect.right, rect.top); 
	pDC->SelectObject(pOldPen);	 
 
	//绘制指针显示区域 
	CRect rectScale; 
	rectScale.SetRect(rect.left + rect.Width() / 4, 
		              rect.top + rect.Height() / 12, 
					  rect.left + rect.Width() / 4 + rect.Width() / 10, 
					  rect.bottom - rect.Height() / 12); 
	pBackBrush.CreateSolidBrush(RGB(128, 0, 0)); 
	pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); 
	pDC->FillRect(&rectScale, &pBackBrush); 
	pDC->SelectObject(pOldBrush); 
	pBackBrush.DeleteObject(); 
 
	//绘制指针区域立体效果 
	pDC->SelectObject(&penThick); 
	pDC->MoveTo(rectScale.left, rectScale.bottom); 
	pDC->LineTo(rectScale.left, rectScale.top); 
	pDC->LineTo(rectScale.right, rectScale.top); 
	pDC->SelectObject(&penThin); 
	pDC->MoveTo(rectScale.left + 1, rectScale.bottom); 
	pDC->LineTo(rectScale.left + 1, rectScale.top + 1); 
	pDC->LineTo(rectScale.right, rectScale.top + 1); 
	pDC->SelectObject(&penShadow); 
	pDC->MoveTo(rectScale.right - 1, rectScale.top + 1); 
	pDC->LineTo(rectScale.right - 1, rectScale.bottom - 1); 
	pDC->LineTo(rectScale.left + 1, rectScale.bottom - 1); 
	pDC->MoveTo(rectScale.right, rectScale.top); 
	pDC->LineTo(rectScale.right, rectScale.bottom); 
	pDC->LineTo(rectScale.left, rectScale.bottom); 
 
	m_rectScale = rectScale; 
	m_rectScale.DeflateRect(2, 2, 2, 2); 
 
	//绘制刻度 
	fScaleFont.CreateFont(rect.Height() / 8, 0,    
		0,    
		0,    
		FW_NORMAL,  
		FALSE,  
		FALSE,  
		FALSE,  
		DEFAULT_CHARSET,  
		OUT_DEFAULT_PRECIS,  
		CLIP_DEFAULT_PRECIS,  
		DEFAULT_QUALITY,  
		DEFAULT_PITCH | FF_DONTCARE,  
		"System");   
	pOldFont = (CFont *)pDC->SelectObject(&fScaleFont);  
	penScale.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));  
	for (int i=0; iSelectObject(penScale); 
		pDC->MoveTo(ptStartTick); 
		pDC->LineTo(ptEndTick); 
 
		//绘制立体感觉 
		CPoint ptShadowStartTick, ptShadowEndTick; 
		ptShadowStartTick = ptStartTick; 
		ptShadowEndTick = ptEndTick; 
		ptShadowStartTick.y--; 
		ptShadowEndTick.y--; 
		pDC->SelectObject(penShadow); 
		pDC->MoveTo(ptShadowStartTick); 
		pDC->LineTo(ptShadowEndTick);		 
 
		//绘制子刻度 
		for (int j=0; jSelectObject(penScale); 
				pDC->MoveTo(ptSubStartTick); 
				pDC->LineTo(ptSubEndTick); 
 
				CPoint ptShadowSubStartTick, ptShadowSubEndTick; 
				ptShadowSubStartTick = ptSubStartTick; 
				ptShadowSubEndTick = ptSubEndTick; 
				ptShadowSubStartTick.y--; 
				ptShadowSubEndTick.y--; 
				pDC->SelectObject(penShadow); 
				pDC->MoveTo(ptShadowSubStartTick); 
				pDC->LineTo(ptShadowSubEndTick); 
			} 
		} 
 
		//绘制刻度  
		CRect ptScale; 
		pDC->SetBkMode(TRANSPARENT); 
		strScale.Format("%.0f", (m_dMaxValue - m_dMinValue) * i / m_nTicks); 
		CSize size = pDC->GetTextExtent(strScale); 
		pDC->SetTextColor(RGB(255, 255, 255)); 
		ptScale.SetRect(rect.left + rect.Width() * 2 / 3, 
			            ptStartTick.y - size.cy / 2, 
						rect.right, 
						ptStartTick.y + size.cy / 2);  
		pDC->DrawText(strScale, ptScale, DT_LEFT | DT_VCENTER | DT_SINGLELINE); 
		pDC->SetTextColor(RGB(0, 0, 0)); 
		ptScale.DeflateRect(-1, -1, 1, 1); 
		pDC->DrawText(strScale, ptScale, DT_LEFT | DT_VCENTER | DT_SINGLELINE); 
	} 
 
	pDC->SelectObject(pOldPen); 
	pDC->SelectObject(pOldBrush); 
	pDC->SelectObject(pOldFont); 
	penThick.DeleteObject(); 
	penThin.DeleteObject(); 
	penShadow.DeleteObject();  
	m_brushBack.DeleteObject(); 
	pBackBrush.DeleteObject();  
	fScaleFont.DeleteObject(); 
	penScale.DeleteObject(); 
} 
 
void CThermoMeter::DrawScale(CDC *pDC) 
{ 
	if (m_dCurrentValue > m_dMaxValue)  
	{  
		m_dCurrentValue = m_dMaxValue;  
	}  
	else if (m_dCurrentValue < m_dMinValue)  
	{  
		m_dCurrentValue = m_dMinValue;  
	}  
 
	CRect rectScale; 
	double yScale = (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue); 
	rectScale.SetRect(m_rectScale.left, 
					  m_rectScale.bottom - int(yScale * (m_rectScale.Height())), 
					  m_rectScale.right, 
					  m_rectScale.bottom); 
	 
	CBrush pBackBrush, *pOldBrush; 
	pBackBrush.CreateSolidBrush(RGB(255, 0, 0)); 
	pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); 
	pDC->FillRect(&rectScale, &pBackBrush); 
 
	pDC->SelectObject(pOldBrush); 
	pBackBrush.DeleteObject(); 
 
	m_ctrlUnit.SetRect(GetUnitRect()); 
} 
 
CRect CThermoMeter::GetUnitRect() 
{ 
	CRect rcClient; 
 
	double yScale = (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue); 
	int yPos = m_rectScale.bottom - int(yScale * (m_rectScale.Height())); 
	rcClient.left = m_rectCtrl.left + m_rectCtrl.Width() / 12; 
	rcClient.right = rcClient.left + m_rectCtrl.Width() / 8; 
	rcClient.top = yPos - m_rectCtrl.Width() / 16; 
	rcClient.bottom = yPos + m_rectCtrl.Width() / 16; 
 
	return rcClient; 
} 
 
void CThermoMeter::SetCurrentValue(const double dCurrentValue) 
{  
	m_dCurrentValue = dCurrentValue; 
	Invalidate();  
}