BizKVM键盘鼠标动作定义

“BizKVM键盘鼠标动作定义”为企顺公司设计的一套描述键盘与鼠标动作的标准,可用于程序自动发送键盘鼠标动作,以及键盘输入的自动验证。

	
键盘按键:
   1.一般情况下,字符串中的字符代表的是该字符所在的键盘,如果字符代表的是键盘再加上Shift,则系统解释执行的时候会自动加上shift功能键。(不同的键盘可能有不同的设计与定义,FWScript可以灵活更改)
   (在微软的SendKeys定义中,+(AB) 为 Shift+A 和 Shift+B,因为在我们的按键字符串定义中, 凡是需要使用shift的字符,发送的时候自动加上了shift, 因此就没有实现这个约定)
   举例:
		"Again"  对应的键盘输入为 shift+a,g,a, i, n
   
   2.针对无法使用某个字符代表的按键情况,则使用特殊的方式表达,称为特殊键盘定义:
      上下左右方向键:使用反斜杠\开头,然后跟^V<>;如"\^"表示向上的方向键。(注意V大写)
      回车\N;制表 \T; F1-F9:\1-\9;(注意都是大写)
	  举例:
			"\>\>\V\N" 表示按“向右的箭头”三下,然后在按“向下的箭头”一下,最后按回车。
			"\V\V\<\^\1" 表示按“向下的箭头”两下,然后向左,再向上,最后按F1。
			
   3.针对像"Ctrl"这样的功能修饰键,往往是跟在所有功能修饰键后的第一个键结合在一起。
      功能键:Alt:\A; Control:\C; Win:\W; Shift:\S或+;Fn:\F;
	   举例:
			"\At" 表示 Alt + t
			"\C\Aa" 表示 Ctrl+Alt+a
			"\Wi" 表示 win+i
	  
   4.可直接使用微软的Keys定义:{enter} {esc} {F1 10} {a 10} ... ... 
   参见: SendKeys定义  (注意微软定义的+(EC)没有在FWScript中实现,因为我们可以直接判断需要shift的字符,圆括号用于定义键盘鼠标动作的集合,参见后面的描述。)
   (注意在微软的定义中,三个符号有特殊的定义:+表示Shift,^表示Ctrl,%表示Alt,如果要使用这三个符号本身代表的键,使用:{+} {^} {%} \+ \% )
		举例:
			"{ctrl}a" 表示 ctrl + a
			"{enter 10}" 表示按回车键10下。(在BizKVM中,也可以用\N*10 代替,参见后面的描述。)
			"{ctrl}{alt}{delete}" 表示ctrl+alt+delete。(在BizKVM中,可以用\C\A{delete}代替)
			"^%{delete}" 也表示ctrl+alt+delete 
         
使用简单的字符描述鼠标动作:
   使用字符'|'开始定义进入鼠标动作的定义,并以|结束;可多次插入到键盘字符串中。(因此'|'为特殊字符,必须使用"\|"代表其本身)
     鼠标移动Move:鼠标的上下左右移动^V<>后跟随数字表示移动的距离, 如^200,表示向上移动200个像素,T表示移动到绝对位置(注意一定是大写),后跟两个数值,中间使用','隔开。
	 如果数值小于1, 则表示移动的距离为屏幕大小的百分比, 如0.5表示屏幕的一半, 也就是50%;
	 举例:
		"|>200V100" 表示鼠标向右移动200个像素,然后再向下移动100个像素
		"|V0.5<100" 表示鼠标向下移动屏幕宽度的一半,然后向左移动100个像素
		"|T0.5,0.6 表示鼠标移到某个具体的位置
	 
     鼠标上下滑动Scroll:Ss上下Scroll后跟数量,大写S表示向上滑动,如S20表示向上滑动20下。
     鼠标单击click:左键点击使用!或c,右键点击使用大写的C,
     鼠标双击double click:左键双击使用小写的d,右键双击为大写的D
     左中右键单独按下Down与松开UP:左键按下为小写的l,松开为大写的L;中建为m,M; 右键为r,R 
		 (注意目前未能实现拖曳的操作)
	 举例:
		"|!" 表示鼠标左键按一下
		"|C" 表示鼠标右键按一下
		"|d" 表示鼠标左键双击一下
	 在鼠标状态下,使用字符'?'表示检查,后跟检查的序号值。 
	  
	  
