Meter类

Meter.h

 #if !defined(AFX_METER_H__D5802279_6502_4453_BE21_58604877AD39__INCLUDED_)
#define AFX_METER_H__D5802279_6502_4453_BE21_58604877AD39__INCLUDED_ #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Meter.h : header file
// #ifndef ROUND
#define ROUND(x) (int)((x) + 0.5 - (double)((x) < 0))
#endif #define BOUNDARY_POINTS 200
#define TABNUM 6
/////////////////////////////////////////////////////////////////////////////
// CMeter window class CMeter : public CStatic
{
// Construction
public:
CMeter(); // Attributes
public: // Operations
public: // Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMeter)
protected:
//}}AFX_VIRTUAL // Implementation
public:
void SetAngleRange(int nStartAngleDeg, int nEndAngleDeg);
int m_nTabNum;
void SetSubTicks(int nSubTicks);
void SetTicks(int nTicks);
void DrawValue(CDC *pDC);
void SetColorTick(BOOL bColorTick = FALSE);
BOOL m_bColorTick;
void DrawNode(CDC *pDC);
COLORREF m_colorTable[];
void SetValueDecimals(int nDecimals);
void SetUnits(CString &strUnits);
CString m_strUnits;
int m_nValueDecimals;
void SetScaleDecimals(int nDecimals);
void SetRange(double dMin, double dMax);
void SetNeedleColor (COLORREF colorNeedle);
void UpdateNeedle(double dValue);
COLORREF m_colorNeedle;
int m_nScaleDecimals; double m_dCurrentValue;
double m_dMaxValue;
double m_dMinValue; void DrawNeedle(CDC *pDC);
void ReconstructControl();
void DrawMeterBackground(CDC *pDC, CRect &rect);
int m_nStartAngleDeg; // 仪表盘圆弧起始角度
int m_nEndAngleDeg; // 仪表盘圆弧终止角度
int m_nTicks; // 刻度数
int m_nSubTicks; // 分刻度数
virtual ~CMeter(); // Generated message map functions
protected:
double m_dLeftAngleRad;
double m_dRightAngleRad;
int m_nCenterRadius; CRect m_rectCtrl; // 控件区域
CRect m_rectValue; // 显示数值区域
CRgn m_rgnBoundary; CBitmap *m_pBitmapOldBackground ;
CBitmap m_bitmapBackground ;
CDC m_dcBackground; CPoint m_ptMeterCenter; // 仪表中心
CPoint m_pointBoundary[BOUNDARY_POINTS]; // 边界点,用于绘制刻度 CFont m_font; // 显示文字字体 COLORREF m_colorWindow; // 背景色
COLORREF m_colorHighlight;
COLORREF m_colorShadow;
COLORREF m_colorButton;
COLORREF m_colorText; // 显示文本颜色 int m_nRadiusFrame; // 仪表盘边框半径
//{{AFX_MSG(CMeter)
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
//}}AFX_MSG DECLARE_MESSAGE_MAP()
}; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_METER_H__D5802279_6502_4453_BE21_58604877AD39__INCLUDED_)

Meter.cpp

 // Meter.cpp : implementation file
