1225【万泉河】WINCC中获取窗口变量前缀以及跨窗口操控的方法 点击:615 | 回复:0



万泉河

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:74帖 | 62回
  • 年度积分:67
  • 历史总积分:413
  • 注册:2009年12月04日
发表于:2022-12-27 11:58:39
楼主

1225【万泉河】WINCC中获取窗口变量前缀以及跨窗口操控的方法

 

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

 

比如:

l  C脚本如何获得窗口中对象的变量前缀?

l  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分不嫌少!


热门招聘
相关主题

官方公众号

智造工程师