您的位置:首页 > 其它

SCADA实例分析之一 --- 计算器页面之 SCADA实现

2012-09-02 13:22 369 查看
本文以用APL SCADA实现的 计算器页面 来介绍 APL SCADA原理和 scada脚本写法.

这个页面可以用 APL平台提供的 浏览器使用.

该页面由我同事Vocational在接触APL后写出, 我加上了相关批注, 对此向Vocational表示感谢!

包含两个文件:

        1. 可视化设计描述文件: calc.sca

2. 脚本处理文件: calc.scax

入口文件:

        calc.sca

-----------------------------------------------------------------------------------------------------------------------------------------

1. calc.sca文件:

/*
此sca页面是 我同事Vocational尝试用 APL平台写出来的 计算器应用.
我在此 页面加上了批注, 特别地在批注中 加上了对APL和内核的原理解析.
在此对我同事 Vocational表示感谢.

以下代码中相关注释部分: 以 "Paul:" 开始的地方是我的批注.
paul
2012-09-02

Paul:

一. APL中 scada基础知识介绍:

APL scada是 基于APL基础平台技术和apl脚本技术的基础上, 并参考HTML设计原理, 实现的组态应用平台.

其中 *.sca文件为 scada页面的可视化设计描述部分.
*.scax文件为 scada页面的 apl脚本部分.

sca文件其实是 特殊的apl脚本文件, 里面增加了 scada库功能部分.

1. sca文件中 可视化设计部分.

#begin design scada
#end design scada

APL平台中的 可视化设计工具(aplSCADA_Tool.exe)将会识别 这个标记段, 并在可视化保存的时候, 替换上述段的内容.

另外apl脚本中支持嵌入 特定的节点型描述语言, 在 sca文件中, 是用 <LDL> </LDL>段来描述 可视化积木信息的.
关于LDL请参考 APL文档中 关于LDL语言的介绍.

2. APL scada基础规范:

A. APL scada窗体类似 浏览器窗体, 是一个 元素容器 + 脚本事件处理的 窗体.

APL scada窗体 对应在 某个页面中的变量是 $$scadaWnd, 脚本中可以利用这个对象 处理窗体属性和方法.
APL scada窗体 中放置一个 根积木(容器积木(brick_combination))占满APL scada窗体, 对应在页面中的变量是 $$I, 其他积木是 放在 $$I里面( 支持多层积木关系 )
APL scada窗体 在 页面中放置了 $$main变量, 这个留给 exe开发者的接口, 让exe开发者可以在 exe框架中 提供扩展的脚本方法库.
比如: 在APL scada脚本处理中, 如果希望 主程序框架处理一个命令, 可以调用 $$main->onCmd( $cmd ) ; 让exe开发者处理 onCmd动作.

B. 积木的UI基础属性( 这个可以参考HTML中box模型 ), 包括了 外部空白(Margin) + 内部空白(Padding) + 边框(Border) + 背景(Background) )

3. 可视化设计基础:

在可视化设计过程中, UI工程师 放到页面的积木 会自动分配 脚本中变量名( $xxx ), 这样 软件工程师可以利用积木变量名操作积木.

4. APL scada原理:

A. APL scada窗体构建 脚本上下文( context ), 准备全局对象( $$main, $$scadaWnd ... )
B. 转给 脚本引擎(aplScriptEngine.dll) 加载脚本( xxx.sca ).
C. APL scada窗体 在脚本加载完成后, 检查上下文中的 $$I变量, 把$$I以及$$I包容的积木描述 转换成 积木对象, 并完成 积木对象到积木描述的聚合处理.

以$$I为例, <LDL>中描述的$$I实际是以 万能容器 实现的, 当脚本加载完成, APL scada窗体再把$$I转为APL scada窗体中的 积木对象,
并完成对 对应的$$I万能容器对象的聚合.
因此, 请注意: 脚本中积木对象在 加载过程中 和 加载完成后, 是有区别的.

D. 事件处理:

积木的事件用 属性存储, 当触发事件时候, 再转给 脚本引擎解析脚本执行.

如:
$brick_0.onClick = 'onZero();'; // 这个定义 $brick_0积木的 onClick事件处理: 调用onZero()方法.

*/

#begin design scada
<LDL>

# Paul:
# 根积木定义
# 积木背景支持了: 颜色填充( 支持alpha, 支持渐变填充 )/图片(各种方式)/ 颜色填充+图片(因图片可以支持alpha)
% $$I
[type] brick_combination
[border.type] none
[bgn.type] common
[bgn.color] DarkBlue
[bgn.color2] White
[bgn.fillStyle] TopToBottom

# 这是根积木的 子积木描述, 注意: 可以调整子积木次序.
% $$I.sons
[] $brick_result
[] $brick_flag
[] $brick_0
[] $brick_1
[] $brick_2
[] $brick_3
[] $brick_4
[] $brick_5
[] $brick_6
[] $brick_7
[] $brick_8
[] $brick_9
[] $brick_mc
[] $brick_mr
[] $brick_ms
[] $brick_backspace
[] $brick_ce
[] $brick_clear
[] $brick_sign
[] $brick_dot
[] $brick_mod
[] $brick_fraction
[] $brick_calc
[] $brick_add
[] $brick_sub
[] $brick_mul
[] $brick_div
[] $brick_mplus
[] $brick_sqrt

#Paul: 这是 结果输出框, edit积木, 是CEdit包装.
% $brick_result
[type] brick_Edit
(x) 6
(y) 8
(width) 220
(height) 26
[border.color] Blue
[border.type] common
(text) 0.
(WS_VISIBLE) 1
(WS_EX_CLIENTEDGE) 1
(ES_RIGHT) 1
(ES_READONLY) 1
(ES_AUTOHSCROLL) 1
(font.name) 宋体
(font.size) 18
(font.weight) 400

#Paul: brick_Static积木功能完全可以被 brick替代, 只为支持 CStatic测试
% $brick_flag
[type] brick_Static
(x) 8
(y) 42
(width) 30
(height) 26
[border.color] Blue
[border.type] common
[bgn.type] none
(font.name) 宋体
(font.size) 18
(font.weight) 400
(staticType) SS_CENTER

#Paul: brick_Button为 CButton包装
% $brick_backspace
[type] brick_Button
(x) 45
(y) 40
(width) 80
(height) 30
[border.color] Blue
[border.type] common
(text) BACKSPACE
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 12
(font.weight) 200

% $brick_ce
[type] brick_Button
(x) 128
(y) 40
(width) 60
(height) 30
[border.color] Blue
[border.type] common
(text) CE
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_clear
[type] brick_Button
(x) 192
(y) 40
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) C
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_mc
[type] brick_Button
(x) 6
(y) 74
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) MC
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_7
[type] brick_Button
(x) 45
(y) 74
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 7
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_8
[type] brick_Button
(x) 82
(y) 74
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 8
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_9
[type] brick_Button
(x) 119
(y) 74
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 9
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_div
[type] brick_Button
(x) 156
(y) 74
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) /
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_sqrt
[type] brick_Button
(x) 193
(y) 74
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) sqrt
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_mr
[type] brick_Button
(x) 6
(y) 106
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) MR
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_4
[type] brick_Button
(x) 45
(y) 106
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 4
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_5
[type] brick_Button
(x) 82
(y) 106
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 5
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_6
[type] brick_Button
(x) 119
(y) 106
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 6
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_mul
[type] brick_Button
(x) 156
(y) 106
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) *
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_mod
[type] brick_Button
(x) 193
(y) 106
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) %
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_ms
[type] brick_Button
(x) 6
(y) 138
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) MS
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_1
[type] brick_Button
(x) 45
(y) 138
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 1
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_2
[type] brick_Button
(x) 82
(y) 138
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 2
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_3
[type] brick_Button
(x) 119
(y) 138
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 3
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_sub
[type] brick_Button
(x) 156
(y) 138
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) -
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_fraction
[type] brick_Button
(x) 193
(y) 138
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 1/x
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_mplus
[type] brick_Button
(x) 6
(y) 170
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) M+
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_0
[type] brick_Button
(x) 45
(y) 170
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) 0
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_sign
[type] brick_Button
(x) 82
(y) 170
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) +/-
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_dot
[type] brick_Button
(x) 119
(y) 170
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) .
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_add
[type] brick_Button
(x) 156
(y) 170
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) +
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400

