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

📄 roundmeter.cpp

📁 一个非常灵活的圆行仪表类
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************
* Copyright (c) 2007* All rights reserved.* 
* ATTRIBUTE:        一个仪表控件类,用来仿真工业控制现场仪表数据显示等
* FILE NAME:		RoundMeter.cpp
* FILE ID:			SYSTEMCTRL-ROUNDMETER-CPP
* ABSTRACT:			可用于工业控制仿真仪表数据显示等
* CURRENT VERSION:	V1.0
* AUTHOR:			戚高
* CONTECT:			successq_g@163.com	
* BUILD DATA:		26/12/2007
* COMPLETION DATE:	26/12/2007
* PRE-VERSION:		NONE
* PRE-AUTHOR:		NONE
* PRE-COMPLETION DATE:	
* NOTE:	            未经授权请不要作为商业用途,或者如果您要作为商业
                    用途,请联系作者
***********************************************************************/
#include "stdafx.h" 
#include "RoundMeter.h"
#include <math.h>
#include "MemDC.h"
 

CRoundMeter::CRoundMeter()
{
	m_bMouseDrag = false;
	//颜色设置
//	m_BackColor = RGB( 33, 177, 138);          //背景方框颜色
	m_BackColor = RGB( 0, 0, 0);          //背景方框颜色
	m_BackLineColor=RGB( 0, 0, 0);             //背景方框线色

	m_NeedleColor=RGB( 0, 0, 0);					//指针颜色
	m_NeedleLineColor=RGB( 0, 0, 0);				//指针线色
	m_WarnNeedleColor=RGB( 255, 0, 0);          //报警指针颜色
	m_WarnNeedleLineColor=RGB( 255, 0, 0);      //报警指针线色
	m_FirstColor=RGB(182, 182, 182);               //第一圈颜色
	m_FirstLineColor=RGB( 0, 0, 0);					//第一圈线色
	m_SecondColor=RGB(182, 182, 182);              //第二圈颜色
	m_SecondLineColor=RGB(0,0,0);					//第二圈线色
	m_ThirdColor=RGB(182, 182, 182);               //第三圈颜色
	m_ThirdLineColor=RGB(0,0,0);					//第三圈线色
	m_FourthColor=RGB(0,0,0);						//第四圈颜色  指针圈1
	m_FourthLineColor=RGB(0,0,0);					//第四圈线色  指针圈1
	m_FifthColor=RGB( 255, 128, 64);               //第五圈颜色  指针圈2
	m_FifthLineColor=RGB( 255, 128, 64);           //第五圈线色  指针圈2
	m_TextColor=RGB( 0, 0, 255);                 //普通字体颜色
	m_TextBackColor=RGB(255,255,255);            //普通字体底色
	m_WarnTextColor=RGB(255,0,0);				 //报警字体颜色  
	m_WarnTextBackColor=RGB(255,255,255);        //报警字体底色  
	m_TickColor=RGB(0,0,255);                    //大格刻度颜色
	m_SubTickColor=RGB(0,0,0);                   //小格刻度颜色


	m_dMinValue = 0.00f;				//表量程初始值
	m_dMaxValue = 1000.00f;				//表量程终值
	m_WarnMaxValue = 900.0f;            //报警上限
	m_WarnMinValue = 100.0f;            //报警下限

	m_nTicks = 5;						//大格个数
	m_nSubTicks = 5;					//大格中小格个数
	m_dCurrentValue = 600.00f;
	m_nStartAngle = 0;                   
	m_nEndAngle = m_nStartAngle;        //两个角度相等表示全圆表
	m_ncnt=0;                           //遮蔽多边形点数为零
	m_bReset=TRUE;                      //第一次需要重绘

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

CRoundMeter::~CRoundMeter()
{

}


BEGIN_MESSAGE_MAP(CRoundMeter, CStatic)
	//{{AFX_MSG_MAP(CRoundMeter)
	ON_WM_PAINT()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

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

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

void CRoundMeter::PreSubclassWindow() 
{
	ModifyStyle(0, BS_NOTIFY);
}

//绘制仪表背景
void CRoundMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
	CPen   pPenThin, *pOldPen;
	CBrush m_brushBack, *pOldBrush;
	static POINT  PtRgn[8];

	pDC->SetBkColor(m_BackColor);
	m_brushBack.CreateSolidBrush(m_BackColor);
	pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);
	pPenThin.CreatePen(PS_SOLID, 1, m_BackLineColor);
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);
	pDC->FillRect(rect, &m_brushBack);   //绘制背景
	pDC->Rectangle(rect);                //绘制一个边框
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
	m_brushBack.DeleteObject();
	pPenThin.DeleteObject();



	pDC->SetBkMode(TRANSPARENT); 

	m_ptMeterCenter = rect.CenterPoint(); //点中心坐标 
	int nRadius = 0;

	if (rect.Width() <= rect.Height())
	{
		nRadius = rect.Width() - 5;
	}
	else
	{
		nRadius = rect.Height() - 5;
	}
	m_nRadiusFrame = nRadius;

	//绘制仪表圆盘

	m_brushBack.CreateSolidBrush(m_FirstColor);   //绘制第一圈
	pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);
	pPenThin.CreatePen(PS_SOLID, 1, m_FirstLineColor);
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);
	CRect rectRound(m_ptMeterCenter.x - nRadius / 2, 
					m_ptMeterCenter.y - nRadius / 2,
					m_ptMeterCenter.x + nRadius / 2, 
					m_ptMeterCenter.y + nRadius / 2);
	pDC->Ellipse(rectRound);  
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
	m_brushBack.DeleteObject();
	pPenThin.DeleteObject();

	if(m_bReset)
	{
		//计算遮蔽区域
		m_ncnt=CalVeilRgn(PtRgn,m_ptMeterCenter,nRadius / 2,m_nStartAngle,m_nEndAngle);
		//计算刻度结构
		CalAboutTicks(nRadius);
		m_bReset=FALSE;
	}
	
	

	m_brushBack.CreateSolidBrush(m_SecondColor);   //绘制第二圈
	pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);
	pPenThin.CreatePen(PS_SOLID, 1, m_SecondLineColor);
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);
	rectRound.SetRect(m_ptMeterCenter.x - nRadius / 2 + nRadius / 50, 
					  m_ptMeterCenter.y - nRadius / 2 + nRadius / 50,
					  m_ptMeterCenter.x + nRadius / 2 - nRadius / 50, 
					  m_ptMeterCenter.y + nRadius / 2 - nRadius / 50);
	pDC->Ellipse(rectRound);  
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
	m_brushBack.DeleteObject();
	pPenThin.DeleteObject();

	m_brushBack.CreateSolidBrush(m_ThirdColor);   //绘制第三圈
	pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);
	pPenThin.CreatePen(PS_SOLID, 1, m_ThirdLineColor);
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);
	rectRound.SetRect(m_ptMeterCenter.x - nRadius / 2 + nRadius / 15, 
					  m_ptMeterCenter.y - nRadius / 2 + nRadius / 15,
					  m_ptMeterCenter.x + nRadius / 2 - nRadius / 15, 
					  m_ptMeterCenter.y + nRadius / 2 - nRadius / 15);
	pDC->Ellipse(rectRound); 
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
	m_brushBack.DeleteObject();
	pPenThin.DeleteObject();

	//绘制遮蔽区
	DrawRgn(pDC,PtRgn,m_ncnt,m_BackColor);	

	//画刻度
	char strFigure[MAXNAMELENGTH + 1];
	memset(strFigure, 0, sizeof(strFigure));
	CFont fDrawFont;
	fDrawFont.CreateFont(nRadius/15, nRadius/45, 0, 0, 0, FALSE, FALSE, ANSI_CHARSET,
					  CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
					  DEFAULT_PITCH, FF_DONTCARE, _T("Arail"));
	CFont *pOldFont = (CFont *)pDC->SelectObject(&fDrawFont);

	pPenThin.CreatePen(PS_SOLID, nRadius / 50, m_TickColor);    //母刻度
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);
	pDC->SetBkMode(TRANSPARENT);
	CPoint pt;
	for (int i=0; i<m_nTicks+1; i++) //刻度坐标
	{
		pt=m_TicksSPt.GetAt(i);pDC->MoveTo(pt);
		pt=m_TicksEPt.GetAt(i);pDC->LineTo(pt);
		//写刻度
		sprintf(strFigure, "%.0f", (m_dMaxValue - m_dMinValue) * i / m_nTicks);
//		pDC->SetTextColor(m_TextBackColor);
//		pDC->DrawText(strFigure, , 
//			DT_SINGLELINE|DT_CENTER|DT_VCENTER);		
		pDC->SetTextColor(m_TextColor);
		pDC->DrawText(strFigure,m_TicksTitle.GetAt(i),DT_SINGLELINE|DT_CENTER|DT_VCENTER);
	}
	pDC->SelectObject(pOldPen);
	pPenThin.DeleteObject();
	
	pPenThin.CreatePen(PS_SOLID, nRadius / 100, m_SubTickColor);   //子刻度颜色
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);
	for (i=0; i<m_nTicks*(m_nSubTicks-1); i++)
	{
		pt=m_SubTicksSPt.GetAt(i);pDC->MoveTo(pt);
		pt=m_SubTicksEPt.GetAt(i);pDC->LineTo(pt);
	}
	pDC->SelectObject(pOldPen);
	pPenThin.DeleteObject();
	pDC->SelectObject(pOldFont);
	fDrawFont.DeleteObject();


	//文本显示的初始化
	int nRadiusFrame = m_nRadiusFrame / 2;
	CFont pUnitFont;
	pUnitFont.CreateFont(nRadiusFrame/5, 0, 0, 0, 0, FALSE, FALSE, ANSI_CHARSET,
					  CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
					  DEFAULT_PITCH, FF_DONTCARE, _T("Times New Roman"));
	pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);
