开源纯C#工控网关+组态软件(六)图元组件
一、 图元概述
图元是构成人机界面的基本单元。如一个个的电机、设备、数据显示、仪表盘,都是图元。构建人机界面的过程就是铺排、挪移、定位图元的过程。
图元设计是绘图和编码的结合。因为图元不仅有显示和动画,还有背后操纵动画的控制逻辑。
一个好的图元设计框架,应该最大限度提高设计的效率和专业程度。
因为你找到一个会做美工的码农,和会写代码的美工,都很困难,但是单独找码农和绘图员却一抓一大把。所以专业性意味着用人的灵活性,和省钱。而你招来一个美工,一个码农,合作完成一个图元组件,必须考虑减少两人的交互,最好埋头各干各的。并行作业,才有最高效率。
可以通过以下手段提高界面开发效率:
- 前后端分离。
前后端分离的设计模式有很多优点。前后端对设计者的要求是不同的。。
前端设计者需要考虑的是界面更直观、美观、清晰、大气,可以熟练使用绘图工具(例如Blend),可以不会编程。
后端设计者要考虑的是业务逻辑,如何有条不紊、准确执行。可以不会画图,但一般必然熟练编码,使用设计工具(如Visual Studio)。
前后端分离便于设计者术业有专攻,前后端分工协作,互不干扰,并行工作,提高效率。
- 专业的前端设计工具。
对于绘图员或美工,一个简单易用、同时又有强大功能的趁手设计器是必须的。
绘图板、动画、整合、调色板,美工的全套装备必须齐全;网格定位、缩放、旋转、保存、撤销,常规的设计器功能必须应有尽有。
- 尽可能少的编码。
很多行业都有庞大的图元库。各种设备、开关、构件,各种非标组件,不断会有新的图元入库。
因此,力求用最少的代码实现尽可能多的功能,最大限度提升开发效率。一个强大的基类和一个方便的继承是必要的。
二、 前后端分离的设计模式式
- 通过WPF实现前后端分离
看看百度百科对WPF的介绍:WPF(Windows Presentation Foundation)是微软推出的基于Windows 的用户界面框架,属于.NET Framework 3.0的一部分。
它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。
WPF通过一种MVVM(Model-View-ViewMode)的设计模式实现界面与编码解耦。界面元素的颜色、动画、形状,可以方便的与代码类的属性绑定(Binding)。
绑定的便利在于,后台类的某属性变化,马上会自动反映到界面的变化,无需编写代码;界面元素的变化,也马上会触发属性值的改变,这种方式天然适合人机界面的前后端分离设计。
同时,WPF提供XAML文件,是一种声明式编程方式,类似于Android的界面文件、HTML,界面设计者与代码编写者只需要通过XAML文件交互,进一步达成前后端分离并行作业的目的。
- 前后端交互的内容
绘图员的工作:
使用Blend绘图,使用故事板(Storyboard)制作动画,定义动画的视图状态(VisualState),绑定属性如:
Text="{Binding BinName, RelativeSource={RelativeSource TemplatedParent}}"
码农的工作:
定义一个CustomControl。继承HMIControlBase。
定义依赖项属性如Running:
public static readonly DependencyProperty RunningProperty = DependencyProperty.Register("Running", typeof(bool), typeof(Elevator),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnValueChanged)));
属性变化事件切换视图状态如
VisualStateManager.GoToState(this, _funcRun () ? "Run" : "Stop", true);
就这么简单。
三、 绘图与动画
- 强大的设计工具:Blend
Blend是VS2010起微软提供的专业设计工具。早期曾经有三贱客(Blend,Design, Encoder ),后两者已经合并入Blend。
在 Expression Blend 中,可以在美工板上绘制形状、路径和控件,然后修改其外观和行为,从而直观地设计界面元素。可以导入图像、视频和声音,还可以导入和更改三维对象。
可以创建Storyboard实现帧动画,定义状态(VisualState),并设计触发器(Trigger)触发动画。还可以定义样式(Style)。
Blend对美工人员是简单易上手的。按我的经验,对于习惯AutoCAD工具的绘图工程师,熟练掌握Blend一般在两周内,就可以绘制复杂的动画图形。
所有的图元组件均为CustomControl类型,这样编辑好的图元文件会自动加入到Generic.xaml文件。相应的图元模板可在Blend内重新编辑。