// #include "stdafx.h"
#include "Meter.h"
#include "math.h"
#include "MemDCEx.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 = ;
m_nEndAngleDeg = ;
m_nTicks = ;
m_nSubTicks = ;
m_dMaxValue = 100.0;
m_dMinValue = 0.0;
m_dCurrentValue = 00.0;
m_nScaleDecimals = ;
m_nValueDecimals = ;
m_colorNeedle = RGB(, , );
m_strUnits = _T("(KV)");
m_bColorTick = FALSE; // 颜色表格
m_colorTable[] = RGB(,,);
m_colorTable[] = RGB(, ,);
m_colorTable[] = RGB(,,);
m_colorTable[] = RGB(,, );
m_colorTable[] = RGB(, , );
m_colorTable[] = RGB(, , );
} CMeter::~CMeter()
{
} BEGIN_MESSAGE_MAP(CMeter, CStatic)
//{{AFX_MSG_MAP(CMeter)
ON_WM_PAINT()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP() /////////////////////////////////////////////////////////////////////////////
// CMeter message handlers void CMeter::OnPaint()
{
CPaintDC dc(this); // device context for painting // 获得控件区域
GetClientRect (&m_rectCtrl); CMemDCEx memDC(&dc, &m_rectCtrl); // 选取圆盘边框半径
m_nRadiusFrame = max(m_rectCtrl.Height(), m_rectCtrl.Width())*/; // 获得仪表盘中心点
m_ptMeterCenter = m_rectCtrl.CenterPoint();
m_ptMeterCenter.y += m_nRadiusFrame/; //绘制仪表盘
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(, , m_rectCtrl.Width(), m_rectCtrl.Height(),
&m_dcBackground, , , SRCCOPY) ; // 绘制指针
DrawNeedle(&memDC); DrawNode(&memDC); DrawValue(&memDC);
// Do not call CStatic::OnPaint() for painting messages
} void CMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
int nInnerRadius = m_nRadiusFrame*/; // 内圆弧半径 m_nCenterRadius = m_nRadiusFrame/; // 中心园半径大小 int nFrame = m_nRadiusFrame/; // 边框厚度 double dstepTickDeg = (360.0+m_nStartAngleDeg-m_nEndAngleDeg)/(m_nTicks*m_nSubTicks); // 刻度步进角度 int nSubTickR = nInnerRadius+(m_nRadiusFrame-*nFrame-nInnerRadius)/; 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+], ptGroup2[PT_NUM*TABNUM+];
CPoint ptRgn[PT_NUM*+];
CPoint pttemp;
CString strtemp;
double dRadPerDeg;
double dTickAngleRad;
double dTemp;
int nRef = ;
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=; 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**cos((m_nStartAngleDeg-i*dDeg)*dRadPerDeg)/);
ptGroup2[i].y = m_ptMeterCenter.y - (int)(m_nRadiusFrame**sin((m_nStartAngleDeg-i*dDeg)*dRadPerDeg)/);
} // 获取系统颜色;
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(, , );
cEdge = RGB(, , ); // 用按钮色绘制背景
brushFill.DeleteObject();
brushFill.CreateSolidBrush(m_colorButton);
pBrushOld = pDC->SelectObject(&brushFill);
pDC->Rectangle(rect);
pDC->SelectObject(pBrushOld); // 绘制圆盘边框 for(int iOnBand=nFrame; iOnBand>; iOnBand--)
{
penDraw.DeleteObject();
colorCaption = RGB((GetRValue(cEdge)-GetRValue(cMiddle))*((float)iOnBand)/nFrame+GetRValue(cMiddle),
(GetGValue(cEdge)-GetGValue(cMiddle))*((float)iOnBand)/nFrame+GetGValue(cMiddle),
(GetBValue(cEdge)-GetBValue(cMiddle))*((float)iOnBand)/nFrame+GetBValue(cMiddle));
penDraw.CreatePen(PS_SOLID, iOnBand*, colorCaption);
pPenOld = pDC->SelectObject(&penDraw);
pDC->Arc(&rectPanel, ptEnd, ptStart);
pDC->SelectObject(pPenOld);
}
// 绘制内圈
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();
penDraw.CreatePen(PS_SOLID, , RGB(,,));
pPenOld = pDC->SelectObject(&penDraw);
pDC->Arc(&rectInnerPanel, ptInnerEnd, ptInnerStart);
pDC->SelectObject(pPenOld); if(m_bColorTick)
{ // 绘制色彩刻度
for(int i=; i<TABNUM; i++)
{
//确定区域
for(int j=; j<=PT_NUM; j++)
{
ptRgn[j] = ptGroup1[i*PT_NUM+j];
ptRgn[*PT_NUM+-j] = ptGroup2[i*PT_NUM+j];
}
brushFill.DeleteObject();
brushFill.CreateSolidBrush(m_colorTable[i]);
pBrushOld = pDC->SelectObject(&brushFill);
penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , m_colorTable[i]);
pPenOld = pDC->SelectObject(&penDraw);
pDC->Polygon(ptRgn, *PT_NUM+);
pDC->SelectObject(pBrushOld);
pDC->SelectObject(pPenOld);
} } // 计算刻度点,避免不能整除引起较大误差*100
for(nTickAngle=m_nStartAngleDeg*; nTickAngle>=(m_nEndAngleDeg-)*; nTickAngle-=(int)(dstepTickDeg*))
{
// 转换成弧度
dTickAngleRad = (double)nTickAngle/*dRadPerDeg;
// 确定外圈坐标
// 确定x坐标
dTemp = m_ptMeterCenter.x + (m_nRadiusFrame-*nFrame)*cos(dTickAngleRad);
m_pointBoundary[nRef].x = ROUND(dTemp);
// 确定y坐标
dTemp = m_ptMeterCenter.y - (m_nRadiusFrame-*nFrame)*sin(dTickAngleRad);
m_pointBoundary[nRef].y = ROUND(dTemp); // 确定刻度点(主刻度和子刻度)
//主刻度及文本标注点
if(nRef%m_nSubTicks == )
{
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/;
m_rectValue.bottom = m_ptMeterCenter.y + m_nRadiusFrame/;
m_rectValue.left = m_ptMeterCenter.x - m_nRadiusFrame/;
m_rectValue.right = m_ptMeterCenter.x + m_nRadiusFrame/; // 绘制刻度
penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , RGB(,,));
pPenOld = pDC->SelectObject(&penDraw);
for(int i=; i<nRef; i++)
{
pDC->MoveTo(m_pointBoundary[i]);
pDC->LineTo(pointInner[i]);
}
pDC->SelectObject(pPenOld); // 刻度标号 nHeight = m_nRadiusFrame/; //字体大小
m_font.CreateFont(nHeight, , , , ,
FALSE, FALSE, , ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_SWISS, "Arial"); pFontOld = pDC->SelectObject(&m_font);
pDC->SetBkMode(TRANSPARENT);
for(int i=; i<=m_nTicks; i++)
{
dtempangle = m_nStartAngleDeg-i*m_nSubTicks*dstepTickDeg;
strtemp.Format("%.*lf", m_nScaleDecimals, (m_dMinValue+(m_dMaxValue-m_dMinValue)*i/m_nTicks)); if(dtempangle>)
{
pDC->SetTextAlign(TA_BOTTOM|TA_LEFT);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/, strtemp);
} else if(dtempangle>)
{
pDC->SetTextAlign(TA_BASELINE|TA_LEFT);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/, strtemp);
}
else if(dtempangle>)
{
pDC->SetTextAlign(TA_BASELINE|TA_LEFT);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/, strtemp);
}
else if(dtempangle>)
{
pDC->SetTextAlign(TA_TOP|TA_LEFT);
pDC->TextOut(pointInner[m_nSubTicks*i].x-nHeight/, pointInner[m_nSubTicks*i].y-nHeight/, strtemp);
} else if(dtempangle>)
{
pDC->SetTextAlign(TA_TOP|TA_CENTER);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y, strtemp);
}
else if(dtempangle>)
{
pDC->SetTextAlign(TA_BOTTOM|TA_RIGHT);
pDC->TextOut(pointInner[m_nSubTicks*i].x+nHeight/, pointInner[m_nSubTicks*i].y+nHeight, strtemp);
}
else if(dtempangle>)
{
pDC->SetTextAlign(TA_RIGHT|TA_BASELINE);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/, strtemp);
}
else if(dtempangle>-)
{
pDC->SetTextAlign(TA_RIGHT|TA_BASELINE);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/, strtemp);
}
else
{
pDC->SetTextAlign(TA_RIGHT|TA_BOTTOM);
pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/, strtemp);
}
}
pDC->SelectObject(pFontOld); } void CMeter::ReconstructControl()
{
if ((m_pBitmapOldBackground) &&
(m_bitmapBackground.GetSafeHandle()) &&
(m_dcBackground.GetSafeHdc()))
{
m_dcBackground.SelectObject(m_pBitmapOldBackground);
m_dcBackground.DeleteDC() ;
m_bitmapBackground.DeleteObject();
} Invalidate ();
} void CMeter::OnSize(UINT nType, int cx, int cy)
{
CStatic::OnSize(nType, cx, cy); // TODO: Add your message handler code here
ReconstructControl() ;
} void CMeter::DrawNeedle(CDC *pDC)
{
int nResult;
double dRadPerDeg = 4.0*atan(1.0)/180.0;
double dAngleDeg;
double dAngleRad ;
double dTemp ;
CBrush brushFill, *pBrushOld ;
CPen penDraw, *pPenOld ;
CPoint pointNeedle[] ; // 指针由四边形组成 // 计算角度并限定指针走的角度
dAngleDeg = m_nStartAngleDeg-(360.0+m_nStartAngleDeg-m_nEndAngleDeg)
*(m_dCurrentValue-m_dMinValue)/(m_dMaxValue-m_dMinValue);
dAngleDeg = min(dAngleDeg, m_nStartAngleDeg);
dAngleDeg = max(dAngleDeg, m_nEndAngleDeg-360.0);
dAngleRad = dAngleDeg*dRadPerDeg; // 计算三角形底边两个点
pointNeedle[].x = m_ptMeterCenter.x - (int)(m_nCenterRadius**sin(dAngleRad)/);
pointNeedle[].y = m_ptMeterCenter.y - (int)(m_nCenterRadius**cos(dAngleRad)/);
pointNeedle[].x = m_ptMeterCenter.x + (int)(m_nCenterRadius**sin(dAngleRad)/);
pointNeedle[].y = m_ptMeterCenter.y + (int)(m_nCenterRadius**cos(dAngleRad)/); // 计算指针顶部坐标
dTemp = m_ptMeterCenter.x + m_nRadiusFrame*cos(dAngleRad)*/;
pointNeedle[].x = ROUND(dTemp);
dTemp = m_ptMeterCenter.y - m_nRadiusFrame*sin(dAngleRad)*/;
pointNeedle[].y = ROUND(dTemp);
// 计算指针尾部坐标
dTemp = m_ptMeterCenter.x - m_nRadiusFrame*cos(dAngleRad)/;
pointNeedle[].x = ROUND(dTemp);
dTemp = m_ptMeterCenter.y + m_nRadiusFrame*sin(dAngleRad)/;
pointNeedle[].y = ROUND(dTemp); pDC->SelectClipRgn(&m_rgnBoundary); brushFill.CreateSolidBrush(m_colorNeedle);
penDraw.CreatePen(PS_SOLID, , m_colorNeedle); pPenOld = pDC->SelectObject(&penDraw) ;
pBrushOld = pDC->SelectObject(&brushFill) ; // 绘制指针
pDC->Polygon(pointNeedle, ); nResult = pDC->SelectClipRgn(NULL); pDC->SelectObject(pPenOld);
pDC->SelectObject(pBrushOld); // 立体感处理
if(dAngleDeg>)
{
penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , m_colorShadow);
pPenOld = pDC->SelectObject(&penDraw);
pDC->MoveTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->SelectObject(pPenOld); penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , m_colorHighlight);
pPenOld = pDC->SelectObject(&penDraw);
pDC->MoveTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->SelectObject(pPenOld);
}
else
{
penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , m_colorShadow);
pPenOld = pDC->SelectObject(&penDraw);
pDC->MoveTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->SelectObject(pPenOld); penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , m_colorHighlight);
pPenOld = pDC->SelectObject(&penDraw);
pDC->MoveTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->LineTo(pointNeedle[]);
pDC->SelectObject(pPenOld);
}
} void CMeter::UpdateNeedle(double dValue)
{
m_dCurrentValue = dValue;
Invalidate();
} void CMeter::SetNeedleColor(COLORREF colorNeedle)
{
m_colorNeedle = colorNeedle ;
ReconstructControl() ;
} void CMeter::SetRange(double dMin, double dMax)
{
m_dMaxValue = dMax ;
m_dMinValue = dMin ;
ReconstructControl() ;
} void CMeter::SetScaleDecimals(int nDecimals)
{
m_nScaleDecimals = nDecimals ;
ReconstructControl() ;
} void CMeter::SetUnits(CString &strUnits)
{
m_strUnits = strUnits ;
ReconstructControl() ;
} void CMeter::SetValueDecimals(int nDecimals)
{
m_nValueDecimals = nDecimals ;
ReconstructControl() ;
} void CMeter::DrawNode(CDC *pDC)
{
CPen penDraw, *pPenOld;
COLORREF cEdge, cMiddle, cNode;
cMiddle = RGB(, , );
cEdge = RGB(, , );
for(int i=m_nCenterRadius*/; i>=; i--)
{
cNode = RGB((GetRValue(cEdge)-GetRValue(cMiddle))*((float)i)*/(*m_nCenterRadius)+GetRValue(cMiddle),
(GetGValue(cEdge)-GetGValue(cMiddle))*((float)i)*/(*m_nCenterRadius)+GetGValue(cMiddle),
(GetBValue(cEdge)-GetBValue(cMiddle))*((float)i)*/(*m_nCenterRadius)+GetBValue(cMiddle)); penDraw.DeleteObject();
penDraw.CreatePen(PS_SOLID, , cNode);
pPenOld = pDC->SelectObject(&penDraw);
pDC->Arc(m_ptMeterCenter.x-i, m_ptMeterCenter.y-i,m_ptMeterCenter.x+i,m_ptMeterCenter.y+i,
m_ptMeterCenter.x-i,m_ptMeterCenter.y,m_ptMeterCenter.x-i,m_ptMeterCenter.y);
pDC->SelectObject(pPenOld);
}
} void CMeter::SetColorTick(BOOL bColorTick)
{
m_bColorTick = bColorTick;
ReconstructControl();
} void CMeter::DrawValue(CDC *pDC)
{
int nHeight;
CPoint pttemp;
CString strtemp;
CFont *pFontOld; // 数值显示
nHeight = m_nRadiusFrame/;
pttemp = m_rectValue.CenterPoint();
strtemp.Format("%.*lf", m_nValueDecimals, m_dCurrentValue);
m_font.DeleteObject() ;
m_font.CreateFont (nHeight, , , , ,
FALSE, FALSE, , ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_SWISS, "Arial") ;
pFontOld = pDC->SelectObject(&m_font);
pDC->SetBkColor(m_colorButton);
pDC->SetTextAlign(TA_TOP|TA_CENTER);
pDC->TextOut(pttemp.x, pttemp.y, m_strUnits);
pDC->TextOut(pttemp.x, pttemp.y+nHeight, strtemp);
// 恢复字体和背景色
pDC->SelectObject(pFontOld);
pDC->SetBkColor(m_colorWindow);
} void CMeter::SetTicks(int nTicks)
{
m_nTicks = nTicks;
ReconstructControl();
} void CMeter::SetSubTicks(int nSubTicks)
{
m_nSubTicks = nSubTicks;
ReconstructControl();
} void CMeter::SetAngleRange(int nStartAngleDeg, int nEndAngleDeg)
{
m_nStartAngleDeg = nStartAngleDeg;
m_nEndAngleDeg = nEndAngleDeg;
ReconstructControl();
}

MemDCEx.h

 #ifndef _MEMDC_H_
#define _MEMDC_H_ //////////////////////////////////////////////////
// CMemDC - memory DC
//
// Author: Keith Rule
// Email: keithr@europa.com
// Copyright 1996-1999, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// History - 10/3/97 Fixed scrolling bug.
// Added print support. - KR
//
// 11/3/99 Fixed most common complaint. Added
// background color fill. - KR
//
// 11/3/99 Added support for mapping modes other than
// MM_TEXT as suggested by Lee Sang Hun. - KR
//
// Modified by Mark Malburg March 12, 1998
// Email: mcmalburg@sytech.cummins.com
// (added new construction and clipboard handling)
//
// Construction :
// |
// | CMemDC pDC (dc, &drawRect, toMemDC) ;
// |
// | where:
// | "dc" - pointer to the CDC that is an argument to OnDraw
// | "drawRect" - pointer to the rectangle to draw in
// | "boolToMemory" - TRUE: to the client, FALSE: to clipboard or printer
// |
//
// This class implements a memory Device Context which allows
// flicker free drawing. class CMemDCEx : public CDC
{
private:
CBitmap m_bitmap; // Offscreen bitmap
CBitmap* m_oldBitmap; // bitmap originally found in CMemDC
CDC* m_pDC; // Saves CDC passed in constructor
CRect m_rect; // Rectangle of drawing area.
BOOL m_bMemDC; // TRUE if CDC really is a Memory DC.
public: CMemDCEx(CDC* pDC, const CRect* pRect = NULL, bool boolToMemory = TRUE) : CDC()
{
ASSERT(pDC != NULL); // Some initialization
m_pDC = pDC;
m_oldBitmap = NULL;
if (boolToMemory)
m_bMemDC = !pDC->IsPrinting();
else
m_bMemDC = FALSE ; // Get the rectangle to draw
if (pRect == NULL)
{
pDC->GetClipBox(&m_rect);
}
else
{
m_rect = *pRect;
} if (m_bMemDC)
{
// Create a Memory DC
CreateCompatibleDC(pDC);
pDC->LPtoDP(&m_rect); m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_oldBitmap = SelectObject(&m_bitmap); SetMapMode(pDC->GetMapMode());
pDC->DPtoLP(&m_rect);
SetWindowOrg(m_rect.left, m_rect.top);
}
else
{
// Make a copy of the relevent parts of the current DC for printing
if (pDC->IsPrinting())
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
} // Fill background
FillSolidRect(m_rect, pDC->GetBkColor());
} ~CMemDCEx()
{
if (m_bMemDC)
{
// Copy the offscreen bitmap onto the screen.
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY); //Swap back the original bitmap.
SelectObject(m_oldBitmap);
}
else
{
// All we need to do is replace the DC with an illegal value,
// this keeps us from accidently deleting the handles associated with
// the CDC that was passed to the constructor.
m_hDC = m_hAttribDC = NULL;
}
} // Allow usage as a pointer
CMemDCEx* operator->()
{
return this;
} // Allow usage as a pointer
operator CMemDCEx*()
{
return this;
}
}; #endif

完整工程下载:https://download.csdn.net/download/qq_23565865/10715458

C++制作电压表电流表仪表盘(vs2008)的更多相关文章

  1. excel仪表盘制作,商业智能仪表盘的作用

    ​商业仪表盘被称为管理驾驶舱的重要组成部分,无论是管理决策者,还是企业业务流程中的普通员工,都可以利用它来展示分析的结果,让决策更加快速准确,更快地推动业务流程的进展,提高工作效率. 一个明确地了解自 ...

  2. 阿里云数加平台——BI报表使用概述和总结

    先声明一点,本人写此文章初衷只为对前段时间的工作做些总结,并做个记录,以备日后查用,此外也顺便与他人分享一下.当然间接上也为阿里云的大数据平台做了个免费广告.以下开始正文. 首先进入数加服务的控制面板 ...

  3. SCM白色幼儿系列(十二) Proteus仿真软件简介

    Proteus软件是英国Labcenter electronics公司出版的EDA工具软件.经常使用于单片机等数字电路仿真,分为ISIS和ARES两个程序,前者用于仿真,后者用于设计PCB.我们常使用 ...

  4. ElasticStack的入门学习

    Beats,Logstash负责数据收集与处理.相当于ETL(Extract Transform Load).Elasticsearch负责数据存储.查询.分析.Kibana负责数据探索与可视化分析. ...

  5. Cognos软件介绍文档(原创)

    1. Cognos简介 Cognos是世界上最大的业务智能软件制造商,它能够帮助用户提取公司数据,然后分析并汇总得出报告.Cognos有许多产品,但最为著名的还是它的PowerPlay联机分析处理(o ...

  6. 一个支持数据绑定与数据联动的Dashboard

    什么是仪表盘 仪表盘是不同部件的组合,可以在一个页面集中显示各类信息,方便用户集中查看信息.并快速处理业务 关于制作部件,请参见:制作部件 CabloyJS仪表盘的特点 更灵活的自适应能力,可以针对m ...

  7. VS2008+GDI实现多幅图像的GIF动画制作

    相信很多朋友和我一样,经常由于这或那的原因,需制作一些特定格式的图像.如开发过程中需要给菜单.工具条及按钮等添加对应的图形标识,通过代码或资源导入方式加载这些图像时往往会有较高的格式要求. 比如,为按 ...

  8. 有关VS2008制作安装包时遇到的问题详解

    公司最近要做一个安装包,然而在做的时候遇到好多问题,这里我一一记录下来 一.先用VS2008建一个Setup项目,添加你需要打包的文件,这里我就不具体介绍了,网上一搜都好多,这时我们一般都需要在安装前 ...

  9. 在vs2008工程中制作cab包

    内容转自MSDN 1.首先,制作自己的智能设备工程 2.添加cab工程: 为解决方案添加智能设备 CAB 项目 打开现有的智能设备项目,并确保“解决方案资源管理器”可见. 在“文件”菜单上指向“添加” ...

随机推荐

  1. android假设给TextView或EditText的email链接加下划线,并在点击在email连接上能够弹框显示

    怎样把textview的一些文字加上背景色: Spannable str = new SpannableString("#fdsfdfsdfdsfd#"); Matcher mat ...

  2. python 基础及资料汇总

    Python 包.模块.类以及代码文件和目录的一种管理方案     Numpy 小结   用 Python 3 的 async / await 做异步编程  K-means 在 Python 中的实现 ...

  3. 【BZOJ3291】Alice与能源计划 二分图最大匹配

    [BZOJ3291]Alice与能源计划 Description 在梦境中,Alice来到了火星.不知为何,转眼间Alice被任命为火星能源部长,并立刻面临着一个严峻的考验. 为了方便,我们可以将火星 ...

  4. ubuntu 安装 pygame 很好玩的东西

    1. 简介 pygame 是基于对 SDL库的python 封装,提供python接口.SDL(Simple DirectMedia Layer) 是一个跨平台的游戏开发库,方便游戏开发和移植.目前最 ...

  5. MongoDB C#驱动:

    MongoDB C#驱动: http://xiaosheng.me/2016/09/15/article24 http://www.cnblogs.com/wuhuacong/p/5098348.ht ...

  6. 一些重要的地址:md5在线解密破解

    md5在线解密破解:https://www.cmd5.com/

  7. 宿舍更换的新淋浴喷头"水温vs旋钮角度"关系的研究(曲线)

    版权声明:我极少创造新知识,大部分情况下是个知识的二道贩子 https://blog.csdn.net/stereohomology/article/details/24478825 应该非常一目了然 ...

  8. SAP-财务会计

    [转自 http://blog.itpub.net/195776/viewspace-1023913/] 一.FI组织架构1主数据1.1总帐科目1.2帐户组.1.3统驭科目1.4 总帐未清项管理2 凭 ...

  9. 应用索引技术优化SQL 语句(转)

    原文出处 一.前言 很多数据库系统性能不理想是因为系统没有经过整体优化,存在大量性能低下的SQL 语句.这类SQL语句性能不好的首要原因是缺乏高效的索引.没有索引除了导致语句本身运行速度慢外,更是导致 ...

  10. 使用Spring AOP实现MySQL数据库读写分离案例分析

    一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...