?? panelmeter.cpp
字號:
/***********************************************************************
* Copyright (c) 2007* All rights reserved.*
* ATTRIBUTE: 一個儀表控件類,用來仿真工業(yè)控制現(xiàn)場儀表數(shù)據(jù)顯示等
* FILE NAME: PanelMeter.cpp
* FILE ID: SYSTEMCTRL-PANELMETER-CPP
* ABSTRACT: 可用于工業(yè)控制仿真儀表數(shù)據(jù)顯示等
* CURRENT VERSION: V1.0
* AUTHOR: 戚高
* CONTECT: successq_g@163.com
* BUILD DATA: 27/12/2007
* COMPLETION DATE: 27/12/2007
* PRE-VERSION: NONE
* PRE-AUTHOR: NONE
* PRE-COMPLETION DATE:
* NOTE: 未經(jīng)授權請不要作為商業(yè)用途,或者如果您要作為商業(yè)
用途,請聯(lián)系作者
***********************************************************************/
#include "stdafx.h"
#include "PanelMeter.h"
#include <math.h>
#include "MemDC.h"
CPanelMeter::CPanelMeter()
{
m_BackColor = RGB( 33, 177, 138);
m_dMinValue = 0;
m_dMaxValue = 100;
m_dInterval = 20;
m_dValidValueMin = 30;
m_dValidValueMax = 75;
m_dCurrentValue = 55.00f;
memset(m_strUnits, 0, sizeof(m_strUnits));
strcpy(m_strUnits, "溫度"); //表單位
}
CPanelMeter::~CPanelMeter()
{
}
BEGIN_MESSAGE_MAP(CPanelMeter, CStatic)
//{{AFX_MSG_MAP(CPanelMeter)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPanelMeter message handlers
void CPanelMeter::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
SendMessage(WM_SIZE);
CRect rect;
GetClientRect(&rect);
ClientToScreen(&rect);
rect.bottom = rect.top + rect.Height() / 2 + 4;
MoveWindow(&rect, TRUE);
}
void CPanelMeter::SetCurrentValue(const double dCurrentValue)
{
m_dCurrentValue = dCurrentValue;
Invalidate();
}
void CPanelMeter::SetValidValue(const double dMin, const double dMax)
{
m_dValidValueMin = dMin;
m_dValidValueMax = dMax;
ReconstructControl();
}
void CPanelMeter::SetRange(const double dMin, const double dMax, const double dInterval)
{
m_dMinValue = dMin;
m_dMaxValue = dMax;
m_dInterval = dInterval;
ReconstructControl();
}
void CPanelMeter::SetUnits(const char *strUnits)
{
strcpy(m_strUnits, strUnits);
ReconstructControl();
}
//重新更新背景
void CPanelMeter::ReconstructControl()
{
if (m_pbitmapOldMeterPlate &&
m_bitmapMeterPlate.GetSafeHandle() &&
m_dcMeterPlate.GetSafeHdc())
{
m_dcMeterPlate.SelectObject(m_pbitmapOldMeterPlate);
m_dcMeterPlate.DeleteDC() ;
m_bitmapMeterPlate.DeleteObject();
}
Invalidate ();
}
void CPanelMeter::OnPaint()
{
CPaintDC dc(this);
// 獲得控件區(qū)域
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);
DrawValue(&memDC, m_rectCtrl);
DrawNeedle(&memDC, m_rectCtrl);
}
BOOL CPanelMeter::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
//繪制儀表背景
void CPanelMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
CBrush m_brushBack, pBackBrush, *pOldBrush;
pDC->SetBkColor(m_BackColor);
m_brushBack.CreateSolidBrush(m_BackColor);
pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);
pDC->FillRect(rect, &m_brushBack); //繪制背景
pDC->Rectangle(rect); //繪制一個邊框
pDC->SelectObject(pOldBrush);
m_brushBack.DeleteObject();
int yHalf = rect.bottom - 8;
float fa = (float)rect.Width() / 2;
float fb = (float)rect.Height() - 8;
CFont fScaleFont;
fScaleFont.CreateFont(10, 12,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
"Arial");
if (m_dValidValueMin >= 0)
{
CBrush brshGreen;
CBrush brshRed;
brshGreen.CreateSolidBrush(RGB(0, 192, 0));
brshRed.CreateSolidBrush(RGB(230, 100, 100));
float fStartAngle = (float)(m_dValidValueMin - m_dMinValue) / (float)(m_dMaxValue - m_dMinValue) * 3.14f;
float fEndAngle = (float)(m_dValidValueMax - m_dMinValue) / (float)(m_dMaxValue - m_dMinValue) * 3.14f;
pDC->MoveTo(rect.left, yHalf);
pDC->LineTo(rect.left + 20, yHalf);
pDC->MoveTo(rect.right - 1, yHalf);
pDC->LineTo(rect.right - 22, yHalf);
pDC->MoveTo(rect.left, yHalf);
for (float f = 0; f <= 3.14; f += 0.01f)
{
pDC->LineTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top);
}
pDC->MoveTo(rect.left + 20, yHalf);
for (f = 0; f <= 3.14; f += 0.01f)
{
pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(f)) + rect.left, yHalf - (int)((fb - 20) * sin(f)) + rect.top);
}
CBrush *pOldBrush = pDC->SelectObject(&brshRed);
pDC->FloodFill(rect.left + 10, yHalf - 10, RGB(0, 0, 0));
fStartAngle *= 100;
fStartAngle = (float)((int)fStartAngle) / 100;
fEndAngle *= 100;
fEndAngle = (float)((int)fEndAngle) / 100;
pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(fStartAngle)) + rect.left, yHalf - (int)(fb * sin(fStartAngle)) + rect.top);
pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(fStartAngle)) + rect.left, yHalf - (int)((fb - 20) * sin(fStartAngle)) + rect.top);
pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(fEndAngle)) + rect.left, yHalf - (int)(fb * sin(fEndAngle)) + rect.top);
pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(fEndAngle)) + rect.left, yHalf - (int)((fb - 20) * sin(fEndAngle)) + rect.top);
pDC->SelectObject(brshGreen);
if (fStartAngle > 0 && fEndAngle < 3.14)
{
pDC->FloodFill(rect.Width() / 2 - (int)((fa - 5) * cos((fStartAngle + fEndAngle) / 2)) + rect.left, yHalf - (int)((fb - 5) * sin((fStartAngle + fEndAngle) / 2)) + rect.top, RGB(0,0,0));
}
pDC->SelectObject(pOldBrush);
}
CPen pen;
pen.CreatePen(PS_SOLID, 3, RGB(255,255,255));
CPen *pOldPen = pDC->SelectObject(&pen);
CFont *pOldFont = pDC->SelectObject(&fScaleFont);
pDC->SetBkMode(TRANSPARENT);
fa -= 10;
fb -= 10;
pDC->MoveTo(rect.left + 10, yHalf);
for (float f = 0; f <= 3.14; f += 0.01f)
{
pDC->LineTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top);
}
float fBigStep = 3.14f / ((float)(m_dMaxValue - m_dMinValue) / (float)m_dInterval) / 4;
int nDiv = 0;
int nScale = (int)m_dMinValue;
for (f = 0; f <= 3.15; f += fBigStep)
{
pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top);
if (nDiv == 0)
{
pDC->LineTo(rect.Width() / 2 - (int)((fa - 15) * cos(f)) + rect.left, yHalf - (int)((fb - 15) * sin(f)) + rect.top);
CString str;
str.Format("%d", nScale);
nScale += (int)m_dInterval;
CSize size = pDC->GetOutputTextExtent(str);
pDC->SetTextColor(RGB(0,0,0));
pDC->TextOut(rect.Width() / 2 - (int)((fa - 33) * cos(f)) + rect.left - size.cx / 2 + 1, yHalf - (int)((fb - 33) * sin(f)) + rect.top - size.cy / 2 + 1, str);
pDC->SetTextColor(RGB(255, 255, 255));
pDC->TextOut(rect.Width() / 2 - (int)((fa - 33) * cos(f)) + rect.left - size.cx / 2, yHalf - (int)((fb - 33) * sin(f)) + rect.top - size.cy / 2, str);
nDiv++;
}
else
{
pDC->LineTo(rect.Width() / 2 - (int)((fa - 10) * cos(f)) + rect.left, yHalf - (int)((fb - 10) * sin(f)) + rect.top);
nDiv++;
if (nDiv == 4)
{
nDiv = 0;
}
}
}
pDC->SelectObject(pOldFont);
fScaleFont.DeleteObject();
CPoint m_ptMeterCenter;
m_ptMeterCenter.x = rect.left + rect.Width() / 2;
m_ptMeterCenter.y = rect.bottom;
int nRadiusFrame = rect.Height();
CFont pUnitFont;
LOGFONT lf;
lf.lfEscapement = 0;
lf.lfItalic = NULL;
lf.lfUnderline = NULL;
lf.lfStrikeOut = NULL;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = nRadiusFrame / 4;
strcpy(lf.lfFaceName, "隸書");
pUnitFont.CreateFontIndirect(&lf);
pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(0, 0, 0));
CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
int(m_ptMeterCenter.y - nRadiusFrame * 0.70f + 2),
int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
int(m_ptMeterCenter.y - nRadiusFrame * 0.20f + 2));
pDC->DrawText(m_strUnits, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
pDC->SetTextColor(RGB( 255, 255, 255));
rectUnits.SetRect(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f),
int(m_ptMeterCenter.y - nRadiusFrame * 0.70f),
int(m_ptMeterCenter.x + nRadiusFrame * 0.30f),
int(m_ptMeterCenter.y - nRadiusFrame * 0.20f));
pDC->DrawText(m_strUnits, rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldFont);
pUnitFont.DeleteObject();
}
void CPanelMeter::DrawNeedle(CDC *pDC, CRect &rect)
{
if (m_dCurrentValue > m_dMaxValue)
{
m_dCurrentValue = m_dMaxValue;
}
else if (m_dCurrentValue < m_dMinValue)
{
m_dCurrentValue = m_dMinValue;
}
double dAngle = (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue) * 3.14f;
float fa = (float)rect.Width() / 2;
float fb = (float)rect.Height() - 8;
CBrush brshWhite;
CBrush brshShadow;
brshWhite.CreateSolidBrush(RGB(255, 255, 255));
brshShadow.CreateSolidBrush(RGB(0, 0, 0));
CBrush *pOldBrush = pDC->SelectObject(&brshShadow);
pDC->Ellipse(rect.Width() / 2 - 9 + rect.left, rect.Height() - 20 + rect.top, rect.Width() / 2 + 11 + rect.left, rect.Height() + rect.top);
pDC->SelectObject(&brshWhite);
pDC->Ellipse(rect.Width() / 2 - 10 + rect.left, rect.Height() - 21 + rect.top, rect.Width() / 2 + 10 + rect.left, rect.Height() - 1 + rect.top);
pDC->SelectObject(pOldBrush);
CPen penThick;
CPen penThin;
CPen penShadow;
penThick.CreatePen(PS_SOLID, 5, RGB(255, 100, 50));
penThin.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
penShadow.CreatePen(PS_SOLID, 5, RGB(0, 0, 0));
CPen *pOldPen = pDC->SelectObject(&penShadow);
pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left + 1, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top + 1);
pDC->LineTo(rect.Width() / 2 + rect.left + 1, rect.Height() - 11 + rect.top + 1);
pDC->SelectObject(&penThick);
pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top);
pDC->LineTo(rect.Width() / 2 + rect.left, rect.Height() - 11 + rect.top);
pDC->SelectObject(&penThin);
pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top);
pDC->LineTo(rect.Width() / 2 + rect.left, rect.Height() - 11 + rect.top);
pDC->SelectObject(pOldPen);
}
void CPanelMeter::DrawValue(CDC *pDC, CRect &rect)
{
char strCurrentValue[10];
memset(strCurrentValue, 0, sizeof(strCurrentValue));
sprintf(strCurrentValue, "%.2f", m_dCurrentValue);
CPoint m_ptMeterCenter;
m_ptMeterCenter.x = rect.left + rect.Width() / 2;
m_ptMeterCenter.y = rect.bottom;
int nRadiusFrame = rect.Height();
CFont pUnitFont, *pOldFont;
LOGFONT lf;
lf.lfEscapement = 0;
lf.lfItalic = NULL;
lf.lfUnderline = NULL;
lf.lfStrikeOut = NULL;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = nRadiusFrame / 6;
strcpy(lf.lfFaceName, "Arial");
pUnitFont.CreateFontIndirect(&lf);
pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(0, 0, 0));
CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
int(m_ptMeterCenter.y - nRadiusFrame * 0.40f + 2),
int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
int(m_ptMeterCenter.y - nRadiusFrame * 0.10f + 2));
pDC->DrawText(strCurrentValue, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
pDC->SetTextColor(RGB( 255, 255, 255));
rectUnits.SetRect(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f),
int(m_ptMeterCenter.y - nRadiusFrame * 0.40f),
int(m_ptMeterCenter.x + nRadiusFrame * 0.30f),
int(m_ptMeterCenter.y - nRadiusFrame * 0.10f));
pDC->DrawText(strCurrentValue, rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
pDC->SelectObject(pOldFont);
pUnitFont.DeleteObject();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -