“InTouch作为一个非常开放的单机版上位机组态软件,不仅能够实现与几乎所有工控设备的通讯,它其实还有很多隐藏的功能,可以作为容器嵌入很多ActiveX控件(图形、动画、音视频、摄像头、曲线、报表等),第三方软件可以开发出很多方法函数的功能封装成dll文件以供Intouch内部脚本调用起到程序保密的作用。在这里利用其扩展函数WWContext()区域定位以实现多级菜单的管理系统。”
功能设计(主菜单、子菜单、子子菜单)
一般将整个画面系统分为操作界面和配置界面。操作界面供操作人员监控、参数设置、查看曲线、报表报警查询等;具有工程师权限的人才可以进入到配置界面,可以对菜单命名先后排列顺序进行调整,可以设置各级菜单的入口权限。
鼠标悬停自定义下拉菜单
- 主菜单:以文本和方框叠加为一组组成一个菜单,预先设定主菜单的数量上限假如为10,则设计10组主菜单,从左到右依次排列开来,整个主菜单作为操作人员的唯一界面入口。
- 子菜单:附属在主菜单下面,经主菜单随意调用以及分配入口权限。
- 子子菜单:附属在子菜单下面,经子菜单随意调用以及分配入口权限。
计算各级菜单的定位
菜单定位涉及到每个文本、方框、窗口的(X,Y)坐标值的动态改变,以及它们的宽度和高度的随之相应的变化。
首先使用WWContext()函数获取窗口的区域定位,这样鼠标游走在哪个区域就会触发相应的动作,这个动作可以是使文本或方框填充变色,也可以触发一个脚本给某个标记名赋值或者打开和关闭某些窗口。实际上这个WWContent()函数的就是省去了鼠标的点击动作,节省了手指头的力气开支。
给不同区域命名以作条件判断
WWContext("分级菜单",75,53,132,45,Tip_Name, "Menu01"); WWContext("分级菜单",207,53,132,45,lTip_Name, "Menu02"); WWContext("分级菜单",339,53,126,45,Tip_Name, "Menu03"); WWContext("分级菜单",465,53,120,45,Tip_Name, "Menu04"); WWContext("分级菜单",585,53,132,45,Tip_Name, "Menu05"); WWContext("分级菜单",717,53,132,45,Tip_Name, "Menu06"); WWContext("分级菜单",849,53,132,45,Tip_Name, "Menu07"); WWContext("分级菜单",849,53,132,45,Tip_Name, "Menu08"); WWContext("分级菜单",849,53,132,45,Tip_Name, "Menu09"); WWContext("分级菜单",849,53,132,45,Tip_Name, "Menu10");
比如:当鼠标进入Menu01区域时触发某动作,进入Menu02区域时触发某动作......后面就都是if...elseif...else...endif...的嵌套了,这是鼠标悬停下拉菜单的核心原理。
实际上,只要是具有“触动按钮”的动作属性的控件都具有“鼠标悬停时”的功能,只是它俩的使用策略不同罢了。
“鼠标悬停时”脚本
若是要说鼠标精确定位哪个更好用,那当然就是非WWContext()莫属了。原因是“鼠标悬停时”这个脚本功能只能寄托于控件元素这个对象之上,脱离了它就不起作用了。而WWContext()的作用对象是整个窗口界面,它比“鼠标悬停时”定位范围更大,不受控件切换的影响,所以孰优孰劣十分明显。
阐述菜单管理系统的用法
鼠标悬停下拉菜单管理是一个系统,因为它牵一发而动全身,后期维护便于管理,条理清晰,工程师和管理员之间可以完美交互,管理员只需要在配置界面修改若干参数即可。如下图所示:
- 禁用菜单:选择权限为6000这个等级,管理员通过勾选对应主菜单、子菜单、子子菜单的CheckBox单选框来授权是否可以开通属于6000这个等级的所有用户的操作权限。若禁用,则用6000这个等级登陆的用户会看到界面上菜单名称均为灰色并鼠标触碰无效;若开通,则菜单名称为黑色,用户鼠标可触碰菜单名称变为白字蓝底。
- 菜单名称:管理员可以更改某个菜单名称并且修改这个菜单名称所链接的窗口脚本等。
- 隐藏/显示:管理员可隐藏和显示某些菜单来达到不该看的不让看。
以上所有实现不需要具有修改工程内容即可完成。
鼠标悬停菜单管理系统
而“中国式”工控工程师的开发习惯。一般我们开发一个画面功能我们只做简洁实现,比如我们点击按钮打开窗口代码这样写:
show "窗口";
禁用或开启6000安全等级的按钮或输入框权限为:
$Accesslevel > 6000
这样完全分散开了,后期业主要求做个修改就必须再次修改工程内容,工作量非常大。
编写脚本
为了实现整个菜单系统的功能,一共写了将近2000多行代码(条件脚本、数据改变脚本、Function函数、窗口脚本),篇幅有限,只能展示主要的代码结构如下所示:
IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos1, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos2, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos3, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos4, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos5, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos6, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos7, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos8, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos9, menu_YPos ); ENDIF; IF ( menu_MainSelec ) THEN ... ShowTopLeftAt( menu_Name, menu_XPos10, menu_YPos ); ENDIF;
以下是实现的效果视频:
Intouch鼠标悬停下拉菜单的实现
注意:要协调好主菜单、子菜单、子子菜单的定位关系;各个菜单界面可以利用公共模板窗口给中间变量赋值的形式来动态切换菜单内容以及窗口链接;需要对子菜单超出窗口的边界的情况加以判断并调整子菜单的X坐标位置;创建的标记名数需要几百个,这其中有需要勾选保留值的标记名(用以存储菜单名称以及等级权限);