//	pDC->SetTextColor(m_TextBackColor);
//	CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
//			        int(m_ptMeterCenter.y + nRadiusFrame * 0.10f + 2),
//					int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
//					int(m_ptMeterCenter.y + nRadiusFrame * 0.50f + 2));
//	pDC->DrawText(m_strUnits, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	pDC->SetTextColor(m_TextColor);
	pDC->DrawText(m_strUnits, &m_nrectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	pDC->SelectObject(pOldFont);
	pUnitFont.DeleteObject();

}

void CRoundMeter::DrawNeedle(CDC *pDC, CRect &rect)
{
	CRect rectRound;
	CPen pPenThin, *pOldPen;
	CBrush pNeedleBrush, *pOldBrush;
	if(m_dCurrentValue>m_WarnMaxValue || m_dCurrentValue<m_WarnMinValue)
	{
		pNeedleBrush.CreateSolidBrush(m_WarnNeedleColor);		
		pPenThin.CreatePen(PS_SOLID, 1, m_WarnNeedleLineColor);	
	}
	else
	{
		pNeedleBrush.CreateSolidBrush(m_NeedleColor);
		pPenThin.CreatePen(PS_SOLID, 1, m_NeedleLineColor);
	}

	pOldBrush = (CBrush *)pDC->SelectObject(&pNeedleBrush);
	pOldPen = (CPen *)pDC->SelectObject(&pPenThin);

	double dRadius = fabs(m_nRadiusFrame / 2 - m_nRadiusFrame / 16) - fabs(m_nRadiusFrame / 15);
	if (m_dCurrentValue < m_dMinValue)
	{
		m_dCurrentValue = m_dMinValue;
	}
	else if (m_dCurrentValue > m_dMaxValue)
	{
		m_dCurrentValue = m_dMaxValue;
	}
/////////////////////////////////////////////////////
	double dAngle; 
	if(m_nStartAngle==m_nEndAngle)
	{
		dAngle=360.0*(m_dCurrentValue-m_dMinValue)/(m_dMaxValue-m_dMinValue);
	}
	if(m_nStartAngle>m_nEndAngle)
	{
		dAngle=double((m_nStartAngle-m_nEndAngle))*(m_dCurrentValue-m_dMinValue)
			/(m_dMaxValue-m_dMinValue);
	}
	if(m_nStartAngle<m_nEndAngle)
	{
		dAngle=double(m_nStartAngle+360-m_nEndAngle)*(m_dCurrentValue-m_dMinValue)
			/(m_dMaxValue-m_dMinValue);
	}
	dAngle=m_nStartAngle-dAngle;
	if(dAngle<0.0)
		dAngle=dAngle+360.0;
//	double dAngle = 300 * (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue);
	
	CPoint ptRgn[5];
	ptRgn[0].x = int(m_ptMeterCenter.x + (m_nRadiusFrame / 25) * cos(dAngle * PI / 180));
	ptRgn[0].y = int(m_ptMeterCenter.y - (m_nRadiusFrame / 25) * sin(dAngle * PI / 180));
	ptRgn[1].x = int(m_ptMeterCenter.x + (m_nRadiusFrame / 25) * cos(dAngle * PI / 180) 
				 + (m_nRadiusFrame / 20) * cos((dAngle-30) * PI / 180));
	ptRgn[1].y = int(m_ptMeterCenter.y - (m_nRadiusFrame / 25) * sin(dAngle * PI / 180) 
				 - (m_nRadiusFrame / 25) * sin((dAngle-30) * PI / 180));
	ptRgn[2].x = int(m_ptMeterCenter.x + (dRadius - 10) * cos(dAngle * PI / 180));
	ptRgn[2].y = int(m_ptMeterCenter.y - (dRadius - 10) * sin(dAngle * PI / 180));
	ptRgn[3].x = int(m_ptMeterCenter.x + (m_nRadiusFrame / 25) * cos(dAngle * PI / 180) 
				 + (m_nRadiusFrame / 20) * cos((dAngle + 30) * PI / 180));
	ptRgn[3].y = int(m_ptMeterCenter.y - (m_nRadiusFrame / 25) * sin(dAngle * PI / 180) 
				 - (m_nRadiusFrame / 25) * sin((dAngle + 30) * PI / 180));
	ptRgn[4].x = int(m_ptMeterCenter.x + (m_nRadiusFrame / 25) * cos(dAngle * PI / 180));
	ptRgn[4].y = int(m_ptMeterCenter.y - (m_nRadiusFrame / 25) * sin(dAngle * PI / 180));
	
//	pDC->SetPolyFillMode(WINDING);
	pDC->Polygon(ptRgn, 5);
	pNeedleBrush.DeleteObject();
	pPenThin.DeleteObject();
 
	//第四圈
	pNeedleBrush.CreateSolidBrush(m_FourthColor);
	pPenThin.CreatePen(PS_SOLID, 1, m_FourthLineColor);

⌨️ 快捷键说明

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