使用关键字描述鼠标动作:
	使用中括号加上关键字表示输入一个单独的鼠标动作,这种描述方式能增加鼠标动作的可读性。 
	依据如下的枚举的定义,可直接指定一个鼠标动作,如果需要数值参数,则使用冒号再跟一个数值。(注意大小写被忽略,因此无需刻意记住大小写)
	public enum ACTIONTYPE
    {
		// 注意此处数值的设置及顺序的排列纯粹是为了算法的效率的需要
        Waiting = 0, // 相当于等待一段时间,单位为毫秒,后面也可以使用 :5s,:2m这样的描述方式;大写的5S,2M也是受欢迎的。
        Up = 1,   //  鼠标向上移动,举例: [up:16]
        Down = 2,  // 鼠标向下移动, [down:200]
        Left = 3,  // 鼠标向左移动, [left:300]
        Right = 4,  // 鼠标向右移动, [right:2]
		Check = 5,  // 表示在此处进行检查,检查的具体定义根据后面跟的数字参数决定,如1号检查,2号检查。
        MoveAction = 8, // 插入一个隔离的假定义,便于分段处理,程序中利用这个值可以快速分辨鼠标动作的种类
        ScrollUp,  // 查看窗口(view)向上移动,往上看内容(往回看内容) [scrollup:2] 向上滚两格
        ScrollDown, // 查看窗口(view)向下移动,往下看内容 (看后面的内容) [scrolldown:1]向下滚1格

        WithMinus=11, // 用于判断是否需要两个参数以及正负数。第一个参数为上下,向上、向左为负数 
        Move,     // 两个参数的移动,  [move:-23:50]  向上移动23,向右移动50
        LDrag, // 左键抓起,移动后释放, [ldrag:30:-100] 向下移动30,向左移动100
        RDrag,  // 右键抓取,移动后释放, [rdrag:40:20]  向下移动40,向右移动20
		To, // 将鼠标移到具体的位置

        ClickAction = 16, // 插入一个隔离的假定义,便于分段处理
        Click,  //最常用的,鼠标左键点击 
        LClick,   //鼠标左键点击 
        RClick,   //鼠标右键点击 
        MClick,   //鼠标中键点击 
        LDoubleClick, //鼠标左键双击 
        RDoubleClick, //鼠标右键双击
        LDown, // 鼠标左键按下
        LUp,    // 鼠标左键松开
        MDown,  // 鼠标中键按下
        MUp,    // 鼠标中键松开
        RDown,  // 鼠标右键按下
        RUp,     // 鼠标右键松开
        LastOne // 作为最后一个的标记,在C++版本中,需要自动生成一个hash。
    }
		
	举例:
		[LClick] 表示鼠标左键点击一下,[MDown]表示按下鼠标中键。
		[Up:200] 表示向上移动200个像素,[Left:0.5]表示向左移动屏幕的一半。
		[Waiting:20s]表示等待20秒, [Waiting:500] 表示等待500毫秒 
				 
