▶ 快速上手
本教程需要一个很小的开源软件 ImTip ( 体积 639 KB )。
关于 ImTip
Jacen He,公众号:aardio电脑必备:通用输入法状态提示,再也不怕按错,再也不用看右下角
请右键点开 ImTip 托盘菜单,然后点击「管理超级热键」:
然后将热键配置改为如下代码,并且勾选「启用超级热键」,再点击「保存」按钮使热键生效。
//大写金额、日期、时间
["Ctrl+$"] = function(hFocus){
win.dlg.chineseNumber().show();
};
//打开调色器
["Ctrl+#"] = function(hFocus){
//创建选色器
var dlg = win.ui.ctrl.pick();
dlg.show();
//置顶
win.setTopmost(dlg.hwnd,true);
};
上面的配置定义了 "Ctrl+$","Ctrl+#" 这两个热键。中括号里是按键名字符串,等号的后面指定要输入的文本或者需要执行的函数对象。
以上热键配置将自动转换为以下 aardio 代码,然后编译执行:
//导入超级热键
import key.hotkey;
//创建超级热键
var superHotkey = key.hotkey(winform);
//批量加载热键配置表
superHotkey.loadTable({
["Ctrl+$"] = function(hFocus){
win.dlg.chineseNumber().show();
};
["Ctrl+#"] = function(hFocus){
var dlg = win.ui.ctrl.pick();
dlg.show();
win.setTopmost(dlg.hwnd,true);
};
});
超级热键配置其实就是一个表对象 ( table )。每个热键配置由等号分隔的键值对组成,等号前面指定热键,等号后面用一个函数指定要执行的代码。多个热键配置使用分号隔开。
如果不会编程没关系,下面会提供可直接复制粘贴的范例,建议先看几个范例 —— 再看看《aardio 语法速览》
aardio 语法速览
Jacen He,公众号:aardioaardio 编程语言快速入门 —— 语法速览
下面看一下 Ctrl + $ 热键运行效果:
Ctrl + # 热键运行效果:
▶ 超级热键检测规则
1、如果首个按下的键不是控制键,则不必同时按住多个键。如果按下的键是已注册的热键前半部分,则阻止当前按键继续发送。如果继续按键已不符合任何热键,则释放已捕获的按键并按原顺序重新发送。
2、如果首次按住的是控制键( CTRL,ALT,SHIFT,WIN 之一),则必须同时按住多个键才算已完成热键。如果这样同时按住的多个键是一个已完成的热键,但同时又是其他热键的前半部分,则必须放开所有键才会生效。
3、如果注册单个控制键热键,并且加上 @ 前缀,则放开该键(且中间没有按其他键)才算完成热键。
4、超键热键中任何键名都只表示该键名所在的按键,不区分上档键。例如热键 "~hi" 指连续按 3 个键,其中的 ~ 键不必按 Shift + ~。
5、超级热键会检测按键顺序,["Ctrl+Shift"] 与 ["Shift+Ctrl"] 是不同的热键。如果希望不同顺序触发同一个回调函数,则需要添加多个热键配置。
示例:
//按连续按 3 个键,每个键都要放开。
["~AA"] = function(){
};
//按下Shift不放,再按2下Q。
["SHIFT+Q,Q"] = function(){
};
//按下Ctrl不放,再按K, 然后都放开。
["Ctrl+K"] = function(){
};
//按下Ctrl不放,再按2次K。
//因为不是其他热键的前半部分,不需要等待放开。
["Ctrl+K,K"] = function(){
};
//表示按下 Shift 键再放开,中间不按其他键,
//通常不会阻止 Shift 切换输入法状态的默认热键。
["@Shift"] = function(){
};
运行 「aardio 自带范例 > Windows 窗口 > 快捷键 > 超级热键」看下效果:
▶ 超级热键回调函数
热键回调函数返回 true 表示允许系统继续发送按键,否则取消该按键,不再继续发送。
例如把斜杠“/”改为顿号的热键配置:
["/"] = function(hFocus){
var openState,mode = key.ime.state();//
if( !openState /*&&(mode==3) */ ) return true;
key.sendString("、")
};
上面的代码检测到当前不是中文标点就执行 return true 允许系统继续发送按键。
如果热键回调函数返回一个函数对象,则取消该按键不再发送,并在返回函数以后异步执行返回的函数对象。
例如输入法纠错热键配置就是这样做的:
["Ctrl+,"] = function(hFocus){
//... 省略其他代码
//通过返回函数异步执行耗时操作
return function(){
key.combine("SHIFT","HOME");
key.combine("CTRL","C");
//... 省略其他代码
};
};
超级热键基于低级键盘钩子,在热键回调中不允许做耗时操作(在热键回调中返回异步执行的函数则不受限制)。
▶ 超级热键配置范例:运行指定程序
//运行计算器
["~calc"] = function(hFocus){
process.execute("calc.exe")
};
//运行word
["~word"] = function(hFocus){
var word = com.CreateObject("Word.Application")
if(word)word.Visible = true;
};
▶ 超级热键配置范例:微软全拼双拼切换
["Ctrl+P"] = function(){
var dpSchemes = tsfInput.getDoublePinyinSchemes();
tsfInput.enableoublePinyinScheme(dpSchemes.default===null);
}
▶ 超级热键配置范例:改键演示
["Ctrl+."] = function(hFocus){
key.up("Ctrl"); //先把已经按下的键弹起来
key.combine("CTRL","A"); //换成别的键,具体看 aardio 库函数文档
return false; //阻止按键事件
};
▶ 超级热键配置范例:取消次选键
[";"] = function(hFocus){
if( winex.msCandidate.isVisible() ){
key.send(" ;")
}
else return true;
};
▶ 超级热键配置范例:按 Shift + Back 变 Ctrl + Z
["SHIFT+BACK"] = function(hFocus){
key.up("SHIFT"); //先把已经按下的键弹起来
key.combine("CTRL","Z")
};
▶ 超级热键配置范例:斜杠“/”改为顿号
["/"] = function(hFocus){
var openState,mode = key.ime.state();//
if( !openState /*&&(mode==3) */ ) return true;
key.sendString("、")
};
▶ 超级热键配置范例:调整音量
//增加音量
["Ctrl+F6"] = function(hFocus){
key.press("VOLUME_UP");
}
//降低音量
["Ctrl+F7"] = function(hFocus){
key.press("VOLUME_DOWN");
}
//切换静音
["Ctrl+F8"] = function(){
key.press("VOLUME_MUTE");
}
▶ 超级热键配置范例:依次按 ~date 输入大写的当前日期
["~date"] = function(hFocus){
var zh = string.chineseNumber('〇一二三四五六七八九');
key.sendString(zh.date()); //改为 zh.time() 输出大写的当前时间
};
注意超键热键中任何键名都只表示该键名所在的按键,不区分上档键。所以 ~ 键不需要同时按 Shift + ~ 。
▶ 超级热键配置范例:按大写自动切换到英文输入
["CAPSLK"] = function(hFocus){
key.ime.setOpenStatus(false);
key.ime.setConversionMode(0);
return true;
};
▶ 超级热键配置范例:右 Shift 键切换为英文
["RSHIFT"] = function(hFocus){
key.ime.setOpenStatus(false);
key.ime.setConversionMode(0);
};
▶ 超级热键配置范例:左 SHIFT 键切换为中文
["LSHIFT"] = function(hFocus){
var openState,mode = key.ime.state();
if( openState && !key.ime.capital() ) return true; //当前已经是中文输入模式,不改变默认行为
key.up("SHIFT");//先放开 SHIFT 键
//如果是大写状态,切换为小写
if(key.ime.capital()) key.press("CAPSLK")
//英文直接切中文 + 中文标点
key.ime.setOpenStatus(true); //打开输入法
key.ime.setConversionMode(1|0x400); //切换到中文状态,这一步不能省略
//再次尝试用键盘切换中文标点,这一步不能省略
key.combine("CTRL",".");
//现在再次检测中文标点状态
var openState,mode = key.ime.state();
if(mode!=3/*_IME_SYMBOLMODE_SYMBOL*/){
//说明切换到了英文标点,再切换回去
key.combine("CTRL",".")
}
};
▶ 超级热键配置范例:按 Ctrl + . 切换到中文输入 + 中文标点 + 小写
["Ctrl+."] = function(hFocus){
var openState,mode = key.ime.state();
if( openState && !key.ime.capital() ) return true; //当前已经是中文输入模式,不改变默认行为
key.up("Ctrl");//先放开 Ctrl 键
//如果是大写状态,切换为小写
if(key.ime.capital()) key.press("CAPSLK")
//英文直接切中文 + 中文标点
key.ime.setOpenStatus(true); //打开输入法
key.ime.setConversionMode(1|0x400); //切换到中文状态,这一步不能省略
//再次尝试用键盘切换中文标点,这一步不能省略
key.combine("CTRL",".");
//现在再次检测中文标点状态
var openState,mode = key.ime.state();
if(mode!=3/*_IME_SYMBOLMODE_SYMBOL*/){
//说明切换到了英文标点,再切换回去
key.combine("CTRL",".")
}
};
▶ 超级热键配置范例:输入法纠错,已输出英文自动转为中文输入
["Ctrl+,"] = function(hFocus){
var openState,mode = key.ime.state();
if( openState && !key.ime.capital() ) return true; //当前已经是中文输入模式,不改变默认行为
key.up("Ctrl");//先放开 Ctrl 键
//如果是大写状态,切换为小写
if(key.ime.capital()) key.press("CAPSLK")
//英文直接切中文 + 中文标点
key.ime.setOpenStatus(true); //打开输入法
key.ime.setConversionMode(1|0x400); //切换到中文状态,这一步不能省略
//再次尝试用键盘切换中文标点,这一步不能省略
key.combine("CTRL",".");
//现在再次检测中文标点状态
var openState,mode = key.ime.state();
if(mode!=3/*_IME_SYMBOLMODE_SYMBOL*/){
//说明切换到了英文标点,再切换回去
key.combine("CTRL",".")
}
//通过返回函数异步执行耗时操作(避免系统删除热键钩子)
return function(){
key.combine("SHIFT","HOME");//选中当前行
key.combine("CTRL","C");//复制当前行
var line = win.clip.read(); //读取剪贴板文本
var str = string.match(line,"[a-zA-Z]+$"); //查找尾部连续字母
key.press("RIGHT");//按右方向键,取消选区
//如果字符串非空
if(#str){
key.repeat("BACK",#str);//按退格键指定次数(取字符串长度)
key.send(str);//字符串转换为发送按键
//key.press("SPACE");//发果需要按空格,请取消前面的注释符号
}
};
};
▶ 超级热键配置范例:粘贴时替换指定的字符
["Ctrl+V"] = function(){
var str = win.clip.read();
if(str && string.find(str,"abcd")){
str = string.replace(str,"abcd","");
win.clip.write(str);
}
return true; //执行默认操作
}
▶ 超级热键配置范例:引号配对
[`SHIFT+"`] = function(hFocus){
if( checkImeProcess(hFocus,"Code.exe") ){
return true;//允许继续发送按键
}
var o,s = key.ime.state();
key.sendString(s==3 ? `“”` : `""`);
//与目标窗口共享输入状态
winex.attach(hFocus,true);
//设置LSHIFT,RSHIFT 为弹起状态
key.up("RSHIFT","LSHIFT","SHIFT");
key.setState(false,"RSHIFT","LSHIFT","SHIFT");
//移动光标
key.press("LEFT");
//取消共享输入状态
winex.attach(hFocus,false);
}
▶ 超级热键配置范例:微软五笔打开或关闭拼音混输
["Ctrl+,"] = function(hFocus){
import win.reg;
var reg = win.reg("HKEY_CURRENT_USER\Software\Microsoft\InputMethod\Settings\CHS");
var mode = !reg.queryValue("PinyinMixEnable") ? 1 : 0
reg.setDwValue("PinyinMixEnable",mode)
key.ime.changeRequest(0x4090409)
key.ime.changeRequest(0x8040804)
};
▶ 超级热键配置范例:切换鼠标左右键
["Ctrl+SHIFT+RIGHT"] = function(hFocus){
::User32.SwapMouseButton(!::User32.GetSystemMetrics(23));
}
▶ 超级热键配置范例:微软五笔叠字键
["`"] = function(hFocus){
var openState,mode = key.ime.state();//用法请查看 aardio 文档
if(!openState
|| mode !=3 || key.getState("Shift")
|| key.getState("Ctrl")
|| key.getState("CAPSLK") ) {
return true; //允许此按键继续发送
}
key.combine("SHIFT","LEFT"); //向后选一个字
key.combine("CTRL","C"); //复制
key.press("RIGHT"); //取消选中
key.combine("CTRL","V"); //粘贴
};
▶ 实现更多功能 ……
ImTip 体积虽然小,但已自带了大量 #aardio# 库。您也可以下载 aardio ,将 aardio 目录下的 /lib/ 目录复制到 ImTip.exe 所在目录 —— 超级热键就可以使用全部的 aardio 库了。
也可以在 /lib/ 目录下新建用户库,然后通过 import 语句导入超级热键。
超级热键配置本质是一个表对象 (table),不但可以包含键值对,也可以包含数组成员。利用这个特性可在超级热键配置内直接执行代码。例如添加一个检测当前窗口启动程序名的全局函数 checkImeProcess,然后使用该函数检测目标窗口的启动程序文件名:
(function(){
var lastFocus,lastPath,lastClass;
checkImeProcess = function(hFocus,exeFile){
if(lastFocus != hFocus){
lastClass = win.getClass(hFocus);
var tid,pid = win.getThreadProcessId(hFocus);
lastPath = process.getPath(pid);
lastFocus = hFocus
}
return (lastPath && io.splitpath(lastPath).file == exeFile )
}
})();
//引号配对
[`SHIFT+"`] = function(hFocus){
if( checkImeProcess(hFocus,"Code.exe") ){
return true;//允许继续发送按键
}
var o,s = key.ime.state();
key.sendString(s==3 ? `“”` : `""`);
//与目标窗口共享输入状态
winex.attach(hFocus,true);
//设置LSHIFT,RSHIFT 为弹起状态
key.up("RSHIFT","LSHIFT","SHIFT");
key.setState(false,"RSHIFT","LSHIFT","SHIFT");
//移动光标
key.press("LEFT");
//取消共享输入状态
winex.attach(hFocus,false);
}
比较常用的按键、文本输入函数:
//发送字符串
key.sendString("这里是要发送的字符串")
//发送按键
key.send("/")
//发送按键
key.press("ENTER")
//判断中文输入法是否打开,打开则执行花括号中的语句
if( key.ime.state() ){ }
更多库函数用法请参考 aardio 自带的《库函数文档》,或者 aardio 自带的范例:
aardio 也支持很多第三方编程语言,例如 C语言、C++、C#、Java、Python、R、Javascript、Node.Js、Fortran、VB、PHP、VBScript、PowerShell、NewLISP、AutoLISP、Delphi、FreeBASIC、Ruby、Rust、Julia、Nim、Go 语言、批处理 ...... 用法请参考 aardio 自带范例。