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

📄 meter.cpp

📁 485通讯接口模块的编程应用
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Meter.cpp : implementation file
//

#include "stdafx.h"
#include "DK20DieselizeDynamotor.h"
#include "Meter.h"
#include "math.h"
#include "MemDC.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define PT_NUM 50
/////////////////////////////////////////////////////////////////////////////
// CMeter

CMeter::CMeter()
{
	m_nStartAngleDeg = 225;
	m_nEndAngleDeg = 315;
	m_nTicks = 10;
	m_nSubTicks = 5;
	m_dMaxValue = 100.0;
	m_dMinValue = 0.0;
	m_dCurrentValue = 50.0;
	m_nScaleDecimals = 0;
	m_nValueDecimals = 1;
	m_colorNeedle = RGB(252,0,116);
	m_strUnits = _T("Volts");
	m_bColorTick = FALSE;
	
	// 颜色表格
	m_colorTable[0] = RGB(255, 255,   0);  //黄
	m_colorTable[1] = RGB(  0, 255,   0);  //绿
	m_colorTable[2] = RGB(255,   0,   0);  //红
	m_colorTable[3] = RGB(255,183, 34);    //褐
	m_colorTable[4] = RGB(255, 92, 93);    //洋红

	iStatus = 2 ; //初始状态为2

}

CMeter::~CMeter()
{
}


BEGIN_MESSAGE_MAP(CMeter, CStatic)
	//{{AFX_MSG_MAP(CMeter)
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMeter message handlers

void CMeter::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	// 获得控件区域
	GetClientRect (&m_rectCtrl);

	CMemDC memDC(&dc, &m_rectCtrl); 

	// 选取圆盘边框半径
	m_nRadiusFrame = max(m_rectCtrl.Height(), m_rectCtrl.Width())*9/21;

	// 获得仪表盘中心点
	m_ptMeterCenter = m_rectCtrl.CenterPoint();
	m_ptMeterCenter.y += m_nRadiusFrame/10;
	
	//绘制仪表盘
	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) ;
       	DrawMeterBackground(&m_dcBackground, m_rectCtrl);

	}
	memDC.BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(), 
			           &m_dcBackground, 0, 0, SRCCOPY) ;
 	// 绘制指针
	DrawNeedle(&memDC);
   	DrawNode(&memDC);
   	DrawValue(&memDC);
	// Do not call CStatic::OnPaint() for painting messages
//  ReleaseDC(&dc) ; 
	
}

void CMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
	int nInnerRadius = m_nRadiusFrame*8/10;	// 内圆弧半径

	m_nCenterRadius = m_nRadiusFrame/20;	// 中心园半径大小

	int nFrame = m_nRadiusFrame/18;			// 边框厚度

	double dstepTickDeg = (360.0+m_nStartAngleDeg-m_nEndAngleDeg)/(m_nTicks*m_nSubTicks);	// 刻度步进角度

	int nSubTickR = nInnerRadius+(m_nRadiusFrame-2*nFrame-nInnerRadius)/2;

	double dDeg = (m_nStartAngleDeg+360.0-m_nEndAngleDeg)/(TABNUM*PT_NUM);
	 

	CRect rectPanel,rectInnerPanel;
	CPen penDraw, *pPenOld;
	CFont *pFontOld;
	CBrush brushFill, *pBrushOld;
	POINT ptStart, ptEnd, ptInnerStart, ptInnerEnd;	
	CPoint pointInner[BOUNDARY_POINTS], ptGroup1[PT_NUM*TABNUM+1], ptGroup2[PT_NUM*TABNUM+1];
	CPoint ptRgn[PT_NUM*2+2];
	CPoint pttemp;
	CString strtemp;
	double dRadPerDeg;
	double dTickAngleRad;
	double dTemp;
	int nRef = 0;
	int nTickAngle;	
	int nHeight;	// 字体大小
	double dtempangle;
	
	// 计算起始角终止角弧度
	dRadPerDeg = 4.0*atan(1.0)/180.0;
	m_dLeftAngleRad = (m_nStartAngleDeg-180.0)*dRadPerDeg;
	m_dRightAngleRad = (m_nEndAngleDeg-360.0)*dRadPerDeg;
	
	// 计算圆弧起始终止点及区域
	ptStart.x = m_ptMeterCenter.x-(int)(m_nRadiusFrame*cos(m_dLeftAngleRad));
	ptStart.y = m_ptMeterCenter.y+(int)(m_nRadiusFrame*sin(m_dLeftAngleRad));
	ptEnd.x = m_ptMeterCenter.x+(int)(m_nRadiusFrame*cos(-m_dRightAngleRad));
	ptEnd.y = m_ptMeterCenter.y+(int)(m_nRadiusFrame*sin(-m_dRightAngleRad));
	
	rectPanel.SetRect(m_ptMeterCenter.x-m_nRadiusFrame, m_ptMeterCenter.y-m_nRadiusFrame,
						m_ptMeterCenter.x+m_nRadiusFrame, m_ptMeterCenter.y+m_nRadiusFrame);
	// 获取点的位置
	for(int i=0; i<=PT_NUM*TABNUM; i++)
	{
		ptGroup1[i].x = m_ptMeterCenter.x + (int)((m_nRadiusFrame-nFrame)*cos((m_nStartAngleDeg-i*dDeg)*dRadPerDeg));
		ptGroup1[i].y = m_ptMeterCenter.y - (int)((m_nRadiusFrame-nFrame)*sin((m_nStartAngleDeg-i*dDeg)*dRadPerDeg));
		ptGroup2[i].x = m_ptMeterCenter.x + (int)(m_nRadiusFrame*8*cos((m_nStartAngleDeg-i*dDeg)*dRadPerDeg)/10);
		ptGroup2[i].y = m_ptMeterCenter.y - (int)(m_nRadiusFrame*8*sin((m_nStartAngleDeg-i*dDeg)*dRadPerDeg)/10);
	}

	// 获取系统颜色;
	m_colorWindow    = GetSysColor(COLOR_WINDOW);
	m_colorButton    = GetSysColor(COLOR_BTNFACE);
	m_colorShadow    = GetSysColor(COLOR_BTNSHADOW);
	m_colorHighlight = GetSysColor(COLOR_BTNHIGHLIGHT);
	m_colorText		= GetSysColor(COLOR_BTNTEXT);
	// 临时使用的颜色
	COLORREF colorCaption, cEdge, cMiddle;
	cMiddle = RGB(255, 255, 255);
	cEdge = RGB(96, 96, 255);

	// 用按钮色绘制背景
	brushFill.DeleteObject();
 	brushFill.CreateSolidBrush(m_colorButton);
 	pBrushOld = pDC->SelectObject(&brushFill);
 	pDC->Rectangle(rect);
 	pDC->SelectObject(pBrushOld);


	// 绘制内圈
	ptInnerStart.x = m_ptMeterCenter.x-(int)(nInnerRadius*cos(m_dLeftAngleRad));
	ptInnerStart.y = m_ptMeterCenter.y+(int)(nInnerRadius*sin(m_dLeftAngleRad));
	ptInnerEnd.x = m_ptMeterCenter.x+(int)(nInnerRadius*cos(-m_dRightAngleRad));
	ptInnerEnd.y = m_ptMeterCenter.y+(int)(nInnerRadius*sin(-m_dRightAngleRad));
	
	rectInnerPanel.SetRect(m_ptMeterCenter.x-nInnerRadius, m_ptMeterCenter.y-nInnerRadius,
						   m_ptMeterCenter.x+nInnerRadius ,m_ptMeterCenter.y+nInnerRadius);

	penDraw.DeleteObject();
  	if(m_bColorTick)
	{
		
		// 绘制色彩刻度
		for(i=0; i<TABNUM; i++)
		{
			//确定区域
			for(int j=0; j<=PT_NUM; j++)
			{
				ptRgn[j] = ptGroup1[i*PT_NUM+j];
				ptRgn[2*PT_NUM+1-j] = ptGroup2[i*PT_NUM+j];
			}
			brushFill.DeleteObject();
			if (i<3)
			{
				brushFill.CreateSolidBrush(m_colorTable[1]);
			}
			else
			{
				brushFill.CreateSolidBrush(m_colorTable[2]);
			}
			pBrushOld = pDC->SelectObject(&brushFill);
			penDraw.DeleteObject();
			if (i<3)
			{
				penDraw.CreatePen(PS_SOLID, 1, m_colorTable[1]);
			}
			else
			{
				penDraw.CreatePen(PS_SOLID, 1, m_colorTable[2]);
			}
			pPenOld = pDC->SelectObject(&penDraw);
			pDC->Polygon(ptRgn, 2*PT_NUM+2);
			pDC->SelectObject(pBrushOld);
			pDC->SelectObject(pPenOld);
		}
		
	}

	// 计算刻度点,避免不能整除引起较大误差*100
	for(nTickAngle=m_nStartAngleDeg*100; nTickAngle>=(m_nEndAngleDeg-360)*100; nTickAngle-=(int)(dstepTickDeg*100))
	{
		// 转换成弧度
		dTickAngleRad = (double)nTickAngle/100*dRadPerDeg;	
		// 确定外圈坐标
		// 确定x坐标
		dTemp = m_ptMeterCenter.x + (m_nRadiusFrame-2*nFrame)*cos(dTickAngleRad);
		m_pointBoundary[nRef].x = ROUND(dTemp);
		// 确定y坐标
		dTemp = m_ptMeterCenter.y - (m_nRadiusFrame-2*nFrame)*sin(dTickAngleRad);
		m_pointBoundary[nRef].y = ROUND(dTemp);
		
		// 确定刻度点(主刻度和子刻度)
		//主刻度及文本标注点
		if(nRef%m_nSubTicks == 0)
		{
			dTemp = m_ptMeterCenter.x + nInnerRadius*cos(dTickAngleRad);
			pointInner[nRef].x = ROUND(dTemp);
			dTemp = m_ptMeterCenter.y - nInnerRadius*sin(dTickAngleRad);
			pointInner[nRef].y = ROUND(dTemp);
		}
		// 子刻度
		else
		{
			dTemp = m_ptMeterCenter.x + nSubTickR*cos(dTickAngleRad);
			pointInner[nRef].x = ROUND(dTemp);
			dTemp = m_ptMeterCenter.y - nSubTickR*sin(dTickAngleRad);
			pointInner[nRef].y = ROUND(dTemp);
		}
		nRef++ ;
	}
	// 多边形区域
	m_rgnBoundary.DeleteObject() ;