- 用代码实现动画
如果不用Blend,也可以用代码直接实现动画。部分对性能要求高、使用频繁的图元组件如Guage,LinkLine,可以继承Control的OnRender方法并使用StreamGeometry这类的底层API绘图,以达到最佳的性能。
StreamGeometry的优点是调用底层绘图API,不生成多余的对象,而Blend在生成图形过程中有大量冗余元素和对象,复杂的层次结构,在对性能要求较高的场合略显笨重。
四、 强大的图元基类
为了尽可能减少编码,需要在图元基类(HMIControlBase) 中实现尽可能多的功能;但又不能包办一切,牺牲图元自身的“个性”。要实现简洁、强大、可扩展。
因此,我在图元基类实现了所有界面元素共有的几个基本功能:
- 连线。
为了实现方便的连线,需要能自行设置图元的锚点,作为拖放连线的连接点。

继承GetLinkPositions方法,锚点分上下左右四个,每个锚点用一个Point确定相对位置。如果只有一个锚点,就返回单一的LinkPosition如下:
public override LinkPosition[] GetLinkPositions()
{
return new LinkPosition[]
{
new LinkPosition(new Point(0.75,),ConnectOrientation.Top),
};
}
- 绑定变量表达式。
只要继承基类,就可以弹出变量组态界面。

可以自行定义左边的属性树。即继承GetActions方法。注意这个树状结构支持嵌套,如某设备带两个电机(Motor),则电机的属性列表会作为树的子节点显示。
public override string[] GetActions()
{
return new string[] { TagActions.VISIBLE, TagActions.CAPTION, TagActions.RUN, TagActions.ALARM, TagActions.DEVICENAME };
}
- 动画显示。
继承SetTagReader方法,只要相关Tag变化,就会触发动画脚本。如
public override Action SetTagReader(string key, Delegate tagChanged)
{
switch (key)
{
case TagActions.RUN:
var _funcInRun = tagChanged as Func<bool>;
if (_funcInRun != null)
{
return delegate { VisualStateManager.GoToState(this, _funcInRun() ? "Running" : "NotRunning", true); };
}
else return null;
}
return base.SetTagReader(key, tagChanged);
}
VisualStateManager.GoToState方法根据不同的状态字,触发了在Blend里定义的故事板动画。
五、 如何实现:增加新图元
图元设计流程:

