WinccOA脚本语言Control基础篇

本文档详细介绍了Control脚本语言的基本概念,包括脚本触发方式、寻址类型、数据类型、映射操作、类型转换、变量和常量、运算符以及控制结构。特别强调了映射在保存键值对中的作用和相关API,同时涵盖了数据类型的动态数组和不同类型间的转换。此外,还阐述了变量的默认值、常量的使用以及各种控制结构(如if-else、循环)的应用。
摘要由CSDN通过智能技术生成

原创作品,如需转载请注明出处

1 简介

Control是一门内置于WinCCOA的脚本语言,语法结构类似C++

支持多线程

每个脚本中都有main()函数,脚本执行后进入main函数中

  • 被动属性脚本

打开界面时对其main()函数处理一次,不一定与用户输入相关联,被动属性对过程状态进行可视化,包括图形边框颜色,可见性等等
可以理解为对象的属性

  • 主动属性脚本

需要用户输入,比如:鼠标点击,单选框或者复选框等输入命令,
每点击一次就会执行一次脚本中的main函数,无需注册设备对象
可以理解为对象的方法

2 脚本触发方式

  • 通过属性改变触发

函数绑定属性,当属性发生变化时,触发相应的函数,执行脚本

  • 用户输入

比如:当我们点击一个按钮,触发脚本运行,这个脚本仅在点击一次按钮

  • 2.3 终止脚本

关闭含有某个图形元素的运行界面,与图形元素相关的被动脚本将停止运行,
如果关闭了管理器(杀掉进程),所有启动脚本会被终止

3 寻址类型

  • 寻址设备对象属性
A.:_original.._value

Pump12.Command_On:_original.._value

A.:_msg_conv.2._round_val

MySystem.:_pv_range.._min

  • 寻址结构元素
Test_Structure.Fifthelement:_original.._value

Test_Structure[5]:_original.._value
  • 使用别名寻址设备对象元素
Pump12.Command_On:_original.._value

@P12Com_On:_original.._value

Mausi1:Test_Structure.FifthElement:_original.._value

Mausi1:@T_Str5:_original.._value

在第一个示例中,“Pump12:Command_On”具有别名“P12Com_On”;在第二个示例中,“T+Str5”是“Test_Structure.FifthElement”的别名。

4 数据类型

名称值范围备注
anytype任何类型,取决于第一个变量赋值
atime报警时间,如多个报警同时触发,会为不同的报警设定索引以区分
bit320~4294967295位模式(32位)
bit640~10146744073709551615位模式(64位)
blob二进制大对象
bool0或1 true或fals二进制(1位)
char0~255字符(单字节)
double-1.79769e+308 to +1.79769e+30864位浮点数
errClass指定错误类
file文件指针
float-1.79769e+308 to +1.79769e+308浮点数 = double
function函数指针
int-2147483648 ~ +2147483647整型值(32位)
uint正整型值(32位)
long整型值64位 常量后缀要有L 0x7FFFFL
ulong整形值64位 常量后缀要有UL 0x7FFFFUL
langString语言字符串
mixed与anytype相反,每次获得一个新类型
mapping映射可保存任意键值对。键值对将包存在两个数组中
va_list通过va_list可定义任意数目的参数。va_start将参数设置到va_list变量,va_arg类似一个迭代器,va_end停止参数列表的处理
string任意数目的字符字符串
time内部时间格式
unsigned0~4294967295正整型值 unsigned f=4294967295u;
dyn_anytype任何数据类型的动态元素数组
dyn_shape图形元素的动态指针数组。
dyn_atimeatime 的动态数组。dyn_atime 包含 atime,因此,它是 DpIdentifier与带计数的时间的组合,其中包括配置和详细信息,但不包括 DPE,例如:":_alert_hdl.2" + 2009.08.12 19:11:54.356 (0)
dyn_bit32动态位模式数组(32 位)
dyn_bit64动态位模式数组(64 位)
dyn_blob动态 blob
dyn_bool二进制值的动态数组
dyn_char动态字符数组
dyn_errClassWinCC OA 内部错误类的动态数组
dyn_float浮点值的动态数组
dyn_function函数指针动态数组
dyn_int整型值的动态数组(32 位)
dyn_uint正整型值的动态数组(32 位)
dyn_long整型值的动态数组(64 位)
dyn_ulong正整型值的动态数组(64 位)
dyn_langString语言字符串的动态数组(请参见多语言功能)
dyn_mapping动态映射。映射可保存任意键/值对。键值对将保存在两个数组中。
dyn_string字符串的动态数组
dyn_time内部时间格式的值的动态数组
dyn_dyn_anytype任何数据类型元素的动态数组的动态数组
dyn_dyn_atime动态 atime 数组的动态数组
dyn_dyn_bit32动态位模式数组的动态数组(32 位)
dyn_dyn_bit64动态位模式数组的动态数组(64 位)
dyn_dyn_blob动态 blob 数组
dyn_dyn_bool二进制值动态数组的动态数组
dyn_dyn_char动态字符数组的动态数组
dyn_dyn_errClass动态错误类的动态数组
dyn_dyn_float浮点值动态数组的动态数组
dyn_dyn_function动态函数指针的动态数组
dyn_dyn_int整型值动态数组的动态数组(32 位)
dyn_dyn_uint正整型值动态数组的动态数组(32 位)
dyn_dyn_long整型值动态数组的动态数组(64 位)
dyn_dyn_ulong正整型值动态数组的动态数组(64 位)
dyn_dyn_langString语言字符串动态数组的动态数组(请参见多语言功能)
dyn_dyn_shape图形元素动态指针的动态数组。
dyn_dyn_string字符串动态数组的动态数组
dyn_dyn_time内部时间格式的值数组的动态数组
dbRecordsetADO 接口的访问变量
dbConnectionADO 接口的访问变量
dbCommandADO 接口的访问变量
shape图形元素的指针
idispatchActiveX 对象的方法的数据类型