//	m_rgnBoundary.CreatePolygonRgn(m_pointBoundary, nRef, ALTERNATE);
	
	m_rectValue.top = m_ptMeterCenter.y + m_nRadiusFrame/5;
	m_rectValue.bottom = m_ptMeterCenter.y + m_nRadiusFrame/2;
	m_rectValue.left = m_ptMeterCenter.x - m_nRadiusFrame/2;
	m_rectValue.right = m_ptMeterCenter.x + m_nRadiusFrame/2;

	// 绘制刻度
	penDraw.DeleteObject();
	penDraw.CreatePen(PS_SOLID, 1, RGB(0,0,0));
	pPenOld = pDC->SelectObject(&penDraw);
	for(i=0; i<nRef; i++)
	{
		pDC->MoveTo(m_pointBoundary[i]);
		pDC->LineTo(pointInner[i]);
	}
	pDC->SelectObject(pPenOld);	

	// 刻度标号
	// 确定字体大小
	nHeight = m_nRadiusFrame/6;
	m_font.CreateFont(nHeight, 0, 0, 0, 400, 
							FALSE, FALSE, 0, ANSI_CHARSET,
							OUT_DEFAULT_PRECIS, 
							CLIP_DEFAULT_PRECIS,
							DEFAULT_QUALITY, 
							DEFAULT_PITCH|FF_SWISS, _T("Arial"));

	pFontOld = pDC->SelectObject(&m_font);
	pDC->SetBkMode(TRANSPARENT);
	for(i=0; i<=m_nTicks; i++)
	{	
		dtempangle = m_nStartAngleDeg-i*m_nSubTicks*dstepTickDeg;
		strtemp.Format(_T("%.*lf"), m_nScaleDecimals, (m_dMinValue+(m_dMaxValue-m_dMinValue)*i/m_nTicks));

		if(dtempangle>190)
		{
 			::SetTextAlign(pDC->m_hDC , TA_BOTTOM|TA_LEFT)  ; 
 			pDC->ExtTextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/2,ETO_OPAQUE,NULL ,strtemp , NULL) ; 
 
		}
		
		else if(dtempangle>170)
		{
			::SetTextAlign(pDC->m_hDC ,TA_BASELINE|TA_LEFT)  ; 
			pDC->ExtTextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/3,ETO_OPAQUE,NULL ,strtemp , NULL) ; 
		}
		else if(dtempangle>135)
		{
			::SetTextAlign(pDC->m_hDC ,TA_BASELINE|TA_LEFT)  ; 
			pDC->ExtTextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/2,ETO_OPAQUE,NULL ,strtemp , NULL) ; 
		}
		else if(dtempangle>100)
		{
			::SetTextAlign(pDC->m_hDC ,TA_TOP|TA_LEFT)  ; 
			pDC->ExtTextOut(pointInner[m_nSubTicks*i].x-nHeight/4, pointInner[m_nSubTicks*i].y-nHeight/8,ETO_OPAQUE,NULL ,strtemp , NULL) ; 
		}

		else if(dtempangle>80)
		{
			::SetTextAlign(pDC->m_hDC ,TA_TOP|TA_CENTER)  ; 
			pDC->ExtTextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y,ETO_OPAQUE,NULL ,strtemp , NULL) ; 
		}
		else if(dtempangle>45)
		{
			::SetTextAlign(pDC->m_hDC ,TA_BOTTOM|TA_RIGHT)  ; 
			pDC->ExtTextOut(pointInner[m_nSubTicks*i].x+nHeight/3, pointInner[m_nSubTicks*i].y+nHeight,ETO_OPAQUE,NULL ,strtemp , NULL) ; 
		}

⌨️ 快捷键说明

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