% $brick_calc
[type] brick_Button
(x) 193
(y) 170
(width) 35
(height) 30
[border.color] Blue
[border.type] common
(text) =
(WS_VISIBLE) 1
(font.name) 宋体
(font.size) 14
(font.weight) 400
</LDL>
#end design scada

//Paul: 加载 脚本处理部分
// 也可写为: include "/calc.scax" ;
// 两者差异是 include( "/calc.scax" ) ; 调用会获得方法的返回值, 而上述写法不会取返回值.
include( "/calc.scax" ) ;

-----------------------------------------------------------------------------------------------------------------------------------------

2. calc.scax文件:

// Paul: 各个积木的事件定义.

#数字键功能
$brick_0.onClick = 'onZero();';
$brick_1.onClick = 'onInput("1");';
$brick_2.onClick = 'onInput("2");';
$brick_3.onClick = 'onInput("3");';
$brick_4.onClick = 'onInput("4");';
$brick_5.onClick = 'onInput("5");';
$brick_6.onClick = 'onInput("6");';
$brick_7.onClick = 'onInput("7");';
$brick_8.onClick = 'onInput("8");';
$brick_9.onClick = 'onInput("9");';
$brick_dot.onClick = 'onDot();';

#存储键功能
$brick_mc.onClick = 'onMC();';
$brick_mr.onClick = 'onMR();';
$brick_ms.onClick = 'onMS();';
$brick_mplus.onClick = 'onMPlus();';

#退位,退格
$brick_backspace.onClick = 'onBackSpace();';

#清除当前
$brick_ce.onClick = 'onClear();';

#清除所有
$brick_clear.onClick = 'onReset();';

#运算
$brick_sign.onClick = 'onSign();';
$brick_mod.onClick = 'onPercent();';
$brick_fraction.onClick = 'onFraction();';
$brick_add.onClick = 'onAdd();';
$brick_sub.onClick = 'onSub();';
$brick_mul.onClick = 'onMul();';
$brick_div.onClick = 'onDiv();';
$brick_sqrt.onClick = 'onSqrt();';

#计算最终结果
$brick_calc.onClick = 'onCalc();';

#全局变量
$isFirstInput = 1; #是否是第一次输入
$store = 0;
$op1 = 0;
$op = 0; #0=无操作,1=加,2=减,3=乘,4=除

// Paul:
// 脚本中方法定义: function( ... ) { ... }
function TrimZero($str){#去掉结果最右边没用的0
if(isString($str)){
$text = trimRight($str,"0");
if(getRight($text,1) == "."){
$text = trimRight($text,".");
}

return $text;
}
return $str;
}

function onZero(){#输入0,需要检查多次输入的是否都是0,多次输入的都是0那么实际只显示一个0
/*
Paul:
当方法中使用全局变量, 需要用 extern $xxx ; 申明.
*/

extern $brick_result;
extern $isFirstInput;

$text = $brick_result->getText();
$len = strlen($text);

if($len == 1){
if(getElement($text,0) != "0"){
onInput("0");
}else{
$isFirstInput = 0;
}
}else{
onInput("0");
}
}