特殊动作与信息:
   1.等待一会再做后面的:=123 表示等待123毫秒 或者 =5s 表示5秒 或者 =2m 表示2分钟(因此'='为特殊字符, 必须使用"\="代表其本身,字符'='的中文为“等于号”,在FWScript使用这个谐音定义符号'='为等待)
   2.占位符: \0为占位符(也可使用{0}),有的时候, 需要直接输入一个功能键如Shift(此处称为“独立功能键”), 则可以用占位符来实现, 如\S\0表示输入一个单独的Shift,  \A\0则表示输入一个单独的Alter。注意,如果独立功能键的定义在最后,或者在进入其他状态之前,则无需占位符,如"abc{win}"表示在最后只输入{win},其它的例子:"{ctrl}*1", "{ctrl}(abc)*2", "{shift}|!|", "{shift}[click]"。 
   3.重复前面的动作:使用星号*表示重复。如a*10 为重复按键'a'10次; \At*9 为重复按“Alter+t" 9次;[lclick]*6 为点击鼠标左键6次, 在鼠标状态下(亦即在两个'|'之间)的 d*20 为双击鼠标左键20次。
   4.音频控制动作:{mute} 表示静音,发1次系统变成静音状态,再发一次取消静音状态;{volume+} {volume-} 为调节音量大小。 也可用{Fn}{F1}表示{mute}(或者使用\F\1);{Fn}{F2}表示{volume-};{Fn}{F3}表示{volume+}。
   5.屏幕亮度控制动作:{brightness+} {brightness-}表示调节亮度,也可用{Fn}{F5}和{Fn}{F6}(或者使用\F\5和\F\6)。
   6.飞行模式控制动作:{airplane}发一次设置成飞行模式,在发一次取消,也可用{Fn}{F8}(或者使用\F\8)。
   7.发送电脑睡眠与关机信号:{sleep},{poweroff},{wakeup} 注意是否起作用要看被控制电脑的实际设置。  8.发送具体的某个HID值:{4}表示输入HID值为4的键,相当于a;{75}相当于pageup。注意目前BizKVM只支持的AT键盘的101键的定义,也就是说HID小于101的值都可以按照标准执行。针对其它的HID值,BizKVM进行了特殊的定义,不建议直接使用。
   9.停下来检查,使用符号?,在非鼠标状态下,为?22。 表示进行第22号检查, 根据检查的返回结果,确定是否继续往下做, 也就是说是否fail to stop。 也可使用[check:22], 在鼠标状态下,也可直接用?, 如“|?22" 。 检查的结果返回值定义:0 成功;1:失败,按照系统的failtostop统一定义是否要中止;2:失败但一定要中止,3:失败但继续执行;
   注意:可以使用Check来实现做其它的动作,如BizFinger的动作,只是在实现这个检查序号的功能时,总是返回成功。
   10.在(之后紧跟一个?并紧跟数字,则表示这个集合执行前的检查,如果返回0则执行,否则跳过这个键盘集合的一次执行,直接执行下一个。(相当于循环里面的continue)
   11.在解释键盘鼠标指令的时候,会忽略里面的空白字符如空格、制表符、换行。当换行后紧跟#(也就是说#位于一行的开头), 则视作这一行为注释行。
   12.在处理键盘鼠标指令的时候,首先会进行一次预处理,预处理将会忽略所有的注释行,还会替换以$开头的预定义标识符, 但如果事先并没有这个预定义符,则不会去替换。使用这个特性,使用者可以实现可读性比较好的键盘鼠标指令,如下所示:
	   #this is for testing bios setting
	   #先按 ctrl+alt+del
	   {ctrl}{alt}{delete}\0 ?$GreenPanel
	   #在按7次tab键移到电源图标处
	   {tab}*7 ?$OnPowerIcon
	   #按回车后出现一个菜单,然后按向下的箭头2次,落在菜单项“关机”上
	   {enter}\V\V{enter} =10s ?$PowerDown
	   #使用BizFinger将电源打开,等待出现可以进入boot的画面,立即按F1键,重复3次
	   ?$PowerOn ?$WaitBootIcon {F1}*3 ?$BootPanel
	   #确认进入Boot画面后,再进行一系列的键盘动作
	   
	注意,上述的所有检查动作都转到调用者的处理程序中,这些处理程序一般是通过摄像头去判别一些内容,
	也可以是去指挥其它的治具,如?$PowerOn执行的就是通知BizFinger去按下电源按钮。

键盘动作的集合:
	使用圆括号'(' ')'代表将中间的一系列键盘鼠标动作看作一个集合, 在其后的重复次数定义(如*10)则表示对这个集合进行重复。 如 abc(efg)*8def 表示 "efg"三个键为一个集合,在这个指令中,为重复efg一共8次。
	扩展:如果是)** 则表示为死循环,依据在执行体里面的检查结果(如“?12”)确定是否退出执行, 注意紧跟(之后的那个检查仅仅用于判断这一轮循环是否跳过,而不会让整个执行退出。
	只要不影响键或鼠标动作的解释,圆括号可以位于任何地方,如 abc(de|v0.5c)*5|fg   ab(c[waiting:5s]t[click]t)t 如果出现在中括号里面,则会报错,如 aaa(bb[click )]ttt,因为它影响了[click]的完整性。
	键盘动作集合可以嵌套,也就是说圆括号里面可以有圆括号,如 aaa(bbbccc(ddd)*3eeefff)*8ggg  
	使用圆括号定义键盘及鼠标动作集合与重复的定义是无关联的,圆括号定义后面可以没有重复的定义,这个时候,默认为执行一次, 但当前对与集合的定义只是用在重复的定义上,还没有引入别的概念(将来有可能引入),因此如果不重复,就没有存在的必要了 

预定义的键盘鼠标字符串:
	针对有些经常用到的键盘鼠标动作字符串,可以放在一个JSON定义文件中,在BizKVM启动的时候,可以读入这些定义。
	在字符串中,使用符号$来表示预定义串。如:假定 $shutdown = "\C\A{Delete}\T*8\N\V\N", 则可以使用 goodbye$ShutDown。
	特别是在设定BIOS的测试中,不同的机器BIOS都会有些差别,但有很多共同的部分,将这些共同的部分设置成预定义字符串,将有利于提升效率。
	预定义字符串可以嵌套使用。如 $A = "aaa", $B="bbb", $ABCD = "$A$Bcccddd";  "itis$ABCD"的最终结果为 "itisaaabbbcccddd" 
	注意替换预定义串是在解释键盘字符串之前进行的,"$A*3" 会变成 "aaa*3" 而不是 "(aaa)*3" (如果要这样,则使用 "($A)*3")
	如果$后面跟随的标识符并没有定义,则一切照原样进行,系统只是有个警告信息,并不会产生错误。
	预定义的JSON结构很简单:[{"classname":"thename", "define":[{"var":"identifier", "value":"string"},...]}, ...] (注意都是小写)
   
特殊字符:
   键盘字符串中有特殊字符如 \ { } [ ] ( ) + ^ %;* $ = | ? (前面的为微软的标准已经定义的,FWScript定义了后面的五个,扩展了()[]的用法)
   如果要输入这些字符代表的键,可以在前面加上反斜杠('\'),如"\|"表示的就是'|'本身,而"|"表示开始的是鼠标动作;
   输入这些特殊字符也可以采用微软的方式使用大括号{},如 {=} {+} 。
   
   有些特殊字符需要规范的定义才能有意义,如*、?与=后面必须跟有数字,如果后面没有跟随,FWScript则会“理解”成使用这个字符本身; 又如字符$,如果后面跟随的内容并不是一个预定义字符串,则照原样使用。
    
  
综合举例:
   '|V0.5>0.5!c|345' 表示 鼠标向下移动一半,再向右移动一半,然后单击鼠标左键,再键盘输入345
   '|!C=500|\>\V\V\V\V' 表示点右键,然后输入右箭头(键盘右移),则输入向下的箭头4次。
   '\A\C{delete}' 表示输入 Alter+Ctrl+Delete 
	


定义特殊的按键

系统提供定义特殊按键的途径,如果在目录c:\bizat\tools\ (注意c:\bizat 为Bizrunner的安装路径) 下存在文件 extraKVMDefine.json,则系统会自动载入这个文件。

Json文件的格式:KeyDefine[] (键盘定义的数组) 

 [DataContract]
    public class KeyDefine
    {
        [DataMember(Order = 0, IsRequired = true)]
        public string key; // 代表在后面键盘串定义define中描述的键,分多种形式:
                            //   如果为单个字符,则使用这个字符代表 (一般很少有这种需求,可以忽略这种情况,适合于有可能某些厂商不按标准设计键盘,如5上面不是%而是别的字符)。
                            //   如果以反斜杠'\'开头,则表示反斜杠的定义,后面需要紧跟对这个键的字符串描述,如"\Llogic", 则表示使用\L表达这个键,描述为”logic“。
                            //   如果以"Fn+"开头,则表示对按下Fn的定义,如“Fn+F1”,表示的是按下Fn,再按下F1时键的定义。 “Fn+k", 为按下Fn,再按下k时的定义。
                            //   其他情况,为一个标识符,为这个标识符代表的键的定义,如”camera”,表示为 {camera} 所代表的定义。

        [DataMember(Order = 1)]  
        public string define; // 对应的key的定义字符串,如果为空,则key可以直接去找对应的 Keys 的定义(枚举字符串)  (注意只适合于反斜杠定义的情况)
                                //  分如下几种情况: 
                                //      如果前面的key为“Fn+”开头,则define必须由三个部分组成,用/分开,如“display/keys/hid”,第一部分为针对这个键显示的内容,第二个部分为对应的微软的键的名称,第三个部分为HID值
                                                    // 注意三部分允许为空,如果HID为空,系统自动依据keys的内容确定出微软的键值定义后,然后换算出HID
                                //      如果以‘+’开头,则表示 shift +  ,也就是说,定义的键是按着shift再按后面指定的键的效果
                                //      定义的剩余部分,如果是数字,则为对应的 Keys 枚举的值,否则为这个字符或者字符串代表的键(必须对应微软的Keys的枚举定义) 
                                // 


        /*  举例:
		 *      [
         *       {"key":"\Llogic", "define":"+F9"},  // 在键盘字符串中,若出现\L,则会解释成 按shift然后按 F9
         *       {"keys":"Fn+F1", "define":"mute//127"},  // 在键盘字符串中,若出现 \F\1,则表示为 mute键 (HID为127) 
         *       {"keys":"ColumeUp", "define":"colume up //128"},   // 在键盘字符串中,若出现 {ColumeUp} 则表示为HID为128的键。  
         *       {"keys":"\Pprtsc",null},  // 在键盘字符串中,可以使用\P 代表 {prtsc}
         *       {"keys":"Fn+k","keypad6//140 }, // 在键盘字符串中,使用\Fk 代表 keypad6,就是有些键盘上按Fn再按k出来6的效果 
		 *		]
		 */
	}