key键盘库

 

一、基础

什么是「键名」

「键名」是一个表示键盘上指定键的字符串。与ApeML「模拟区块」中使用的「键名」一致。
「键名」是键盘上的按键名称。键名必须是大写,不能包含空格。

按Ctrl + k快捷键呼出键名输入框,在键名输入框中按键可直接生成键名,回车即可自动输入到编辑器中,并根据代码自动添加引号、逗号等.

二、模拟按键

key.press(...)

如果只有一个参数,那么应当是一个表示键名的字符串参数。
如果有多个参数,那么第一个参数应当是表示延时的数字参数,后
面可以有不定个数的表示键名的字符串参数.
如果延时为零,表示同时按下的组合键。

例:

key.press(500,"A","B","C","D"); -- 间隔0.5秒,依次按下A,B,C,D四个键

key.press(0,"CTRL","ALT","A"); -- 同时按下组合键Ctrl + Alt + A;

key.press("A"); --按下A键,也可以仅指定一个键名

key.pressIO(...)
使用硬件指令模拟按键,仅支持支持标准PS/2键盘。
必须以管理员身份登录系统,必须删除其他键盘模拟类软件。

用法与key.press完全相同。

key.down(k,flush)
key.up(k,flush)


参数k为键名,参数flush指定是否立即输出(如果省略或为false则输出到「键盘缓冲区」)
在以下几种情况下,缓冲区会输出按键命令到系统。
1、指定flush参数为true
2、所有按键都已释放(即没有键保持按下状态)
3、超出缓冲区大小(模拟精灵 v6.90版本缓冲可容纳18个键盘指令、超出则自动发送)

什么是「键盘缓冲区」

使用软件模拟时,模拟精灵会缓存要发送的键盘指令,直到接收到一组完整的指令以后会才会向系统发送。
缓存软件模拟指令的内存称为「键盘缓冲区」

例:

key.down("B"); --将A键按下的指令发送到输出缓冲(等待发送)
key.down("A",true); --直接发送A键按下的指令
key.up("A",true); --直接发送A键按下的指令

key.down(k[,...])
key.up(k[,...])

参数为任意多个键名,模拟精灵将会把所有按键命令发送到“键盘缓冲区”

例:

key.down("A","B","C"); --将ABC按下指令发送到输出缓冲(等待发送)
key.up("A","B","C"); --将ABC弹起指令发送到输出缓冲(等待发送,因为所有的键都已弹起导致自动发送缓冲区所有按键)

key.downIO(k,...)
key.upIO(k,...)

使用硬件指令模拟按键,仅支持支持标准PS/2键盘。
必须以管理员身份登录系统,必须删除其他键盘模拟类软件。

参数为任意多个键名,直接发送硬件指令(硬件指令无缓冲区,也没有添加flush参数的用法)

例:

key.downIO("A");
key.downIO("A","B","C");
key.upIO("A","B","C");


注意:

在任何时候,都推荐大家使用key.press() key.pressIO() 取代上面的函数

例如:按shift + 9

key.down("SHIFT");
key.down("9");
key.up("SHIFT")
key.up("9")

上面的写法与 key.press(0,"SHIFT","9") 作用相同,但是key.press(0,"SHIFT","9")效率更好。
大多时候我们没有必要把事情复杂化。

三、检测键盘状态

d = key.getState(keyName)
d = key.getStateX(keyName)

keyName参数指定键名,这两个函数以不同的方式检测指定的键是否被按下。返回布尔值.如果键被按下返回true;
key.getState 检测已经被应用程序处理的按键,而key.getStateX 检测按键最新状态
key.getStateX不能检测模拟发送的按键。

注意:

仅在键盘上的键被按下时, key.getState或key.getStateX才会返回true;
通常这两个函数用来配合其他的键盘监视函数检测组合键状态。而不是用来等待按键



下面是一个完整例子:

win.consoleOpen();
print("请按A键");

while(nStop()) do
    if(key.getState("A"))then
        print("您按下了A键,请按ESC键退出");
    end;

    if(key.getState("ESC"))then
        break;
    end;
end;

win.consoleClose();

四、等待按下指定键

key.waitKey(k)
等待按下指定键,k参数指定键名.

五、监视硬件端口

监视硬件端口仅支持支持标准PS/2键盘。
必须以管理员身份登录系统,必须删除其他键盘模拟类软件。

监视硬件端口仅适用于「fap模拟程序」,不适用纯「LAS脚本程序」。

k = key.getDnIO()
等待按下一个键,返回值为键名。
k = key.getDnIO(false)
等待按下一个键,同时禁止按键指令继续发送,返回值为键名。
k = key.getUpIO()
等待弹起一个键,返回值为键名。
k = key.getUpIO(false)
等待弹起一个键,同时禁止弹起键指令继续发送,返回值为键名。

