📄 pointerdevice.cpp
字号:
/////////////////////////////////////////////////////////
// 指针式测量设备PointerDevice封装类
// 版本:1.08
// 最后修改日期:2002.1.25
/////////////////////////////////////////////////////////
// PointerDevice.cpp : implementation file
//
#include "stdafx.h"
#include "PointerDevice.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// PointerDevice
/////////////////////////////////////////////////////////////////////////////////////////
//函数名:PointerDevice(CWnd *parent)
//输入参数:父窗口的指针
//返回值:无
//作用:为PointerDevice类的构造函数,将类的内部变量设置成默认值,创建类的实例并显示子窗体
PointerDevice::PointerDevice(CWnd *parent)
{
PD_Width = 200; //仪表默认宽度
PD_Height = 200; //仪表默认高度
//设置仪表的原点为窗体的中心
PD_Origin.x = (long)((PD_Width - 1) / 2);
PD_Origin.y = (long)((PD_Height - 1) / 2);
PD_Direction = 1; //默认为逆时针转动,该变量表示正方向
PD_CurrentDirection = 1;//默认方向和正向一样
PD_UseBitmap = 0; //默认下仪表不使用位图作为背景。
PD_BitmapID = 0; //仪表背景位图的资源ID,默认下不使用
PD_CenterAngle = 90; //设置表盘的弧度中心默认位置为Y轴(90度)方向
PD_SweepAngle = 360; //设置表盘弧度的默认跨度为360度
PD_FaceSweepAngle = 360;//设置表盘面板弧度跨度
PD_TextStartAngle = 0; //刻度文字的起始位置默认为弧度中心位置
PD_SmallGridLength = 4; //设置表盘小刻度线长度
PD_SmallGridNum = 50; //设置表盘默认小刻度格数
PD_BigGridLength = 8; //设置表盘大刻度线长度为
PD_BigGridNum = 10; //设置表盘默认大刻度格数
PD_FontSize = 12; //刻度标注字体大小,默认采用12点字体
PD_OutputFontSize = 16; //输出框内文字大小,默认采用16点字体
PD_Title = ""; //标题文字(默认为空)
PD_TitleOffset.x = 0; //标题相对仪表窗口左上角的位置
PD_TitleOffset.y = 0;
PD_TitleColor = RGB(0, 0, 0); //默认的标题颜色
PD_TitleFontSize = 0; //标题栏字体大小(默认为0,表示不需要标题)
PD_TextSpace = 10; //默认文字与刻度线距离
PD_CenterNumber = 0; //默认刻度中心的数字为0
PD_DeltaNumber = 1; //默认刻度数字增量为1
PD_BorderWidth = 12; //圆形边界的宽度
PD_StepLength = 5; //指针默认的最小旋转量
PD_FaceRadius = (UINT)((PD_Width - 1) / 2) - PD_BorderWidth; //设置表盘弧度的默认半径为仪表边长的一半(扣除边界尺寸)
PD_Radius = PD_FaceRadius - 10; //默认情况下,让刻度显离开边缘10个象素
PD_InnerRadius = 0; //默认情况不加空心内圆
PD_AxleRadius = 0; //指针转轴的半径
PD_PointerWidth = 1; //默认表针为1象素粗
PD_PointerLength = PD_Radius - PD_BigGridLength - 1; //默认的指针长度
PD_HasPointerShadow = 0; //默认没有指针阴影
PD_PointerShadowColor = RGB(100, 100, 100); //默认的指针阴影颜色
PD_PointerShadowOffset.x = 3; //指针阴影相对于指针的偏移量
PD_PointerShadowOffset.y = 2;
PD_PointerColor = RGB(0, 255, 0); //默认仪表指针颜色为绿色
PD_AxleColor = RGB(150, 150, 150); //默认仪表指针的轴颜色
PD_BkColor = GetSysColor(COLOR_3DFACE); //默认仪表背景颜色和对话框背景颜色一致
PD_CalibrationColor = RGB(255, 255, 255); //默认仪表刻度颜色为白色
PD_FaceColor = RGB(0, 0, 0); //默认仪表表盘颜色为黑色
PD_TextColor = PD_CalibrationColor; //默认刻度文字和刻度线颜色相同
PD_BorderColor = RGB(150, 150, 150); //定义边界颜色为灰色
PD_Timer = 30; //仪表内部定时器的触发时间间隔,默认为40毫秒
PD_Status = PD_UPDATED; //仪表的默认状态设置成测试状态
PD_IsLoop = false; //默认情况下,仪表的指针不能循环转动
PD_RotateDir = false; //默认情况下,仪表的指针是逆时针转动
PD_CurrentAngle = 0; //默认情况下,仪表的指针和刻度弧的中线重合
PD_CurrentNumber = 0; //设置量程和当前示数
PD_MaxNumber = 10;
PD_MinNumber = 0;
PD_PointerSide.x = 3; //设置默认的指针形状
PD_PointerSide.y = 6;
PD_PointerTail = 10;
PD_OutputPos.x = 0; //设置默认的输出框位置
PD_OutputPos.y = - ((int)PD_Radius / 2) + 5;
PD_OutputWidth = (PD_Radius / 2); //设置默认的输出框大小
PD_OutputHeight = 20;
PD_OutputBkColor = RGB(0, 0, 55); //设置输出框的外观
PD_OutputBdColor = RGB(255, 255, 255);
PD_OutputTextColor = RGB(255, 255, 0);
PD_OutputTextPos.x = 0;
PD_OutputTextPos.y = PD_OutputPos.y - PD_OutputFontSize / 2;
PD_OutputAccuracy = 1; //默认输出框采用一位小数精度
PD_Accuracy = 1; //默认刻度文字用一位小数精度
PD_Style = PD_3DSTYLE; //默认采用3D边框
PD_Update(); //调用该函数对其他变量进行初始化
//创建相应的静态控件并且显示
CRect rect;
rect.left = rect.top = 0;
rect.bottom = PD_Height - 1;
rect.right = PD_Width - 1;
Create(NULL, WS_CHILD | WS_VISIBLE | SS_NOTIFY, rect, parent);
SetTimer(1, PD_Timer, NULL); //设置定时器
}
/////////////////////////////////////////////////////////////////////////////////////////
//函数名:~PointerDevice()
//输入参数:无
//返回值:无
//作用:析构函数
PointerDevice::~PointerDevice()
{
PD_Font.DeleteObject();
PD_OutputFont.DeleteObject();
KillTimer(1);
}
BEGIN_MESSAGE_MAP(PointerDevice, CStatic)
//{{AFX_MSG_MAP(PointerDevice)
ON_WM_PAINT()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// PointerDevice message handlers
/////////////////////////////////////////////////////////////////////////////////////////
//函数名:OnPaint()
//输入参数:无
//返回值:无
//作用:重载函数,绘制仪表盘的界面
void PointerDevice::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
DrawFace();
// Do not call CStatic::OnPaint() for painting messages
}
/////////////////////////////////////////////////////////////////////////////////////////
//函数名:OnPaint()
//输入参数:定时器事件的ID
//返回值:无
//作用:重载函数,处理定时器消息,完成指针某时刻的位置指定,更新界面显示
void PointerDevice::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch(PD_Status) //仪表将根据不同的状态作出反应
{
case PD_TEST: //测试状态,转动指针
PD_CurrentAngle += PD_StepLength * PD_CurrentDirection;
if(PD_IsLoop == false && (PD_CurrentAngle >= (PD_SweepAngle / 2) || PD_CurrentAngle <= - (PD_SweepAngle / 2)))
{
PD_CurrentDirection = - PD_CurrentDirection;
}
DrawFace(); //更新显示
break;
case PD_UPDATED: //等候状态,等待数据的变动
break;
case PD_UPDATING: //更新过程状态,指针尚未摆动到合适的位置
if(PD_CurrentAngle < PD_ObjectAngle) //当前角度小于目标角度
{
PD_CurrentAngle += PD_StepLength * PD_Direction;
if(PD_CurrentAngle > PD_ObjectAngle)
{
PD_CurrentAngle = PD_ObjectAngle;
PD_Status = PD_UPDATED;
}
}
else //当前角度大于目标角度
{
PD_CurrentAngle -= PD_StepLength * PD_Direction;
if(PD_CurrentAngle < PD_ObjectAngle)
{
PD_CurrentAngle = PD_ObjectAngle;
PD_Status = PD_UPDATED;
}
}
DrawFace(); //更新显示
break;
case PD_SHUTDOWN: //关闭状态,不作响应
break;
default:
break;
}
CStatic::OnTimer(nIDEvent);
}
/////////////////////////////////////////////////////////////////////////////////////////
//函数名:DrawFace()
//输入参数:无
//返回值:无
//作用:绘制整个仪表的界面
void PointerDevice::DrawFace()
{
CClientDC dc(this);
CDC dcmem;
BITMAP bmp;
CBitmap bmpc, *pbitmapold;
CPen pen, *ppenold;
CBrush brush0, brush, *pbrushold;
COLORREF temp_color;
int j;
if(PD_UseBitmap == 1) //使用位图背景
bmpc.LoadBitmap(PD_BitmapID);
else if(PD_UseBitmap == 2) //使用映射位图作为背景
bmpc.LoadMappedBitmap(PD_BitmapID);
else //不使用位图背景
bmpc.CreateCompatibleBitmap(&dc, PD_Width, PD_Height); //创建与系统兼容的位图
bmpc.GetBitmap(&bmp);
if(!PD_Font.m_hObject)
PD_Font.CreateFont(PD_FontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial")); //创建一个默认的刻度数字字体
if(!PD_OutputFont.m_hObject)
PD_OutputFont.CreateFont(PD_OutputFontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial")); //创建一个默认的刻度数字字体
if(!PD_TitleFont.m_hObject)
PD_TitleFont.CreateFont(PD_TitleFontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial")); //创建一个默认的刻度数字字体
dcmem.CreateCompatibleDC(&dc);
pbitmapold = (CBitmap *)dcmem.SelectObject(&bmpc);
if(PD_UseBitmap != 1 && PD_UseBitmap != 2) //如果不使用位图或者映射位图作为背景,就用矢量绘制整个面板
{
//绘制“透明”的位图底色
brush0.CreateSolidBrush(PD_BkColor);
CBrush * pbrushold = (CBrush *)dcmem.SelectObject(&brush0);
dcmem.SelectStockObject(NULL_PEN);
dcmem.Rectangle(0, 0, bmp.bmWidth + 1, bmp.bmHeight + 1);
dcmem.SelectObject(pbrushold);
//绘制3D圆形外框
temp_color = PD_BorderColor;
brush.CreateSolidBrush(PD_BorderColor);
pbrushold = (CBrush *)dcmem.SelectObject(&brush);
dcmem.Pie(PD_Origin.x - PD_FaceRadius - PD_BorderWidth, PD_Origin.y - PD_FaceRadius - PD_BorderWidth, PD_Origin.x + PD_FaceRadius + PD_BorderWidth, PD_Origin.y + PD_FaceRadius + PD_BorderWidth, PD_FaceStartPoint.x, PD_FaceStartPoint.y, PD_FaceEndPoint.x, PD_FaceEndPoint.y);
dcmem.SelectObject(pbrushold);
brush.DeleteObject();
if(PD_BorderWidth)
{
int halfbdw = (int)(PD_BorderWidth / 2);
for(j = 0; j < (int)PD_BorderWidth; j ++)
{
if(j >= halfbdw)
temp_color = GetNextColor(temp_color, 0.9);
else
temp_color = GetNextColor(temp_color, 1.1);
pen.CreatePen(PS_SOLID, 1, temp_color);
ppenold = (CPen *)dcmem.SelectObject(&pen);
dcmem.MoveTo(PD_FaceStartPoint);
dcmem.AngleArc(PD_Origin.x, PD_Origin.y, PD_FaceRadius + j, (float)(PD_RightAngle - (PD_FaceSweepAngle - PD_SweepAngle)/ 2), (float)PD_FaceSweepAngle); //绘制刻度弧
dcmem.SelectObject(ppenold);
pen.DeleteObject();
}
}
//绘制扇形(圆形)刻度盘
brush.CreateSolidBrush(PD_FaceColor);
pbrushold = (CBrush *)dcmem.SelectObject(&brush);
pen.CreatePen(PS_SOLID, 1, PD_FaceColor);
ppenold = (CPen *)dcmem.SelectObject(&pen);
dcmem.Pie(PD_Origin.x - PD_FaceRadius, PD_Origin.y - PD_FaceRadius, PD_Origin.x + PD_FaceRadius, PD_Origin.y + PD_FaceRadius, PD_FaceStartPoint.x, PD_FaceStartPoint.y, PD_FaceEndPoint.x, PD_FaceEndPoint.y);
dcmem.SelectObject(pbrushold);
brush.DeleteObject();
dcmem.SelectObject(ppenold);
pen.DeleteObject();
//绘制内圆
if(PD_InnerRadius)
{
pbrushold = (CBrush *)dcmem.SelectObject(&brush0);
dcmem.Ellipse(PD_Origin.x - PD_InnerRadius, PD_Origin.y - PD_InnerRadius, PD_Origin.x + PD_InnerRadius, PD_Origin.y + PD_InnerRadius);
dcmem.SelectObject(pbrushold);
}
brush0.DeleteObject();
}
pen.CreatePen(PS_SOLID, 1, PD_CalibrationColor);
ppenold = (CPen *)dcmem.SelectObject(&pen);
//绘制刻度弧线,这里先暂时不用
//dcmem.MoveTo(PD_StartPoint.x, PD_StartPoint.y);
//dcmem.AngleArc(PD_Origin.x, PD_Origin.y, PD_Radius, PD_RightAngle, PD_SweepAngle); //绘制刻度弧
//绘制大刻度分割线
UINT i;
UINT R1 = PD_Radius - PD_BigGridLength;
double delta = PD_SweepAngle / PD_BigGridNum;
double current_angle = PD_RightAngle;
CPoint in, out;
for(i = 0; i < PD_BigGridNum; i ++)
{
out.x = PD_Origin.x + (long)(PD_Radius * cos(ANG * current_angle));
out.y = PD_Origin.y - (long)(PD_Radius * sin(ANG * current_angle));
in.x = PD_Origin.x + (long)(R1 * cos(ANG * current_angle));
in.y = PD_Origin.y - (long)(R1 * sin(ANG * current_angle));
dcmem.MoveTo(in);
dcmem.LineTo(out);
current_angle += delta;
}
//绘制小刻度分割线
R1 = PD_Radius - PD_SmallGridLength;
delta = PD_SweepAngle / PD_SmallGridNum;
current_angle = PD_RightAngle;
int tmp = PD_SmallGridNum / PD_BigGridNum;
for(i = 0; i < PD_SmallGridNum; i ++)
{
if(i % tmp == 0)
{
current_angle += delta;
continue;
}
out.x = PD_Origin.x + (long)(PD_Radius * cos(ANG * current_angle));
out.y = PD_Origin.y - (long)(PD_Radius * sin(ANG * current_angle));
in.x = PD_Origin.x + (long)(R1 * cos(ANG * current_angle));
in.y = PD_Origin.y - (long)(R1 * sin(ANG * current_angle));
dcmem.MoveTo(in);
dcmem.LineTo(out);
current_angle += delta;
}
dcmem.SelectObject(ppenold);
pen.DeleteObject();
//写入刻度文字
R1 = PD_Radius - ((PD_BigGridLength > PD_SmallGridLength) ? PD_BigGridLength : PD_SmallGridLength);
CFont * pfontold = (CFont *)dcmem.SelectObject(&PD_Font);
int oldmode = dcmem.SetBkMode(TRANSPARENT);
COLORREF oldcolor = dcmem.SetTextColor(PD_TextColor);
CString text, format;
CPoint textpos;
double tmpnum;
current_angle = PD_TextStartAngle + PD_CenterAngle;
delta = PD_SweepAngle / PD_BigGridNum;
for(i = 0; i <= PD_BigGridNum; i ++)
{
textpos.x = PD_Origin.x + (long)((R1 - PD_TextSpace) * cos(ANG * current_angle));
textpos.y = PD_Origin.y - (long)((R1 - PD_TextSpace) * sin(ANG * current_angle));
tmpnum = PD_CenterNumber + i * PD_DeltaNumber;
if((int)tmpnum == tmpnum)
{
text.Format("%d", (int)tmpnum);
}
else
{
format.Format("%%.%dlf", PD_OutputAccuracy);
text.Format(format, tmpnum);
}
if(current_angle < 180 && current_angle > 0)
{
dcmem.SetTextAlign(TA_CENTER | TA_TOP);
dcmem.TextOut(textpos.x + 2, textpos.y - 5, text);
}
else
{
dcmem.SetTextAlign(TA_CENTER | TA_BOTTOM);
dcmem.TextOut(textpos.x + 2, textpos.y + 5, text);
}
current_angle += delta;
if(current_angle - PD_TextStartAngle - PD_CenterAngle >= 360)
break;
if(PD_SweepAngle < 360 && current_angle >= PD_LeftAngle)
break;
}
current_angle = PD_TextStartAngle + PD_CenterAngle;
if(PD_SweepAngle < 360) //对于非圆形的表盘,还要画出负数部分
{
for(i = 0; i <= PD_BigGridNum; i ++)
{
textpos.x = PD_Origin.x + (long)((R1 - PD_TextSpace) * cos(ANG * current_angle));
textpos.y = PD_Origin.y - (long)((R1 - PD_TextSpace) * sin(ANG * current_angle));
tmpnum = PD_CenterNumber - i * PD_DeltaNumber;
if((int)tmpnum == tmpnum)
{
text.Format("%d", (int)tmpnum);
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -