自定义注册热键类, 保证稳定同时可覆盖注册已注册过的热键
By
圣地
at 2021-12-23 • 0人收藏 • 968人看过
import win.ui; /*DSG{{*/ var winform = win.form(text="aardio form";right=759;bottom=469) winform.add( button={cls="button";text="Button";left=282;top=183;right=609;bottom=289;z=1} ) /*}}*/ import console; import key.hotkey; class reghotkey{ ctor( winform ){ var superHK = ..key.hotkey(winform) var modArr = {Alt=1,Ctrl=2,Shift=4,Win=8} var regHkId = {}; }; reg = function(func, hotkeyStr){ var mod = 0; var vk; if(..string.find(hotkeyStr,"@+")){ var retArr = ..string.split(hotkeyStr,'+') var lastKey = retArr[#retArr] vk = ..key.getCode(lastKey) for(i=1;#retArr-1;1){ mod += modArr[retArr[i]] } }else { vk = ..key.getCode(hotkeyStr) } var ret = winform.reghotkey( func , mod, vk) if(ret){ //这时可以用超极热键来注册 ..console.log("------- reg 方式 --------------",hotkeyStr) }else { ..console.log("------- hook 方式 --------------",hotkeyStr) superHK.regStr(hotkeyStr,func ) } }; unreg = function(){ superHK.clear() for(k,v in winform._hotkeys){ ..console.log(k,v) winform.unreghotkey(k) } } } var hk = reghotkey(winform) hk.reg(function(){ console.log(3333) },"F2") hk.reg(function(){ console.log(5555) },"Win+A") hk.reg(function(){ console.log(6666) },"Ctrl+A") winform.button.oncommand = function(id,event){ hk.unreg() } winform.show(); win.loopMessage();
钩子热键有时会不稳定(如远程桌面连接后有时会失效),RegisterHotKey 方式个别键又无法注册
用上面方法优先用 RegisterHotKey 来注册,如果不成功再用钩子方式。
Update 2021-12-24 10:40 增加卸载热键功能,这样会将所有热键全部卸载掉,如果说要修改某个本程序内已注册的热键只需要 unreg() 然后根据热键字符串重新注册就可以了,
如果要单独修改某个热键,对 RegisterHotKey 还可以根据热键ID卸载后重新注册一个,但超极热键无法单独修改,这样操作代码写起来简洁省事,速度也很快。
6 个回复 | 最后更新于 2021-12-24
A用远程桌面连接B后,B上的低级键盘钩子程序有时会失效,这个也不好重现出来,只是有时会,当时查的资料是说一定时间内执行不完相关动作,Win7以上系统会没有任何提示情况下释放钩子。解决方法可以改个注册表加大一个时间的方法。
//贴一下当时查的资料 https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/f6032ca1-31b8-4ad5-be39-f78dd29952da/hooking-problem-in-windows-7?forum=windowscompatibility https://stackoverflow.com/questions/48695720/setwindowshookex-hook-stops-working https://stackoverflow.com/questions/14596117/setwindowshookex-wm-keyboard-ll-not-coming-through-with-full-screen-rdc 远程桌面导致挂钩不工作 https://kb.vmware.com/s/article/1009409 用vmware虚拟机时出现钩子不能用,可以手动注册表创建超时项目建议改为5000 VC底层钩子程序在Win7/Vista下无效 Source: https://www.cnblogs.com/braver/articles/2557961.html HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout //Win10中默认没有这个项,可以手动创建: 新建>DWORD32值,类型改为10进制写入5000 该值以毫秒为单位。如果挂接过程超时,系统会将消息传递到下一个挂接。但是,在 Windows 7 及更高版本上,钩子会静默地删除,而不会被调用。应用程序无法知道钩子是否已移除。 注意调试挂钩无法跟踪这种类型的低级键盘挂钩。如果应用程序必须使用低级挂钩,则应在专用线程上运行挂钩,该线程将工作传递给工作线程,然后立即返回。在大多数情况下,应用程序需要使用低级挂钩,它应该改为监视原始输入。这是因为原始输入可以异步监视针对其他线程的鼠标和键盘消息,这些消息比低级钩子更有效。有关原始输入的详细信息,请参 阅原始输入。 https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85) 以上信息说明了,会有超时的情况导致 钩子失效: 对Win7以下,系统会将消息传递到下一个挂接。 对Win7以上,系统会悄悄的静默删除挂钩并不给出任何提示。 解决办法( 这是我当时瞎总结的,也没有实际测试不一定对 ): 改注册表将超时时间改大一点如 5000ms 用专用线程运行挂钩 改为原始钩子,既扩展库 win.win.rawInput; 底层输入设备钩子
360这个有时会弹出键盘被监控,这个情况所有键盘钩子类程序都这样,AHK 也这样。
我是想怎么能减少这类情况所以用 RegisterHotKey 替代,这样也可以在出现钩子1/100失效情况和360拦截情况下不至于不工作,所以用了上述方法,
AHK不是高手、aardio更不是,这个问题不懂。
登录后方可回帖
以前用的纯钩子方法,受到限制不只远程桌面 还有360什么的,然后如果加上//RUNAS//误报也会增加( 待进一步验证 ),尽可能用系统标准注册热键方式,保证软件基本可用,不至于出问题热键完全不能用。
我在看了AHK的实现方法也是这么干的,算是相对比较稳定的方法了,能尽可能的保证不会出错