# key.hook 库模块帮助文档

<details>  <summary>重要说明</summary>  <p>
勿滥用低级键盘钩子，
普通快捷键不必要使用此钩子，可参考:
aardio 范例 » Windows 窗口 » 快捷键。

低级键盘钩子只能用于界面线程，并且依赖界面线程创建的消息循环。

低级键盘钩子所在界面线程的任何耗时操作执行时间不应超过 200 毫秒。
耗时操作可能导致遗漏部分键盘消息，如果耗时操作阻塞键盘钩子消息超过一秒或超过注册表限制的更小时间，
系统可能会直接删除键盘钩子（导致超级热键不可用）。

建议将阻塞消息循环的耗时操作放到后台工作线程内执行，
请参考：[创建多线程](../../../guide/language/thread.html)。

key.hotkey 源码实现了一种检测键盘钩子状态的方法，主要思路如下：
1. 在收到键盘钩子消息时记录激活状态
2. 使用定时器检测钩子激活状态，如果键盘钩子在一段时间内未收到任何消息，
并且检测的时间段大于 `win.getIdleTime()` 获取的空闲时间，
则用 `key.up(0xFF/*_VK__none_*/)` 或者 `::User32.keybd_event( 0xFF/*VK__none_*/,0,2|8, 0 )`
发送一个无效的虚拟键消息，如果键盘钩子收不到这个消息则重新安装键盘钩子。

具体实现请参考 key.hotkey 源代码。

</p></details>

## key 成员列表 <a id="key" href="#key">&#x23;</a>

### key.hook <a id="key.hook" href="#key.hook">&#x23;</a>
低级键盘钩子。  

低级键盘钩子只能用于包含窗口消息循环的界面线程。  
键盘钩子所在的界面线程如果有阻塞钩子消息的耗时操作，可能导致遗漏键盘消息。  
耗时操作阻塞键盘钩子消息超过一秒或注册表限制的更小时间，系统可能导致钩子失效。  
建议将阻塞消息循环的耗时操作应当放到后台工作线程内执行。

### key.hook() <a id="key.hook" href="#key.hook">&#x23;</a>
创建低级键盘钩子  

[返回对象:KeyHookObject](#KeyHookObject)

## KeyHookObject 成员列表 <a id="KeyHookObject" href="#KeyHookObject">&#x23;</a>

### KeyHookObject.close() <a id="KeyHookObject.close" href="#KeyHookObject.close">&#x23;</a>
释放按键录制钩子

### KeyHookObject.mapKey <a id="KeyHookObject.mapKey" href="#KeyHookObject.mapKey">&#x23;</a>
创建一个映射按键的 proc 。  
用法请参考：范例/自动化/adb/安卓投屏

### KeyHookObject.mapKey(map,owner,hwnd) <a id="KeyHookObject.mapKey" href="#KeyHookObject.mapKey">&#x23;</a>
参数 @map 可在 down 字段指定按键映射表，在 up 字段指定弹起键映射表。  
按键映射表的键应当为 key.VK 定义的虚拟键名，值为 @owner 的成员函数名。  
可选用 @hwnd 限定映射按键的窗口句柄

### KeyHookObject.proc <a id="KeyHookObject.proc" href="#KeyHookObject.proc">&#x23;</a>

```aardio
KeyHookObject.proc = function(msg,vkCode,scanCode,injected,flags,timeStamp,extraInfo){
	if( injected ) return;/*忽略模拟按键*/

    var vkName = key.getName( vkCode );
    select(msg) {
    	case 0x100/*_WM_KEYDOWN*/ ,0x104/*_WM_SYSKEYDOWN*/{
    	    io.print("按下",vkName)
    	}
    	case 0x101/*_WM_KEYUP*/,0x105/*_WM_SYSKEYUP*/{
    	    io.print("弹起",vkName)
    	}  
    }   

	/*返回 true 取消当前按键;  
注意钩子回调函数不要做耗时操作。  
耗时超过一秒或超过注册表限制的更小时间，  
系统会直接删除钩子，没有方法可以直接检查到删除键盘钩子的操作。  
可以参考 key.hotkey 的源码记录并检测键盘钩子的有效状态，在失效时重新安装。  
建议用 win.setTimeout 或创建线程执行耗时操作*/
}
```

### 自动完成常量
_LLKHF_ALTDOWN=0x20  
_LLKHF_EXTENDED=1  
_LLKHF_INJECTED=0x10  
_LLKHF_UP=0x80  
