⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 panelmeter.cpp

📁 工控软件图形界面-控件实现 利用双缓冲技术编写圆盘仪表
💻 CPP
字号:
/***********************************************************************
* Copyright (c) 2007* All rights reserved.* 
* ATTRIBUTE:        一个仪表控件类,用来仿真工业控制现场仪表数据显示等
* FILE NAME:		PanelMeter.cpp
* FILE ID:			SYSTEMCTRL-PANELMETER-CPP
* ABSTRACT:			可用于工业控制仿真仪表数据显示等
* CURRENT VERSION:	V1.0
* AUTHOR:			戚高
* CONTECT:			successq_g@163.com	
* BUILD DATA:		27/12/2007
* COMPLETION DATE:	27/12/2007
* PRE-VERSION:		NONE
* PRE-AUTHOR:		NONE
* PRE-COMPLETION DATE:	
* NOTE:	            未经授权请不要作为商业用途,或者如果您要作为商业
                    用途,请联系作者
***********************************************************************/
#include "stdafx.h"
#include "PanelMeter.h"
#include <math.h>
#include "MemDC.h"

CPanelMeter::CPanelMeter()
{
	m_BackColor = RGB( 33, 177, 138);
	m_dMinValue = 0; 
	m_dMaxValue = 100; 
	m_dInterval = 20; 
	m_dValidValueMin = 30; 
	m_dValidValueMax = 75; 
	m_dCurrentValue = 55.00f;

	memset(m_strUnits, 0, sizeof(m_strUnits));
	strcpy(m_strUnits, "温度");			//表单位
}

CPanelMeter::~CPanelMeter()
{
}


BEGIN_MESSAGE_MAP(CPanelMeter, CStatic)
//{{AFX_MSG_MAP(CPanelMeter)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPanelMeter message handlers

void CPanelMeter::PreSubclassWindow() 
{
	CStatic::PreSubclassWindow();

	SendMessage(WM_SIZE);

	CRect rect;
	GetClientRect(&rect);
	ClientToScreen(&rect);
	rect.bottom = rect.top + rect.Height() / 2 + 4; 
	MoveWindow(&rect, TRUE);
}

void CPanelMeter::SetCurrentValue(const double dCurrentValue)
{ 
	m_dCurrentValue = dCurrentValue;
	Invalidate(); 
}

void CPanelMeter::SetValidValue(const double dMin, const double dMax)
{
	m_dValidValueMin = dMin;   
	m_dValidValueMax = dMax; 

	ReconstructControl(); 
}

void CPanelMeter::SetRange(const double dMin, const double dMax, const double dInterval)
{ 
	m_dMinValue = dMin; 
	m_dMaxValue = dMax; 
	m_dInterval = dInterval; 
	
	ReconstructControl(); 
}

void CPanelMeter::SetUnits(const char *strUnits)
{
	strcpy(m_strUnits, strUnits);
 
	ReconstructControl();
}

//重新更新背景
void CPanelMeter::ReconstructControl()
{
	if (m_pbitmapOldMeterPlate &&
		m_bitmapMeterPlate.GetSafeHandle() && 
		m_dcMeterPlate.GetSafeHdc())
	{
		m_dcMeterPlate.SelectObject(m_pbitmapOldMeterPlate);
		m_dcMeterPlate.DeleteDC() ;
		m_bitmapMeterPlate.DeleteObject();
	}
	
	Invalidate ();
}

void CPanelMeter::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);

	DrawValue(&memDC, m_rectCtrl);
	DrawNeedle(&memDC, m_rectCtrl);	
}

BOOL CPanelMeter::OnEraseBkgnd(CDC* pDC) 
{
	return TRUE; 	
}

