工控软件图形界面-控件实现(圆形仪表控件三)(zz)
介绍
在工业控制系统开发过程中,图形显示方面占有着很重要的作用。比起很多专用的组态软件,他们有着强大的在图形系统,能够组态出来非常漂亮的系统。现在的很多的工业图形开发包都需要支付费用,很多漂亮的控件比如仪表等只能看图兴叹了。前些天一个朋友做一个泵站的监控系统,由于缺少相关的控件,在研究了该类控件的编程方法上,借鉴网络上的一些编程资料,完成了一些可用于工业控制系统开发使用的控件。
正文
前面的两篇文章中我已经用实例介绍了如何利用双缓冲技术编写圆盘仪表的方法。具体见
工控软件图形界面-控件实现(圆形仪表控件) http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=1671
工控软件图形界面-控件实现(圆形仪表控件二) http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=1672
实际仪表的编写原理可以大致差不多,区别就是编写背景或者指针或者显示实时值的时候采用的不同方法而已。而在工业控制程序中,如果采用了多种不同的仿真仪表来实现现场的模拟,将会在人机接口方面更加的友好。这里继续在前面的基础上编写一种新型的仪表,并应用到工控现场的仪表。
我们还是按照编写的步骤,建立一个集成CStatic的仪表类。然后出发WM_PAINT等消息。然后在OnPaint中间完成仪表背景,仪表指针,仪表实时值的显示工作。在背景编写,指针和文字显示的时候,我们采用叠加的方法。图形叠加或者文字叠加方法其实很简单,在上篇文章已经有介绍,即是我们利用在相同的区域或者偏移量区域进行相同内容的绘制,绘制时候采用不同颜色,由于绘图的先后顺序,我们可以产生视觉上的立体叠加效果,具体实现见 工控软件图形界面-控件实现(圆形仪表控件二) http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=1672
相关核心代码如下:
绘制仪表背景
//绘制仪表背景
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();
}
至此,基本绘制工作完成,我们添加一些接口以便能在程序中进行程序参数的改变。
转载于:https://www.cnblogs.com/strinkbug/archive/2010/06/11/1756661.html
工控软件图形界面-控件实现(圆形仪表控件三)(zz)相关推荐
- python日历gui_python GUI库图形界面开发之PyQt5日期时间控件QDateTimeEdit详细使用方法与实例...
PyQt5日期时间控件QDateTimeEdit介绍 QDateTimeEdit是一个允许用户编辑日期时间的控件,可以使用键盘上的上下键头按钮来增加或减少日期的时间值,QDateTimeEdit通过s ...
- win10 使用Xming+Putty显示Linux下软件图形界面
在windows下使用Xming+Putty显示Linux下软件图形界面 转载 ############# 安装Xming 和 Putty: ############# Xming是一个在Micros ...
- Python上位机软件图形界面实战——PyQt
转载:https://blog.csdn.net/qq_25939803/article/details/97894219 文章目录 引言 1 环境配置 2 新建一个软件窗口 3 QtDesigner ...
- C# 第六章『交互式图形界面』◆第2节:控件(2)ListView
一.ListView 类 ListView 类 1.定义 命名空间:System.Windows.Forms 程序集:System.Windows.Forms.dll 表示 Windo ...
- C# 第六章『交互式图形界面』◆第2节:控件(1)
一.概述 在C#中,控件的基类是位于System.Windows.Forms命名空间下的Control类.Control类定义了控件类的共同属性.方法和事件,其他的控件类都直接或间接地派生自这个基类. ...
- 渗透测试快速稳定远控软件,2019-9-11:渗透测试,Kill远控软件,初接触
初步使用Kill远控软件,使win7靶机被远控 该文章仅供学习,利用方法来自网络文章,仅供参考 1,打开运行Kill,选择系统设置,设置监听端口,通讯密码,点击保存设置 2,点击服务生成,上线参数,设 ...
- 在 windows 下使用 Xming+Putty 显示 Linux 下软件图形界面
From: http://www.blogjava.net/ivanwan/archive/2012/04/26/376670.html From: http://www.bubuko.com/inf ...
- 在windows下使用Xming+Putty显示Linux下软件图形界面
From: http://www.blogjava.net/ivanwan/archive/2012/04/26/376670.html From: http://www.bubuko.com/inf ...
- 图形界面 II: 设置库的事件处理函数 (第三章)
目录 简介 私有元素数组 管理图表的状态 区分外部和内部使用 增强上下文菜单类 增强菜单项类 增强图形界面事件处理的主类 事件处理函数的预先测试 测试多个上下文菜单的调整 测试在应用程序的自定义类中接 ...
最新文章
- Centos7:update-initramfs -u:command not found
- wpf里的menu怎么用_股市里的两市成交量是什么,它反映了什么,我是怎么用它来定投的...
- Delphi与SQL模糊查询(转载)
- xml02 XML编程(CRUD)增删查改
- 微博自媒体,一个新的生态
- html5新特性:异步上传文件
- 职场上有3种类型的人,最后一种类型老板最喜欢,你是哪一类?
- JBoss 目录结构解释
- 接受你无法改变的事情 改变你可以改变的事情
- java mschart_vb之mschart控件小结
- 浅析双11背后的电商IT基础架构
- 浙大翁凯老师Java课堂学习记录(第三周)
- Project Management-软件开发之项目管理
- Jvm面试题及答案(2021年Jvm面试题大全带答案)
- 前端智能化实践——可微编程
- 编程常用英语单词(一)
- java中cbrt_JavaScript中带有示例的Math.cbrt()方法
- 服务器有哪些品牌,各品牌服务器之间性价比对比!
- argument type mismatch 属性参数不匹配
- VarianceDeviation Tradeoff(方差、偏差权衡)
热门文章
- 领域驱动系列五模型驱动设计的构造块
- SQL SERVER 2000安装教程图文详解
- Android:解决魅族5在Logcat下不输出Log.v()日志
- 玩转iOS开发:iOS 8 新特性《UIVisualEffect》
- 值得学习的C/C++开源框架(转)
- Photoshop通道抠出散乱的儿童头发
- Modelsim-altera 仿真 顶层原理图的解决办法
- C#/.net 中的事件与代理
- linux上运行onedrive,教你如何在Linux中同步微软 OneDrive
- 启动go服务_go微服务框架go-micro深度学习 rpc方法调用过程详解