📄 roundmeter.cpp
字号:
/***********************************************************************
* 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 + -