//绘制仪表背景
void CPanelMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
	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->Rectangle(rect);                //绘制一个边框
	pDC->SelectObject(pOldBrush);
	m_brushBack.DeleteObject();

	int yHalf = rect.bottom - 8; 
	float fa = (float)rect.Width() / 2; 
	float fb = (float)rect.Height() - 8; 
	
	CFont fScaleFont; 
	fScaleFont.CreateFont(10, 12,   
		0,   
		0,   
		FW_NORMAL, 
		FALSE, 
		FALSE, 
		FALSE, 
		DEFAULT_CHARSET, 
		OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS, 
		DEFAULT_QUALITY, 
		DEFAULT_PITCH | FF_DONTCARE, 
		"Arial");   
	
	if (m_dValidValueMin >= 0)  
	{ 
		CBrush brshGreen; 
		CBrush brshRed; 
		brshGreen.CreateSolidBrush(RGB(0, 192, 0)); 
		brshRed.CreateSolidBrush(RGB(230, 100, 100)); 
		
		float fStartAngle = (float)(m_dValidValueMin - m_dMinValue) / (float)(m_dMaxValue - m_dMinValue) * 3.14f; 
		float fEndAngle   = (float)(m_dValidValueMax - m_dMinValue) / (float)(m_dMaxValue - m_dMinValue) * 3.14f; 
		
		pDC->MoveTo(rect.left, yHalf); 
		pDC->LineTo(rect.left + 20, yHalf); 
		pDC->MoveTo(rect.right - 1, yHalf); 
		pDC->LineTo(rect.right - 22, yHalf); 
		
		pDC->MoveTo(rect.left, yHalf); 
		for (float f = 0; f <= 3.14; f += 0.01f) 
		{
			pDC->LineTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top); 
		}
		pDC->MoveTo(rect.left + 20, yHalf); 
		for (f = 0; f <= 3.14; f += 0.01f)
		{
			pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(f)) + rect.left, yHalf - (int)((fb - 20) * sin(f)) + rect.top); 
		}

		CBrush *pOldBrush = pDC->SelectObject(&brshRed); 
		pDC->FloodFill(rect.left + 10, yHalf - 10, RGB(0, 0, 0)); 
		
		fStartAngle *= 100; 
		fStartAngle = (float)((int)fStartAngle) / 100; 
		fEndAngle *= 100; 
		fEndAngle = (float)((int)fEndAngle) / 100; 
		
		pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(fStartAngle)) + rect.left, yHalf - (int)(fb * sin(fStartAngle)) + rect.top); 
		pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(fStartAngle)) + rect.left, yHalf - (int)((fb - 20) * sin(fStartAngle)) + rect.top); 
		
		pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(fEndAngle)) + rect.left, yHalf - (int)(fb * sin(fEndAngle)) + rect.top); 
		pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(fEndAngle)) + rect.left, yHalf - (int)((fb - 20) * sin(fEndAngle)) + rect.top); 
		
		pDC->SelectObject(brshGreen); 
		if (fStartAngle > 0 && fEndAngle < 3.14) 
		{
			pDC->FloodFill(rect.Width() / 2 - (int)((fa - 5) * cos((fStartAngle + fEndAngle) / 2)) + rect.left, yHalf - (int)((fb - 5) * sin((fStartAngle + fEndAngle) / 2)) + rect.top, RGB(0,0,0)); 
		}

		pDC->SelectObject(pOldBrush);
	} 

	CPen pen; 
	pen.CreatePen(PS_SOLID, 3, RGB(255,255,255)); 
	CPen *pOldPen = pDC->SelectObject(&pen); 
	CFont *pOldFont = pDC->SelectObject(&fScaleFont); 
	pDC->SetBkMode(TRANSPARENT); 
	
	fa -= 10; 
	fb -= 10; 
	pDC->MoveTo(rect.left + 10, yHalf); 
	for (float f = 0; f <= 3.14; f += 0.01f) 
	{ 
		pDC->LineTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top); 
	} 
	
	float fBigStep = 3.14f / ((float)(m_dMaxValue - m_dMinValue) / (float)m_dInterval) / 4; 
	int nDiv = 0; 
	int nScale = (int)m_dMinValue; 
	for (f = 0; f <= 3.15; f += fBigStep) 
	{ 
		pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top); 
		if (nDiv == 0) 
		{ 
			pDC->LineTo(rect.Width() / 2 - (int)((fa - 15) * cos(f)) + rect.left, yHalf - (int)((fb - 15) * sin(f)) + rect.top); 
			CString str; 
			str.Format("%d", nScale); 
			nScale += (int)m_dInterval; 
			CSize size = pDC->GetOutputTextExtent(str); 
			pDC->SetTextColor(RGB(0,0,0)); 
			pDC->TextOut(rect.Width() / 2 - (int)((fa - 33) * cos(f)) + rect.left - size.cx / 2 + 1, yHalf - (int)((fb - 33) * sin(f)) + rect.top - size.cy / 2 + 1, str); 
			pDC->SetTextColor(RGB(255, 255, 255)); 
			pDC->TextOut(rect.Width() / 2 - (int)((fa - 33) * cos(f)) + rect.left - size.cx / 2, yHalf - (int)((fb - 33) * sin(f)) + rect.top - size.cy / 2, str); 
			nDiv++; 
		} 
		else 
		{ 
			pDC->LineTo(rect.Width() / 2 - (int)((fa - 10) * cos(f)) + rect.left, yHalf - (int)((fb - 10) * sin(f)) + rect.top); 
			nDiv++; 
			if (nDiv == 4) 
			{
				nDiv = 0; 
			}
		} 		
	} 	
	pDC->SelectObject(pOldFont); 
	fScaleFont.DeleteObject();

	CPoint m_ptMeterCenter;
	m_ptMeterCenter.x = rect.left + rect.Width() / 2;
	m_ptMeterCenter.y = rect.bottom;
	int nRadiusFrame = rect.Height();
	CFont pUnitFont;
	LOGFONT lf;
	lf.lfEscapement = 0;
	lf.lfItalic = NULL;
	lf.lfUnderline = NULL;
	lf.lfStrikeOut = NULL;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfHeight = nRadiusFrame / 4;
	strcpy(lf.lfFaceName, "隶书");
	pUnitFont.CreateFontIndirect(&lf);
	pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);	
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(RGB(0, 0, 0));
	CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
			        int(m_ptMeterCenter.y - nRadiusFrame * 0.70f + 2),
					int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
					int(m_ptMeterCenter.y - nRadiusFrame * 0.20f + 2));
	pDC->DrawText(m_strUnits, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	pDC->SetTextColor(RGB( 255, 255, 255));
	rectUnits.SetRect(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f),
			          int(m_ptMeterCenter.y - nRadiusFrame * 0.70f),
					  int(m_ptMeterCenter.x + nRadiusFrame * 0.30f),
					  int(m_ptMeterCenter.y - nRadiusFrame * 0.20f));
	pDC->DrawText(m_strUnits, rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	
	pDC->SelectObject(pOldPen); 
	pDC->SelectObject(pOldFont); 
	pUnitFont.DeleteObject();
}