function onInput($char){#通用输入
extern $brick_result;
extern $isFirstInput;

if($isFirstInput != 0){
$isFirstInput = 0;
$brick_result->setText($char);
}else{
$text = $brick_result->getText();
$text += $char;
$brick_result->setText($text);
}
}

function onBackSpace(){#退格
extern $brick_result;

$text = $brick_result->getText();
$len = strlen($text)-1;
if($len > 0){
$text = getLeft($text,$len);
$brick_result->setText($text);
}
}

function onClear(){#清除当前
extern $isFirstInput;
extern $brick_result;

$isFirstInput = 1;
$brick_result->setText("0.");
}

function onReset(){#全部清零
extern $isFirstInput;
extern $op1;
extern $op;
extern $brick_result;

$isFirstInput = 1;
$op1 = 0;
$op = 0;
$brick_result->setText("0.");
}

function onCalc(){#计算
extern $op;
extern $op1;
extern $isFirstInput;
extern $brick_result;

$isFirstInput = 1;

if($op == 0){#直接点击=按钮
$op1 = toReal($brick_result->getText());
}

if($op == 1){#加法
$op1 += toReal($brick_result->getText());
}

if($op == 2){#减法
$op1 -= toReal($brick_result->getText());
}

if($op == 3){#乘法
$op1 *= toReal($brick_result->getText());
}

if($op == 4){#除法
$tmp = toReal($brick_result->getText());
if($tmp != 0){
$op1 = $op1 / $tmp;
}else{
messageBox(NULL,"被除数为零!");
}
}

$brick_result->setText(TrimZero(toString($op1)));

$op = 0;
}

function onAdd(){#加法处理
onCalc();

extern $op;
$op = 1;
}

function onSub(){#减法处理
onCalc();

extern $op;
$op = 2;
}

function onMul(){#乘法处理
onCalc();

extern $op;
$op = 3;
}

function onDiv(){#除法处理
onCalc();

extern $op;
$op = 4;
}

function onSqrt(){#求平方根
extern $brick_result;

$tmp = toReal($brick_result->getText());
if($tmp > 0){
$brick_result->setText(toString(sqrt($tmp)));
}else{
messageBox(NULL,"负数不能求平方根!");
}
}

function onPercent(){#求百分数
extern $brick_result;

$tmp = toReal($brick_result->getText());
$tmp = $tmp*100;
$brick_result->setText(toString($tmp));
}

function onFraction(){ #求倒数
extern $brick_result;

$tmp = toReal($brick_result->getText());
if($tmp != 0){
$tmp = 1/$tmp;
$brick_result->setText(toString($tmp));
}
}

function onSign(){#求相反数
extern $brick_result;

$tmp = toReal($brick_result->getText());
$tmp = 0-$tmp;
$brick_result->setText(toString($tmp));
}

function showFlag($flag){#标志显示
extern $brick_flag;
$brick_flag->setText($flag);
}

function onMC(){#清除存储在存储器的数据
extern $store;
$store = 0;

showFlag("");
}

function onMS(){#存储当前数据到存储器
extern $store;
extern $brick_result;

$store = toReal($brick_result->getText());

if($store != 0){
showFlag("M");
}
}

function onMR(){#显示存储在存储器的数据
extern $store;
extern $brick_result;

$brick_result->setText(TrimZero(toString($store)));
}

function onMPlus(){#将当前的数据和存储器中的数据相加,结果放到存储器中
extern $store;
extern $brick_result;
$store += toReal($brick_result->getText());

if($store != 0){
showFlag("M");
}
}

function findchr($strSrc,$ch){#在字符串中查找字符
$len = strlen($strSrc);

while($len > 0){
if(getElement($strSrc,$len) == $ch){
return $len;
}
$len -= 1;
}

return -1;
}

function onDot(){#输入.的时候要检查之前是否含有小数点
extern $brick_result;

if(findchr($brick_result->getText(),".") <0){
onInput(".");
}
}

----------------------------------------------------------------------------------------------------------

可视化工具 + 运行 截图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: