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.****.net/download/qq_23565865/10715458