下标访问法

位模式下使用pattern[i]访问每个位,对于bit32 i的范围是[0,31]返回bool
处理位运算的函数
字符串下使用string[i]访问每个字符,string[i]返回char

5 映射(关联数组)

5.1 基本概念

“one”1
“two”2
“three”3

映射的作用:保存键值对
所有的键:放在一个数组中,所有的值放在另外一个数组中,所以也叫做关联数组

main(){
    mapping m;
    m["one"] = 1;
    m["two"] = 2;
    m["three"] = 3;
    DebugN(m["one"]); // 输出: 1
}

映射可以嵌套

main(){
    mapping m;
    mapping n;
    n["k1"] = "v1";
    n["k2"] = "v2";
    m["mk1"] = n;
    DebugN(m["mk1"]["k1"]); // 输出”v1“
}

与dyn_string相比,映射占用空间大,写速度慢,读速度快

main(){
    mapping root;
    mapping child_map;
    dyn_string child_dyn;
    child_map["one"] = 1;
    child_map["two"] = 2;
    child_map["three"] = 3;
    child_dyn[1] = "one";
    child_dyn[2] = "two";
    child_dyn[3] = "three";
    root["c1"] = child_map;
    root["c2"] = dyn_map;
    DebugN("root->c1->element2"+root["c1"]["two"]); // 输出:2
    DebugN("root->c2->element3"+root["c2][3]); // 输出: "three"
}

5.2 映射相关API

  • 通过键直接修改/访问值
main(){
    mapping m;
    m["one"] = 1;
    DebugN(m["one"]); //输出:1    
    m["one"] = 2;
    DebugN(m["one"]); //输出:2 
}
  • 获取映射内共有多少对键值对 mappinglen
main(){
    mapping m;
    m["one"] = 1;
    m["two"] = 2;
    DebugN(mapping(m),"should be=2")
}

  • 获取映射内所有key mappingKeys()

  • 获取映射上索引的键 mappingGetKey()

for(int i = 1; i<=mappinglen(m); i++){
    DebugN(mappingGetKey(m,i)); // 输出:k1,k2,...
}
  • 获取映射上索引的值 mappingGetValue()

  • 判断映射上有没有指定的键 mappingHasKey(mapping:m,string:“one”)

  • 移除映射上的指定键 和键值 mappingRemove(mapping:m,string:“one”)

6 类型转换

数据类型转换过程中可能会有意想不到的结果

  • 显示类型转换
int a = 123;
string s = "hello";
DebugN((string)a+s); //输出:hello 123
  • 字符串转字节
string s = "00000011111100000011111100000011";
bit32 b = s;

string s = "FFAB003A";
blob b = s;
// 该 blob 现在包含 4 个字节,十六进制值为 FF、AB、00 和 3A。
// 字符串也可具有此形式
string s = "FF,AB,00,3A";
  • 时间值与其他类型互转

7 变量和常量

  • 变量名

字母或下划线开头,不限长度,区分大小写,推荐小驼峰命名:sayHelloWorld

  • 默认值

control中每个变量即使不初始化变量,也有一个默认值,对于数值类型,int,float,double 默认值是0;对于字符变量char string 默认值为""

  • 管理器全局变量
main()
{
...

addGlobal("counter", INT_VAR); // creation of the variable

counter=15; //counter can now be assigned a value

...

}
  • 字符常量

‘x’ 单引号括起来的就是字符常量

  • 数值常量

如果要显示大于 MAX_LONG 的值,则应使用无符号后缀

一般没有小数点的是int类型数值常量,十进制数,有小数点是float类型数值常量

字符串0开头,会被解析成八进制数,字符串以0X开头,会被解析成16进制数据

  • 错误变量

errClass 存储错误信息:优先级,错误类型或错误文本。

  • 未定义变量
    如果运行时访问未定义的变量,则会报错,立即停止当前线程

  • “const”关键字

const用于将变量标记成常量,使用const修饰后的变量不支持修改

  • 全局变量

main函数开头声明的变量在整个脚本/库内有效,如果脚本/库内其他函数含有同名变量,局部变量将覆盖全局变量

main(){
   int a = 1;
   int b = 2;
   
   int add(){
       int a = 4;
       int b = 5;
       return a+b;
   } 
   
   int sum;
   sum = add();
   
   DebugN(sum); // 输出:9 而不是输出3 
}

global 保留关键字

public 库内函数可以被调用

private 库内函数不能被外部程序调用,只能自己调用

8 运算符

8.1 算术运算符

// 二元运算符
// + - * / % 
// % 求余运算符不能用于浮点数
// + - 运算符才可用于时间值

time t1, t2;
t1 = t1 - 3600; // 简写 t1 -= 3600 t1减小1小时

8.2 递增/递减运算符

// ++ 自增运算发
// -- 自减运算符
// ++a 在使用a变量之前对a变量加1
// a++ 在使用a变量之后对a变量加1

main()
{
   int a, b, d;
   a = 3;
   b = 5;
   d=a*b++;
   DebugN(d); //++b 的结果 = 18,而 b++ 的结果 = 15
   DebugN(b); //结果总是 = 6
}


8.3 条件运算符

// expr1? expr2 :expr3;
// 判断expr1表达式的值,如果为true执行expr2,如果为false执行expr3,返回值是expr2或者expr3表达式返回的值
main(){
    int a,b;
    a = 1; b =2;
    int res;
    res = (a>b) ? a*10 : b*10;
    DebugN(res); // 20
}
// expr2和expr3表达式一定要返回相同的数据类型

8.4 关系运算符和逻辑运算符

// > >= < <= == !=
// && || !

8.5 位运算符和移位运算符

// & 位与运算符
// 1 & 1 = 1 
// 1 & 0 = 0

// | 位或运算符

// ~ 位非运算符

// ^ 位异或运算符 相同为0 相异为1

// << 左移移位运算符  1 << 2 返回 100

// >> 右移移位运算符  00100 >> 1 返回 00010

main() 

{ 

  bit32 Test; 

  Test=0x8FFFFFFFU;

  DebugN("Firstly",Test);

  Test=Test>>16u;

  DebugN("Secondly",Test);

} 

8.6 赋值运算符

左侧的变量将在右侧最开始处重复。可用更紧凑的形式来书写该表达式:i += 2

// 多重赋值
tag1 = tag2 = tag3 = 1;// tag3=1 tag1和tag2没有赋到值

main()

{
   setMultiValue("RECTANGLE1", "visible", bVisible, "RECTANGLE2", "visible", bVisible, "RECTANGLE3", "visible", bVisible);
}


9 控制结构

9.1 if-else


main(){
    int a,b;
    a = 1; b=2;
    if(a>b){
        DebugN("a>b");
    }
    else{
        DebugN("a<b");
    }
    
}

// if...else... 支持嵌套使用

9.2 switch

main(){
    int y;
    switch(y){
        case 1:DebugN("Monday");
        break;
        case 2:DebugN("Thusday");
        braek;
        default:
        DebugN("error");
    }
}

9.3 while

// 1~100 的和
main(){
    int sum = 0;
    int i = 0;
    while(i<=100){
        sum += i;
        i ++ ;
    }
    DebugN(sum);
}

9.4 do… while…

//  1~100加和
main(){
    int i = 0;
    int sum = 0 ;
    do{
        sum = sum + i;
        i ++;
    }
    while(i<=100);
    DebugN(sum);
}

do…while… 和while的区别是do…while语句至少执行一次,while语句不满足条件一次都会执行

9.5 for循环

// for语法
/* 
for(expr1;expr2;expr3;){
    循环体;
}
*/

// 1-for循环计算0~100加和
main(){
    int sum = 0;
    for(int i=0;i<=100;i++){
        sum+=i;
    }
    DebugN(sum);
}

// 2-for死循环方式1
main(){
    for(;;){
        DebugN("loop always");
    }
}

// 3-for死循环方式2
main(){
    for(int i=0;i<10;){
        DebugN("loop always");
    }
}

9.6 break&continue

main(){
    mapping m;
    m["one"] = 1;
    m["two"] = 2;
    m["three"] = 3;
    for(int i=0;i<mappinglen(m);i++){
        if (mappingGetKey(m,i) == "one"){
            continue;
        }
        DebugN(mappingGetKey(m,i)); 
    }
}
/*
输出:
    "two"
    "three"
*/

main(){
    mapping m;
    m["one"] = 1;
    m["two"] = 2;
    m["three"] = 3;
    for(int i=0;i<mappinglen(m);i++){
        if (mappingGetKey(m,i) == "three"){
            break;
        }
        DebugN(mappingGetKey(m,i)); 
    }
}
/*
输出:
    "one"
    "two"
*/

9.7 try…catch/finally-throw

try-catch 语句可以捕获由 throw() 显式抛出的异常或由脚本错误(例如,未声明的变量、索引超出范围、被零除等)引发的异常。
“被试验”并最终引发异常的代码/语句是在一个 try 块中定义的。如果在执行这些语句过程中发生异常,则执行一个 catch 块或 finally 块。

try 块的后面必须跟有一个 catch 块、一个 finally 或这两个块(以 catch-finally 的顺序)。

catch 块可捕获异常并将其删除。如果还另外跟有一个 finally 块,则在将在 catch 块的后面执行该块。如果没有该块,则将处理 try 块中尚未执行的语句。

finally 块将独立执行,而不管是引发了异常还是提供了 catch 块。随后,在应执行特定代码的每种情况下(如变量重置),finally 块都十分有用,即使此时无法对异常进行处理。

throw(errClass e) 函数会抛出异常 (‘e’)。异常的类型总是 errClass。.

finally-/catch块中的 异常

如果 finally 块中发生异常,则会取消处理,该块继续“前滚”,直到发现下一个 try-catch//finally 块。一个异常总是会由最新/当前异常所取代。

如果在 catch 块中发生异常,则会取消处理,但最终将在对该块“前滚”之前执行现有的 finally 块,以便找到新的 try-catch/-finally 块。一个异常总是会由最新/实际异常所取代。

如果在“前滚”过程中未找到其它 try-catch/-finally 块,则该线程将退出并返回错误消息(“uncaught exception …”)。

main() 
{ 
  try 
  { 
    DebugN("main:try"); 
    throw(makeError("", PRIO_SEVERE, ERR_PARAM, 54, "In main:try")); 
    foo(); 
    DebugN("main:try end"); 
  } 
  catch 
  { 
    DebugN("main:catch"); 
DebugN(getLastException());     
    //抛出(makeError("", PRIO_SEVERE, ERR_PARAM, 54, "In main:catch"));   
    DebugN("main:catch end"); 
  } 
  finally 
  { 
   DebugN("main:finally"); 
    //抛出(makeError("", PRIO_SEVERE, ERR_PARAM, 54, "In main:finally"));   
    DebugN("main:finally end"); 
  } 
    DebugN("main:end"); 
} 
foo() 
{ 
  try 
  { 
    DebugN("foo:try"); 
    throw(makeError("", PRIO_SEVERE, ERR_PARAM, 54, "In foo:try")); 
    DebugN("foo:try end"); 
  } 
  finally 
  { 
    DebugN("foo:finally"); 
    //抛出(makeError("", PRIO_SEVERE, ERR_PARAM, 54, "In foo:finally"));
    DebugN("foo:finally end"); 
  } 
    DebugN("foo:end"); 
} 


未完待续

原创作品,如需转载请注明出处

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kobe_OKOK_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值