下面是一个完整示例程序,等待用户按下一个键

win.consoleOpen();
print("请按任意键,按ESC键退出");

local keyName;
while( nStop() ) do
   keyName = key.getDnIO(true);
   print("您按下了".. keyName);

   if keyName=="ESC" then
      break; --注意一定要设置一个停止热键,不然会一直循环下去了
   end;
end;

--当然你也可以不用上面的循环,
--直接用一句 keyName = key.getDnIO();等待按下一个键就继续后面的代码

k,down = key.getIO(true)
等待按下一个键,返回值为键名,如果是按键返回值down为true、释放则为false。

六、监视键盘

key.get(mode,hook)
函数启动HOOK功能监测鼠标键盘事件,
第一个参数指定模式,0:监视鼠标键盘 1:仅监视键盘 2:仅监视鼠标
win9x系统mode参数只能为0。

原则上用这个函数,你也可以写一个小型的模拟精灵,实现录制生成脚本的功能。
也可以方便的在模拟程序中,响应用户的鼠标键盘事件。

key.get()函数有两种用法

1、函数有返回值,等待用户按键,不调用key.getProc

m,k,x,y =key.get(mode)
m,k,x,y =key.get(mode,false)

返回值m为字符串,表示发生的事件源,k为键名,x、y为鼠标事件的坐标值。
如果m是鼠标事件 k等于空,x,y为坐标值。
如果m是键盘事件 k等于键名,x,y为零。

例:
m,k,x,y = key.get(0)


2、函数无返回值,不等待用户按键而立即返回,监测到鼠标键盘事件自动执行 key.getProc

key.get(mode,true)

例:

win.consoleOpen();

key.getProc = function(m,k,x,y)
   print(m,k,x,y);
   return true;
   --返回true表示继续hook,返回false停止hook,
   --如果使用key.get第一个参数为1或者2
,则可以通过返回_FALSE禁止监测到的按键继续发送

end;

key.get(1,true);

delay(0);


要注意的几个问题:

1、key.get* 系列函数只能用于「fap模拟程序」,不能用于「纯LAS脚本程序」。
2、key.get()的有效范围为当前脚本区块,脚本区块执行完成, key.get()无条件释放hook
3、key.get()会自动忽略所有的鼠标移动事件
4、如果使用key.get第一个参数为1或者2,则key.getProc可以返回_FALSE禁止监测到的按键继续发送

下面是一个完整的例子,请在fap程序中新建一个脚本区块在脚本区块中添加以下脚本

-- 回调函数
key.getProc = function(m,k,x,y)
    if(k=="ESC")then--如果按下了ESC键
        if(key.getState("SHIFT") ) then--并同时按下了SHIFT键
            print("您按下了Shift + Esc")
            stop(); --退出模拟程序 等于用户按停止
            return false; --取消HOOK
        end;
    end;
   
    return true; --继续hook, --返回false停止hook
end;
 
 
-- 如果是NT系统(2000,xp,2003等)推荐用模式1
if(win.version.isNT)then
    key.get(1,true); --启用键盘监视
else
     key.get(0,true); --启用键盘监视
end;
 
 
win.consoleOpen(); --打开控制台
print("按SHIFT+ESC组合键退出循环")
 
-- 循环,注意要用nStop()检测是否停止。
while( nStop() ) do
    delay(1000);--延时一秒
    print(os.time()); --打印当前时间
end;


七、多线程模拟按键的例子

模拟精灵通过win.exec执行脚本、或者执行脚本文件可以启动多线程。

strO=[[LAScript:
while( nStop() ) do --注意要用while循环,nStop检测用户是否按了全部停止
    key.press("O")
    delay(1000*3)
end;
]]
 
strL=[[LAScript:
while( nStop() ) do --注意要用while循环,nStop检测用户是否按了全部停止
    key.press("L")
    delay(1000*2)
end;
]]
 
win.exec(strO); --启动新线程
win.exec(strL);--启动新线程


八、自动注册热键

热键方案--热键绑定列表 可以导出为文件、也可以从文件导入。
这样我们可以轻松的定义一组热键方案、并快速更换一组热键。
另外,LAScript提供自动注册热键的函数 key.regHK()

ok,err = key.regHK("程序文件路径",k1,k2,k3...)


除第一个参数为执行程序、模拟程序路径以外,其他参数为指定组合键的键名,
键名可以有任意多个,但键名不能重复,热键规则与“模拟精灵->热键方案”相同。

如果注册热键成功,第一个返回值为true,第二个返回值为空(nil)。
如果注册热键失败,第一个返回值为false,第二个返回值为错误信息(string字符串类型);