简介:WinCC画面图层隐藏显示项目案例包,面向工业自动化组态工程师、SCADA系统维护人员及WinCC二次开发学习者,聚焦组态画面中多图层动态显示与切换的典型需求。资源围绕图层管理与VBS脚本控制展开,涵盖图层概念、图层对象组织方式、Layer.Visible属性设置、按钮点击事件触发等内容,可帮助读者快速掌握借助脚本实现控件按条件显隐的方法。压缩包共298个文件、约10.1MB,以rpl、pdl、xml、ini等组态与配置类型为主体,另含sav、mdf数据文件以及log、cfg运行记录,文件类型较完整,便于还原项目结构并辅助排查画面刷新、显隐失效等问题。已有2284人浏览学习,对需要处理复杂画面层级与交互逻辑的读者具有直接借鉴价值,尤其适合作为中小型监控画面的设计模板。对于需要实现多画面联动、按权限或报警状态切换图层的应用场景,这套案例可提供可直接参考的脚本逻辑与对象命名思路。
1. WinCC画面图层隐藏显示:这套显隐逻辑值得单独做一篇文章
做水厂或汽车产线的WinCC项目时,最容易出现这种尴尬:操作画面上堆了三四十个对象,设备状态、阀门指示、操作提示、报警闪烁全部摆在同一屏里,一旦工艺切到某个模式,不需要的对象却还留在画面上,操作员光找启动按钮就要花几秒。WinCC的图层隐藏显示,就是把画面按逻辑分组后再按条件统一显隐的手段。它的核心不是“每个对象单独设Visible”,而是利用WinCC图形编辑器里那几十个图层的可见性开关,一口气把一组对象同时切出来或收进去。本文会把图层机制、动态对话框、C/VBS脚本三种落地做法拆开讲,并附上我在项目里踩过的几个坑,适合WinCC V7/V8项目上被画面层显隐折腾过的组态工程师。
2. 图层机制与方案选型:为什么不用画面切换,偏要用图层
2.1 图层的存储位置:图形编辑器右下角的“图层”面板
WinCC的画面文件(.pdl)在图形编辑器里打开时,默认能调出“图层”面板,常见版本会提供32个图层,名字从Layer 1到Layer 32。每个画面对象都可以分配到其中一个图层,分配位置在对象属性对话框里,一般能看到一个“图层”或“层”的下拉项。
图层面板里每一行都有三个小图标,分别控制“可见”、“可编辑”、“可选中”。开发时如果把某一层设为不可见,编辑器里这一层上的对象会变成灰显或直接隐藏,这方便你分层组态,不会误改其他层的内容。运行时,这些图层的可见性也会跟着运行状态实时变化,于是便有了“图层隐藏显示”的效果。
这里要分清楚:画面文件本身是顶层容器,画面窗口(Picture Window)是对象。真正干活的是“画面文件的图层”,而不是画面窗口的某几个属性。如果你要控制的是整个子画面的显隐,那是另外一套动态画面名称切换的逻辑,别和图层机制混在一起。
2.2 图层方案和画面切换方案怎么选
画面切换的做法大家很熟悉:画面窗口对象连一个内部变量,运行时通过改变画面名称来换掉整个子画面。这个方案适合“完全不同的页面”,比如操作页切到趋势页,页面内容没有任何交集,切换成本低。
图层方案适合的是“同一个画面框架内,局部内容要随工艺状态组合显隐”的场景。我做过一个泵站项目,主画面固定,底部设备区要按“手动/自动/检修”三种模式显示不同的操作按钮和状态文本。如果用画面切换,得做三个几乎相同的画面文件,每个文件里复制同样的管道和仪表对象,后续改一个阀门颜色要改三处;用图层方案,只需要在三个图层里各放一组按钮,每次只显示其中一层,对象引用不丢,动画连接也一直在后台保持激活。
选型结论:零散按钮显隐用对象的Visible属性就够;整组显隐且频率高、条件多的情况,必须上图层。另外,图层的显隐在运行时不重新加载画面,切换速度明显比换画面窗口快,对操作员点按钮后的反馈体验很重要。
2.3 图层显隐的执行方式:三种手段怎么搭配
在实际WinCC项目里,图层显隐有三级实现手段。
第一级是开发组态时手动设定图层可见性,这只能用于编辑阶段,运行系统不会跟着变量自动变。
第二级是动态对话框,把一个内部布尔变量直接连接到图层的“可见性”属性上。变量为1时层显示,为0时层隐藏。这种做法不需要写一行脚本,是项目里最常用的无代码方案。
第三级是C动作或VBS动作,适合需要联动计算、循环判断多层状态的场景。比如多个变量组合决定某层是否可见,或者一个按钮要同时关闭三层再打开另一层,写脚本比铺一堆动态对话框清爽得多。
我一般建议:单层控制用动态对话框,多层组合切换用脚本,并且把所有图层变量统一命名成Layer1Show、Layer2Show这种格式,调试时在变量管理里扫一眼就能判断哪一层在生效。
3. 动态对话框加C脚本:把图层显隐接到变量上
3.1 动态对话框配置步骤:无代码方案怎么把变量接上去
打开图形编辑器,选中画面上任意一个空白区域,属性窗口里找到“图层”节点。展开后你会看到当前画面每个图层的可见性条目。右键目标图层的可见性属性,选择“动态对话框”,然后按下面顺序操作。
第一,在“事件”里选择“变量”,再点“选择”按钮,从变量管理里挑一个内部布尔变量,比如@Layer1Show。第二,在“触发”区域把触发方式选为“变化时”或“变化时立即触发”,这样变量一翻转过画面立刻响应。第三,在“数据范围”或“连接关系”里确认数据类型是布尔量,并把“0时隐藏、1时显示”的对应关系设置正确。
这里有一个容易搞错的地方:动态对话框连接的是“可见性”属性,不是“可编辑”属性。可见性管的是运行时眼睛能不能看到;可编辑性管的是运行人员能不能操作。很多临时排查找不到对象,就是因为把变量接到了“可编辑”上,操作员看到的画面倒是全的,但按钮怎么点都没反应。
配置示例: 目标属性:画面对象的 Layer1 可见性 连接变量:@Layer1Show(内部布尔) 触发方式:变化时立即触发 对应关系:0 = 隐藏,1 = 显示配置完成后,在运行系统里手动把@Layer1Show置1,图层1上的所有对象会一起出现;置0后全部消失。这套配置不需要编译脚本,改完保存画面就能直接在运行系统里调试。
参数说明:变量名不能带空格,布尔型内部变量是Simatic WinCC变量管理里“内部变量”节点下新建的“二进制变量”。如果你用的是外部PLC变量,要注意通讯中断时变量值会保持最后状态,可能造成图层锁定在某个状态,这一点后面的避坑章节会再提。
3.2 C脚本按钮动作:联动多个图层开关
单层显隐用动态对话框很干净,但项目里更常见的是“点一个按钮,同时切走旧层、切进新层”,这种联动用C脚本更直接。
#include "apdefap.h" void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) { // 点击按钮后,把画面切到“手动模式”对应的图层组合 // 这里假设开发时已经用动态对话框把 Layer1Show/Layer2Show 连接到图层可见性 // 脚本只负责统一翻转变量值,避免动态属性数量过多 SetTagBit("Layer1Show", 0); SetTagBit("Layer2Show", 1); SetTagBit("Layer3Show", 0); }这段脚本挂在一个按钮的“鼠标按下”事件里。逻辑说明:按钮被按下时,先关掉图层1和图层3,再打开图层2。这样操作界面上会瞬间切换到图层2包含的设备状态和操作按钮。
参数说明:SetTagBit的第一个参数是变量名,第二个参数是布尔值,0或1。WinCC的C脚本里变量名通常不带“@”前缀,变量管理里显示的是带@的内部变量,脚本里直接用去掉@的名字。
如果不想通过变量中转,也可以用SetProp直接操作画面图层的可见性属性,但不同WinCC版本的属性命名有差异,建议先在项目里查属性面板里“图层”节点下的准确属性名,再决定用哪种写法。
// 备选方案:不经过变量,直接写图层属性 // 属性名以你项目属性面板显示的为准,不同 WinCC 版本可能写成 Layer1Visible 或 Layer0Visible SetProp(lpszPictureName, NULL, "Layer1Visible", 1); SetProp(lpszPictureName, NULL, "Layer2Visible", 0);逻辑说明:SetProp第一个参数是当前画面名(lpszPictureName),第二个参数是对象名,这里传NULL表示操作的是画面文件本身而不是某个画面窗口对象;第三个参数是属性名,第四个参数是值。这种写法跳过了变量转发,但属性名拼写错了不会报编译错,只会运行时不生效,所以我一般不用在需要快速交付的项目里。
3.3 初始化逻辑:启动时先把图层状态归位
图层显隐最怕的是“上一次运行留下的状态被带进下一次”。如果某个图层在系统退出前是隐藏的,重启后又没有脚本去复位,操作员看到的画面可能是不完整的。
建议在“初始画面”的打开事件或项目启动脚本里做一次统一初始化。写一个全局C函数,把所有图层变量一次性置成默认值,再按启动时的工艺模式设置对应图层。
void L_InitLayerDisplay() { // 先全部关闭,再按默认模式打开第1层 SetTagBit("Layer1Show", 1); SetTagBit("Layer2Show", 0); SetTagBit("Layer3Show", 0); SetTagBit("Layer4Show", 0); }逻辑说明:这个函数放在WinCC的全局脚本编辑器里,可以在项目启动阶段被调用,也可以挂在主画面的“画面打开”事件里。它的作用是把所有图层显隐状态收敛到一个确定的起点,避免操作员一进画面就看到一个莫名其妙的多层重叠状态。
参数说明:默认显示哪一层,要看项目的工艺约定。我一般把“总览层”放在第1层,第2层放主操作层,第3层放报警提示层,第4层放维护辅助层,这样变量编号和画面视觉层级能对应上。
4. 用VBScript实现多图层组合显隐:适合复杂条件判断
4.1 属性动作里直接读变量返回显示状态
C脚本擅长处理“点击后立即执行”的时序逻辑,VBScript则在“属性值根据变量实时计算”的场景里更好用,因为它可以直接在属性动作里写条件表达式,返回当前这一帧该层应该显示还是隐藏。
在画面图层可见性属性的“属性动作”里,可以选VBScript,然后写如下代码。
' 在图层1可见性属性的动态属性动作中写入 ' 当工艺模式是1或3时,图层1显示 Dim nMode nMode = HMIRuntime.Tags("MachineMode").Read Layer1Visible = (nMode = 1 Or nMode = 3)逻辑说明:这个动作每一帧都会被运行系统执行一次,也就是说MachineMode一变,图层的显示状态在下一个刷新周期就会跟着变,不需要按钮触发,也不需要在变量事件里写额外逻辑。Layer1Visible是这个属性动作里约定的返回值名称,运行系统会把它的布尔结果作为图层可见性的当前值。
参数说明:MachineMode是我在项目里定义的内部整数变量,工艺模式1代表自动,2代表手动,3代表检修。你可以按自己的变量替换。VBScript里布尔运算用Or、And、Not,不要用C语言风格的|、&。
4.2 按钮事件里先全关再开目标层
多图层切换最容易出现“上一层的残留还留在画面上”的翻车现场。比如从自动模式切到检修模式,自动模式的按钮层忘了隐藏,结果两个操作层叠在一起,现场值班员点了半天不知道点在哪个按钮上。
推荐的做法是一个按钮事件里先统一把所有图层关掉,再打开目标层。这样逻辑里只有一个出口,不会出现“这次忘了关某层”的低级错误。
Dim i Dim objTag ' 先把图层1到图层6全部关掉 For i = 1 To 6 Set objTag = HMIRuntime.Tags("Layer" & i & "Show") objTag.Write 0 Next ' 再打开目标图层3 Set objTag = HMIRuntime.Tags("Layer3Show") objTag.Write 1逻辑说明:这个脚本放在“检修模式”按钮的鼠标点击事件里。循环先把所有已存在的图层显隐变量清零,再把目标层置1。看起来多写了几行,但胜在稳定,以后新增图层时只需要把循环上限从6改成新的层数。
参数说明:这里的变量名用了字符串拼接,Layer & i & Show,对应的变量是Layer1Show、Layer2Show直到Layer6Show。变量名必须和变量管理器里完全一致,否则运行时找不到变量会报错。
4.3 组合条件显隐:一个图层显示需要两个变量同时满足
实际工艺里经常出现这种情况:报警提示层要显示,不只是因为“有报警”,还要满足“当前画面是主操作画面”和“系统不在检修模式”两个条件。这种组合条件用VBS动作写非常直观。
Dim bAlarm as Boolean Dim bMainView as Boolean Dim bMaintain as Boolean bAlarm = HMIRuntime.Tags("AlarmActive").Read bMainView = HMIRuntime.Tags("MainViewActive").Read bMaintain = HMIRuntime.Tags("MaintainMode").Read Layer4Visible = (bAlarm And bMainView And Not bMaintain)逻辑说明:图层4作为报警操作提示层,同时满足报警存在、当前在主画面、不在检修模式三个条件时才显示。任何一个条件不满足,这一层就自动隐藏,操作员不会在检修模式下误看到一堆报警提示按钮。
参数说明:逻辑表达式里括号明确优先级。VBScript对布尔值的读取结果可能是整数或布尔类型,建议都用变量声明承接后再参与计算,可读性更好,排错时也能用MsgBox把中间值打出来看。
5. WinCC图层显隐的常见问题与排查:现象、原因、解决
5.1 图层配置好了,运行起来对象却不见
现象:开发环境里图层上对象都亮着,编译也没报错,但运行系统启动后,这一层上的设备符号、阀门图标全部消失。图层可见性变量也确认过是1。
原因:最常见的是对象压根没有被分配到这个图层,或者对象被分配到了图层面板里被编辑状态锁定的图层。WinCC的“可见/可编辑/可选中”三个状态是独立的,开发时如果把该层设成“不可编辑”,画面会隐藏该层对象以方便编辑其他层,运行系统里也沿用这一状态,于是对象就一直不显示。
解决:回到图形编辑器,打开“图层”面板,检查目标层是否被手动设置为“隐藏”。再把画面里那个消失的对象选中,在属性里确认它的图层编号是否真的指到了目标层,而不是默认的“图层1”。确认后执行一次“画面编译”,运行系统重新加载画面再看效果。
5.2 变量已经是1,图层还是没切出来
现象:内部布尔变量Layer1Show已经在变量管理里被强制为1,运行系统画面上的图层1还是没有出现,或者要等好几秒才出现。
原因:变量确实置1了,但图层可见性属性连接的不是这个变量,而是另一个“看起来很像”的变量;或者动态对话框的触发方式选成了“仅在画面打开时读取一次”,变量后续变化不再触发。
解决:打开图层属性对话框,点开动态对话框,核对连接变量是不是当前在变量表里强制的那个;变量名不要只看缩写,要完整核对路径。触发方式统一改成“变化时立即触发”。如果项目里大量使用了动态对话框,建议用变量表里的“查找引用”功能,右键变量名查一下它到底被哪些画面属性引用了。
5.3 多层同时显示时出现白底遮挡
现象:图层4本来是报警提示层,显示后就盖住了图层1上的工艺流程图,而且屏幕中央出现一块白色或灰色背景框,把下面的管道和电机符号遮得严严实实。
原因:这一层上的某些对象带有“填充背景”属性,比如矩形框默认会填充一种背景色,即使里面没有文字,也会在画面上生成一块不透明色块。图层本身只是分组工具,不会自动给你一个透明背景,透明与否取决于层内对象的填充设置。
解决:选中图层上所有对象,在属性里把填充模式设为“否”,或把填充颜色改为透明。如果确实需要一个背景框,把背景框放在一个专门的“底层”,不参与显隐变化,这样切换图层时其他层上的半透明效果就不会被背景色块截断。
5.4 不同WinCC版本的图层属性名对不上
现象:从老项目里复制来的VBS脚本,在新版WinCC V7.5/V8环境里报“对象不支持该属性”或“类型不匹配”,尤其属性动作里写Layer1Visible这种名字。
原因:不同版本的图层索引起始值和属性命名有差异,有的从Layer0开始,有的从Layer1开始。老教程里写的Layer1Visible,在新版本里可能对应Layer0Visible,或者属性名改成了其他写法。
解决:不要直接照着旧脚本套。在图形编辑器属性窗口里展开“图层”节点,看当前版本到底显示的属性名是什么,以属性面板为准。复制老项目脚本时,先在一个测试画面上验证属性名能正常返回,再大规模贴到正式画面里。这个坑我翻过两次,后来养成习惯:凡是图层相关脚本,第一行写注释标明“属性名以V7.5 SP2属性面板为准”。
5.5 运行系统里点击按钮没反应,模拟环境却正常
现象:图形编辑器里开着“仿真运行”调试画面,点按钮图层切换一切正常;正式启动WinCC运行系统后,同样的按钮点了无反应,图层状态纹丝不动。
原因:运行系统启动时加载的是编译后的画面文件。如果开发环境里修改过按钮脚本或图层配置,但没有重新编译,运行系统加载的还是上一次编译的旧版本。另一种可能是按钮的C脚本引用了变量的“画面树路径”,在直接调试时能解析,在运行环境里的启动顺序不同导致变量未初始化。
解决:修改过脚本后,退出运行系统,在项目编辑器里执行一次完整编译,重点是“画面”编译节点。如果项目是多用户环境,还要注意当前编译的是不是你登录的那个版本。启动顺序问题则把图层初始化脚本从按钮移到全局启动画面里,保证变量初始化先于按钮可点击。
6. 进阶技巧:把图层显隐逻辑收口成统一函数
做大型WinCC项目时,图层显隐最怕的不是做不出来,而是做到后面图层变量散落在几十个按钮和属性动作里,现场改一个工艺模式要满画面找脚本。我的习惯是建一个全局脚本函数,把所有图层切换逻辑收口到一个入口里,按钮事件只负责调函数,不做具体判断。
在全局脚本编辑器里定义一个函数,参数是目标模式编号。函数内部根据模式计算每一层该不该显示,然后统一写变量。
void SetLayerByMode(int nMode) { // 按工艺模式计算各层显隐状态 // 模式1:自动,显示第1、2层 // 模式2:手动,显示第1、3层 // 模式3:检修,显示第1、4层,隐藏操作层 SetTagBit("Layer1Show", 1); SetTagBit("Layer2Show", (nMode == 1) ? 1 : 0); SetTagBit("Layer3Show", (nMode == 2) ? 1 : 0); SetTagBit("Layer4Show", (nMode == 3) ? 1 : 0); }按钮脚本里就只写一句SetLayerByMode(2),把具体的模式编号传进去。
这样改完的好处是现场排查问题只需要看这一个函数:工艺人员说“手动模式看不到启动按钮”,打开SetLayerByMode,看模式2时Layer3Show有没有被置1,再检查图层3上的对象有没有放错,问题链非常短。新来维护的人不用翻遍全部画面找图层变量被谁写过。
我还会在变量表里把所有图层显隐变量集中放在一个用户文件夹下,命名统一带Layer前缀,打开变量管理器就能看到整个画面分了几层、分别叫什么。跑现场调试时,把Layer1Show强制成1,哪一层该出现的东西没出现,一眼就能定位到是对象放错层还是变量没连上。
从那以后,我每次做WinCC画面图层显隐,都会先画一张图层分配表,列清楚哪一层放什么内容、由哪个模式驱动、初始化默认值是什么,再动手组态。虽然多花了十分钟,但后面现场调试省下来的时间远远不止十分钟。希望这篇文章能把你在图层显隐上踩过的坑一起填平。
本文还有配套的精品资源,点击获取