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

本文以用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(".");
 }
}

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

可视化工具 + 运行 截图:

 

 


 

 

 

 

 

 

 

 

posted on 2012-09-02 13:22  smartfish_liu  阅读(1457)  评论(0编辑  收藏  举报

导航