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. java 面试总结

    1.static变量与实体变量的差别? static是静态变量,static能够通过类名直接訪问 内存方面的不同:static在定义的时候jvm就会分配空间, 而实体变量仅仅有在创建对象的时候才会去分 ...

  2. Using ADO.NET Data Service

    ADO.NET Data Service是随同Visual Studio 2008 SP1提供的用于构建在数据对象模型 (如EF-DEMX, LINQ-DBML) 之时来快速提供企业网内外的轻量级数据 ...

  3. ASP.NET动态网站制作(0)

    前言:一直想系统地学习一下网站建设的相关内容,看过相关的书籍,也跟着视频学过,但总觉得效率不高,学过的东西印象不深刻,或许还是自己动手实践的少.无意中免费听了一堂讲ASP.NET网站建设的课,觉得性价 ...

  4. Devexpress Spreadsheet 中文教程

    http://blog.csdn.net/hotmee/article/details/50554381

  5. <转> Struct 和 Union区别 以及 对内存对齐方式的说明

    转载地址:http://blog.csdn.net/firefly_2002/article/details/7954458 一.Struct 和 Union有下列区别: 1.在存储多个成员信息时,编 ...

  6. 从symbol link和hard link 到 unlink函数的一点记录

    之前一直对Linux的文件类型中的 “l” 类型的了解不是很深入,最近经过“圣经”指点,略知一二,在此先记录一下,以便以后查阅,之后会对文件和目录.文件I/O这部分再扩充. 首先需明确,Unix在查阅 ...

  7. EasyPlayer Android安卓RTSP服务器低延时再优化策略

    EasyPlayer低延迟再优化策略 EasyPlayer是一款专门针对RTSP协议进行过优化的播放器.其中两个我们引以为傲的的优点就是起播快和低延迟.最近我们遇到一些需求,其对延迟要求非常苛刻,于是 ...

  8. input file 选择Excel

    说明:开发环境 vs2012 asp.net mvc4 c# ,使用file 选择Excel文件 传到后台 使用Aspose.Cells获取Excel sheet页的名称 1.HTML代码 <% ...

  9. rails debug

    =debug @thesis config下配置 东西需要重启之后才管用

  10. JDBC超时原理与设置

    抄录自网上,因为担心以后找不到,因此抄录之.感谢分享的大神! 英文原版:http://www.cubrid.org/blog/dev-platform/understanding-jdbc-inter ...