万泉河
WX:ZHO6371995,欢迎+
级别: 略有小成
精华主题: 0
发帖数量: 116 个
工控威望: 226 点
下载积分: 783 分
在线时间: 10(小时)
注册时间: 2021-06-11
最后登录: 2024-05-04
查看万泉河的 主题 / 回贴
楼主  发表于: 2022-12-27 12:00
1225 【跨新年】【万泉河】WINCC中获取窗口变量前缀以及跨窗口操控的方法

近段时间,不约而同的,网站论坛和烟台方法学员中都有提出这样的问题。

比如:
l C脚本如何获得窗口中对象的变量前缀? VBS如何获得?
l C脚本如何实现在一个窗口中操控父窗口下的另一个窗口内的控件?
l VBS如何实现?

这些问题,都有个特点,提问的时候先把编程语言给限定了。

而咱就不太有办法拒绝。毕竟,人家有可能是在完成一个更复杂的工作,已经在选定的语言下实现了大部分的功能,现在就在这一点点功能搞不定被卡主了,过不去了,才来求助的。

而如果不指定语言的话,其实我都早就有答案,特别是VBS的解决方案,都写在《西门子WINCC入门到精通》的书里了,所以只需要从书柜里把我自己的书拿出来,找到页码,把页码号告诉对方就可以了。

而且会发现,大部分提问者其实是有我的那本书的,只是通读不够细致,没发现,或者没记住有这方面的介绍。验证了一个道理,对一本书,最了解的还是作者自己。

当然,我也发现了我写书时候遗漏的该写而未写的技巧知识点。可能潜意识里面,我自己觉得反正另一条路上有解决方案了,这边这一条就没必要去重复啰嗦实现了。特别是C脚本,对西门子来说自从20年前的WINCC版本支持VBS之后,官方逐渐在弱化C脚本的地位,我自己也逐渐淡化对其的研究和使用。想一碗水端平是永远不可能的。    

在此先提醒大家,提问问题的时候,尽可能不要限定编程语言。那样的答案多的是,可以唾手可得。而非要限定语言了,寻找起来就会有一些难度。

所以,我这里做了个例子,进行了测试,可以把这些坑填上了。也算是对我自己著作中遗漏部分的补充。


主画面中是2个按钮,分别演示了VBS脚本和C脚本弹出窗口的方法。

而弹出的窗口外观相同,然而内部的程序语言不同,分别有按钮按下后可以弹出对话框提示读取得到了前缀。

而后,将上述2个按钮分别放到另一个叫做“窗口中操控”的窗口(PDL文件),脚本经过稍微修改,实现了上述同样的功能。

l 按钮11的单击鼠标中的VBS程序为:
Sub OnClick(ByVal Item)
ScreenItems("画面窗口1").TagPrefix="M001_"
ScreenItems("画面窗口1").PictureName=Item.Text
ScreenItems("画面窗口1").Visible=True

End Sub
而窗口中有2个获取前缀的按钮,同样可以得到结果,脚本分别为:
Sub OnClick(Byval Item)
'MsgBOX(ITEM.Parent.Parent.TagPrefix)

MsgBOX(Parent.TagPrefix)
End Sub
注释掉的脚本也同样可以执行。

Sub OnClick(Byval Item)
Dim name
name=HMIRuntime.Tags("aa").Name

Dim TagPrefix
TagPrefix=Split(name,"_")(0)
MsgBOX(TagPrefix)
End Sub
这里取了一个不存在的aa后缀的变量,然而也丝毫不影响功能。因为语法本身获取的是变量名字,对变量是否有值是否合法根本不在意。

也注意两种方式得到的前缀分别有分隔符和无分隔符的区别。

标准的用法当然不能每次都通过脚本来获取,而是会在子窗口打开时即执行脚本,获取到前缀后,赋值到一个静态文本中,窗口中任何需要的地方,可以通过读取文本内容得到。

Sub OnOpen()
'MsgBOX(Parent.TagPrefix)
ScreenItems("窗口前缀").Text=Parent.TagPrefix
End Sub

而如果画面窗口中不需要显示这个前缀,可以设置静态文本为隐藏。这是官方例程中惯用的手法。

l 按钮12的单击鼠标中的C程序为:
#include "apdefap.h"
void OnClick(char* lpszPictureName, char*lpszObjectName, char* lpszPropertyName)
{
SetPropChar(lpszPictureName, "画面窗口1","PictureName","窗口12-C获取前缀.Pdl");
SetPropChar(lpszPictureName, "画面窗口1","TagPrefix", "M002_");

SetPropBOOL(lpszPictureName, "画面窗口1","Visible", TRUE);
}

窗口内获取按钮的脚本:
#include "apdefap.h"
void OnClick(char* lpszPictureName, char*lpszObjectName, char* lpszPropertyName)
{
char Name[20];
HWND hwnd=NULL;

hwnd=FindWindow(NULL,"WinCC-运行系统 -"); //获得句柄
strcpy(Name,GetPropChar(GetParentPicture(lpszPictureName),GetParentPictureWindow(lpszPictureName),"TagPrefix")); //Return-Type: char*

MessageBox(hwnd,Name,"OK",MB_OK);
}
画面打开事件中文本内容得到的方法:
#include "apdefap.h"
void OnOpenPicture(char* lpszPictureName,char* lpszObjectName, char* lpszPropertyName)
{
char Name[20];
strcpy(Name,GetPropChar(GetParentPicture(lpszPictureName),GetParentPictureWindow(lpszPictureName),"TagPrefix")); //Return-Type: char*
SetPropChar(lpszPictureName,"窗口前缀","Text",Name); //Return-Type: BOOL
}

这里C脚本实现的核心是一个GetParentPicture的函数,可以得到窗口的父窗口的文件名字。而这个函数是个神仙函数,各种帮助资料中都没有见过介绍。所以只有从已有的使用演示程序中获取。

l 窗口中按钮11的单击鼠标中的VBS程序为:
Sub OnClick(ByVal Item)
Parent.Parent.ScreenItems("画面窗口1").TagPrefix="M001_"
Parent.Parent.ScreenItems("画面窗口1").PictureName=Item.Text
Parent.Parent.ScreenItems("画面窗口1").Visible=True
End Sub

l 窗口中按钮12的单击鼠标中的C程序为:
#include "apdefap.h"
void OnClick(char* lpszPictureName, char*lpszObjectName, char* lpszPropertyName)
{
char szParentPicture[512];
strncpy (szParentPicture,GetParentPicture(lpszPictureName), sizeof(szParentPicture));

SetPropChar(szParentPicture, "画面窗口1","PictureName","窗口12-C获取前缀.Pdl");
SetPropChar(szParentPicture, "画面窗口1","TagPrefix", "M002_");

SetPropBOOL(szParentPicture, "画面窗口1","Visible", TRUE);
}

分别实现了上述同样的功能。

当然,我们也可以随意的组合搭配按钮和窗口内的程序,都可以实现同样的功能。比如即便你程序的主体语言是C的或者VBS,然而窗口中的文本获得前缀部分可以用VBS简单得到。

最后,这些具体产品知识点的技巧内容我近几年确实很少触及了。因为在我看来那都是基本功。我甚至也不去记忆具体的函数名字,比如上面的name还是tagname, TagPrefix还是Prefix都记不住的。我即便要使用,也都直接找现成的程序模块看一眼,抄来用下即可。

而事实上,随着标准化模块化的推进,这些技能已经很少用到了,因为早就封装完善在模块中了。

有一些年轻人看到我近年来写各种科普文章,很少提及这些具体的技术技能技巧,怀疑我从来没掌握这些技能,DISS我,甚至来跟我PK,只能是他们眼光太短浅了,你要从事技术工作,不是要把一项项的技能从年轻到年老记忆地牢牢的,以随时使用。相反的是,大部分技能是需要封装的,封装以后直接使用,甚至自己要主动把这些具体技能都遗忘掉,才可以有更多的精力去掌握更高层的知识。

最后,给大家的建议是,要尽量少自己从头造轮子。

虽然我自己在成长过程中,是摸着石头过河每个轮子逐个造过来的,遇到任何问题,也都抑制不住要自己亲自造轮子的冲动。轮子的每一个细节,如果不亲自掌握,就会抓耳挠腮睡觉都不安心。

然而仍然要提醒同行后来者,这是一种非常低效率的行为。你可以有好奇心,精力充沛的情况下可以对别人造好的轮子仔细研读原理,自己可以从中掌握些基本功,然而自己从头造轮子这件事,就要尽量避免了。

上述例程的实现方法,西门子官方的例子中其实原本就有,而且功能比我这里介绍的要全面而细致得多得多。

西门子官方例程中, BST例程较多的是使用了C脚本,而LBP例程(或者叫做BPL)相同的功能则更多是用VBS实现的。

这些例程我都已经写文章推荐过多次了。这回就不再提供链接以及亲自提供文件了,而只提供名字,需要者自己辛苦一点去找到并学习了解。看来太容易得到的资料通常都不珍惜,只有自己辛苦一点,千辛万苦得到的才会更加倍的去学习。

另外,考虑到上面的乏味的语言讲述不够直观,有可能很多人看了并不能理解。 我有计划在元旦期间做2次视频直播讲座,专门讲解展示这个例程的实现方法。第一次直播会在烟台方法学员群中,第二次直播会面向大众。有感兴趣者请关注公众号、朋友圈,及时获取通知。  
本帖最近评分记录:
  • 下载积分:+1(hsiung) 热心助人!
    eaglesence
    eaglesence
    级别: 略有小成
    精华主题: 0
    发帖数量: 384 个
    工控威望: 462 点
    下载积分: 19449 分
    在线时间: 77(小时)
    注册时间: 2019-04-02
    最后登录: 2024-05-05
    查看eaglesence的 主题 / 回贴
    1楼  发表于: 2022-12-30 12:14
    这个跨窗口操作大家用的多吗?