六、 下面的计划
写一系列帖子,把架构、原理讲清楚。大致如下:
- 网关层接口概述
- 上下位机通讯原理
- 如何实现一个设备驱动
- 如何设计图元
- VS插件模块及原理
- 归档模块及文件格式
- 如何进行功能扩展
- 组态变量表达式实现
github地址:https://github.com/GavinYellow/SharpSCADA。QQ群:102486275
开源纯C#工控网关+组态软件(六)图元组件的更多相关文章
- 开源纯C#工控网关+组态软件
一. 前言 在园子潜水也七八年了.说来惭愧,这么多年虽然一直自称.NET铁杆粉丝,然仅限于回几个不痛不痒的贴,既没有发布过代码,也没有写过文章. 看着.NET和C#在国外风生水起,国内却日趋没落, ...
- 开源纯C#工控网关+组态软件(二)工控网关的实现
一. 工控网关是什么 网关是物联网和工控系统的核心组件.网关起的是承上启下的作用.上即上位机,电脑/触屏监控系统.MES这些:下即下位机,包括PLC.传感器.嵌入式芯片等. 不同厂家的下位机,往往 ...
- 开源纯C#工控网关+组态软件(七)数据采集与归档
一. 引子 在当前自动化.信息化.智能化的时代背景下,数据的作用日渐凸显.而工业发展到如今,科技含量和自动化水平均显著提高,但对数据的采集.利用才开始起步. 对工业企业而言,数据采集日益受到重视, ...
- 开源纯C#工控网关+组态软件(八)表达式编译器
一. 引子 监控画面的主要功能之一就是跟踪下位机变量变化,并将这些变化展现为动画.大部分时候,界面上一个图元组件的某个状态,与单一变量Tag绑定,比如电机的运行态,绑定一个MotorRunning ...
- 开源纯C#工控网关+组态软件(九)定制Visual Studio
一. 引子 因为最近很忙(lan),很久没发博了.不少朋友对那个右键弹出菜单和连线的功能很感兴趣,因为VS本身是不包含这种功能的. 大家想这是什么鬼,怎么我的设计器没有,其实这是一个微软黑科技 ...
- 开源纯C#工控网关+组态软件(十)移植到.NET Core
一. 引子 写这个开源系列已经十来篇了.自从十年前注册博客园以来,关注了张善友.老赵.xiaotie.深蓝色右手等一众大牛,也围观了逗比的吉日嘎啦.精密顽石等形形色色的园友.然而整整十年一篇文章都 ...
- 开源纯C#工控网关+组态软件(五)从网关到人机界面
一. 引子 之前都在讲网关,不少网友关注如何实现界面.想了解下位机变量变化,是怎样一步步触发人机界面动画的. 这个步步触发,实质上是变量组(Group)的批量数据变化(DataChange)事件, ...
- 开源纯C#工控网关+组态软件(三)加入一个新驱动:西门子S7
一. 引子 首先感谢博客园:第一篇文章.第一个开源项目,算是旗开得胜.可以看到,项目大部分流量来自于博客园,码农乐园,名不虚传^^. 园友给了我很多支持,并提出了很好的改进意见.现加入屏幕分辨率自 ...
- 开源纯C#工控网关+组态软件(四)上下位机通讯原理
一. 网关的功能:承上启下 最近有点忙,更新慢了.感谢园友们给予的支持,现在github上已经有.目标是最好的开源组态,看来又近一步^^ 之前有提到网关是物联网的关键环节,它的作用就是承上启下. ...
随机推荐
- JavaEE 对象的串行化(Serialization)
什么情况下需要序列化 a)当你想把的内存中的对象写入到硬盘的时候:b)当你想用套接字在网络上传送对象的时候:c)当你想通过RMI传输对象的时候:再稍微解释一下:a)比如说你的内存不够用了,那计算机就要 ...
- windows server 2003安装 SQL server 2008r2 版本的步骤
大家好,这里介绍的是在系统 windows server 2003安装 SQL server 20008r2版本,如有雷同,敬请谅解,如果错误,欢迎大家多提意见 1.下载好安装包解压以后,就会出现如下 ...
- Anroid四大组件service之本地服务
服务是Android四大组件之一,与Activity一样,代表可执行程序.但Service不像Activity有可操作的用户界面,它是一直在后台运行.用通俗易懂点的话来说: 如果某个应用要在运行时向用 ...
- 自学 Python 3 最好的 入门 书籍 推荐(附 免费 在线阅读 下载链接)
请大家根据自己的实际情况对号入座,挑选适合自己的 Python 入门书籍: 完全没有任何编程基础:01 号书 少量编程基础,不求全,只希望能以最快的速度入门:02 号书 少量编程基础,有一定的英文阅读 ...
- SpringMVC + Spring + Mybatis+ Redis +shiro以及MyBatis学习
SpringMVC + Spring + Mybatis+ Redis +shiro http://www.sojson.com/shiro MyBatis简介与配置MyBatis+Spring+My ...
- 23种设计模式JAVA 实现目录总结
曾看了不少的有关设计模式的文章,有的提供的实现在现在看来是有些问题,所以现在对以前看过的有关设计模式的文章在这里总结一下,随笔中有引用其他资料,并根据自己的理解重新实现了一次,23种设计模式中,并没有 ...
- Spring 为Bean对象执行初始化和销毁方法
1)初始化: ①可以利用<bean>元素的init-method="方法名"属性指定初始化方法. ②指定的初始化方法是在构造方法调用后自动执行.若非单例模式,则每创建一 ...
- Git相关操作四
1.克隆远程仓库 git clone remote_location clone_name remote_location为仓库地址,clone_name为要克隆到本地的仓库名称. 2.显示对应克隆地 ...
- APUE 4 - 线程<2> : 线程同步
当控件的多个线程共享统一内存时,我们需要确定各个线程访问到的数据的一致性.在cpu结构中,修改操作由多个内存读写周期(memory cycle),而在这些内存周期之间, 有可能会发生其他线程的内存读操 ...
- LeetCode 120. Triangle (三角形)
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...