void CPanelMeter::DrawNeedle(CDC *pDC, CRect &rect)
{
	if (m_dCurrentValue > m_dMaxValue) 
	{ 
		m_dCurrentValue = m_dMaxValue; 
	} 
	else if (m_dCurrentValue < m_dMinValue) 
	{ 
		m_dCurrentValue = m_dMinValue; 
	}   
  
	double dAngle = (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue) * 3.14f; 
  
	float fa = (float)rect.Width() / 2; 
	float fb = (float)rect.Height() - 8; 

	CBrush brshWhite; 
	CBrush brshShadow; 
	brshWhite.CreateSolidBrush(RGB(255, 255, 255)); 
	brshShadow.CreateSolidBrush(RGB(0, 0, 0)); 
  
	CBrush *pOldBrush = pDC->SelectObject(&brshShadow); 
	pDC->Ellipse(rect.Width() / 2 - 9 + rect.left, rect.Height() - 20 + rect.top, rect.Width() / 2 + 11 + rect.left, rect.Height() + rect.top); 
	pDC->SelectObject(&brshWhite); 
	pDC->Ellipse(rect.Width() / 2 - 10 + rect.left, rect.Height() - 21 + rect.top, rect.Width() / 2 + 10 + rect.left, rect.Height() - 1 + rect.top); 
	pDC->SelectObject(pOldBrush); 
  
	CPen penThick; 
	CPen penThin; 
	CPen penShadow; 
  
	penThick.CreatePen(PS_SOLID, 5, RGB(255, 100, 50)); 
	penThin.CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); 
	penShadow.CreatePen(PS_SOLID, 5, RGB(0, 0, 0)); 
  
	CPen *pOldPen = pDC->SelectObject(&penShadow); 
	pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left + 1, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top + 1); 
	pDC->LineTo(rect.Width() / 2 + rect.left + 1, rect.Height() - 11 + rect.top + 1); 
	pDC->SelectObject(&penThick); 
	pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top); 
	pDC->LineTo(rect.Width() / 2 + rect.left, rect.Height() - 11 + rect.top); 
	pDC->SelectObject(&penThin); 
	pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top); 
	pDC->LineTo(rect.Width() / 2 + rect.left, rect.Height() - 11 + rect.top); 
	pDC->SelectObject(pOldPen); 
}

void CPanelMeter::DrawValue(CDC *pDC, CRect &rect)
{
	char strCurrentValue[10];
	memset(strCurrentValue, 0, sizeof(strCurrentValue));

	sprintf(strCurrentValue, "%.2f", m_dCurrentValue);

	CPoint m_ptMeterCenter;
	m_ptMeterCenter.x = rect.left + rect.Width() / 2;
	m_ptMeterCenter.y = rect.bottom;
	int nRadiusFrame = rect.Height();
	CFont pUnitFont, *pOldFont;
	LOGFONT lf;
	lf.lfEscapement = 0;
	lf.lfItalic = NULL;
	lf.lfUnderline = NULL;
	lf.lfStrikeOut = NULL;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfHeight = nRadiusFrame / 6;
	strcpy(lf.lfFaceName, "Arial");
	pUnitFont.CreateFontIndirect(&lf);
	pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);	
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(RGB(0, 0, 0));
	CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
			        int(m_ptMeterCenter.y - nRadiusFrame * 0.40f + 2),
					int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
					int(m_ptMeterCenter.y - nRadiusFrame * 0.10f + 2));
	pDC->DrawText(strCurrentValue, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	pDC->SetTextColor(RGB( 255, 255, 255));
	rectUnits.SetRect(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f),
			          int(m_ptMeterCenter.y - nRadiusFrame * 0.40f),
					  int(m_ptMeterCenter.x + nRadiusFrame * 0.30f),
					  int(m_ptMeterCenter.y - nRadiusFrame * 0.10f));
	pDC->DrawText(strCurrentValue, rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	
	pDC->SelectObject(pOldFont);
	pUnitFont.DeleteObject();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -