1. 程式人生 > >AutoHotInterception使用說明翻譯,以及解釋,願願原創。

AutoHotInterception使用說明翻譯,以及解釋,願願原創。

上一篇通過聯想m300多功能光電滑鼠側鍵的重新定義,引進了AutoHotInterception。但說實話,這是相當粗糙的敘述。以下,我將,一邊翻譯原文,一邊解釋,讓讀者們,更好的使用這個工具。

首先,講AutoHotInterception離不開[Interception Driver](http://www.oblita.com/interception) 攔截驅動軟體。(原文我就不貼了,只翻譯並解釋,有興趣的看看以上的網頁)

Interception What’s Interception?

何為Interception?

它是攔截系統與windows裝置通訊的程式設計介面軟體工具。

我能用它來幹什麼。

Currently, with Interception you are able to intercept and transform input data from keyboard and mouse. Support is still Windows only (from Windows XP to Windows 10).

目前,用它能夠攔截並轉換從鍵盤和滑鼠傳送來的輸入請求。僅支援微軟windows,win xp到win10。

這個功能我可以用windows鉤子來做,有什麼問題嗎?

是的,但windows鉤子有幾點做不到。 1,當你有多個鍵盤和滑鼠時,windows是不能分辨從那個鍵盤,或者從哪個滑鼠發過來的請求。用windows Raw Input可以辨別,但無法進行攔截或者對它進行轉換。

2,你無法在使用者模式攔截CTRL-ALT-DELETE快捷鍵,以及在登陸介面做些小動作。 3,你無法用鉤子來攔截一些舊版本的DirectInput編寫的遊戲。

好,彆著急,你需要如何實現以上的功能呢,請往下看. 本軟體包,提供了與核心模式元件通訊的介面,簡單但功能強大。本軟體的核心位於在正常驅動之上(願願:它可以叫篩選器驅動程式)。 曾經有人說,你這個東西對有些核心元件是無效的,事實上,它是可以做到的。

其次,我們開始進入主題。

# AutoHotInterception

AutoHotInterception(AHI) allows you to execute AutoHotkey code in response to events from a *specific* keyboard or mouse, whilst (optionally) blocking the native functionality (ie stopping Windows from seeing that keyboard or mouse event).   In other words, you can use a key on a second (or third, or fourth..) keyboard to trigger AHK code, and that key will not be seen by applications. You can use the *same key* on multiple keyboards for individual actions.   Keyboard Keys, Mouse Buttons and (Relative) Mouse movement are supported. Support for Absolute Mouse movement is planned.  用AutoHotInterception(AHI)可以讓你在AutoHotkey程式碼中,識別不同的鍵盤和滑鼠。(願願:比如聯想m300,就是一個滑鼠和鍵盤的結合體, 裝置管理器中,它對應一個鍵盤,雖然它只有一個側鍵),同時它能阻塞鍵盤和滑鼠事件,讓windows無法看到。也就是說,可以觸發AutoHotkey熱鍵,而又不讓程式知道。 你可以用不同鍵盤的同一鍵,做不同的事情。鍵盤按鍵和滑鼠鍵都是支援的,但注意滑鼠移動事件,它是部分支援的(Relative)。Absolute Mouse movement就是為滑鼠移動事件而專門設計的。 AHI使用了Francisco Lopez 開發的Interception driver。重要的事情說三遍,是Francisco Lopez,Francisco Lopez,Francisco Lopez。

AHI uses the Interception driver by Francisco Lopez  

# WARNING **TAKE CARE** when using this code. Because Interception is a driver, and sits below windows proper, blocking with Interception goes so deep that it can even block CTRL+ALT+DEL etc. As such, it is entirely possible to lock up all input, or at least make life a little difficult.   In general, worst-case scenario would require use of the reset button.   For example, using Subscription Mode with `block` enabled will **totally** block that key from working on that keyboard. So if you block `Ctrl` on your only keyboard, you just blocked CTRL+ALT+DEL.   This is less of an issue whilst AHI does not support mouse blocking (As you could probably kill the script with just the mouse), but if/when that happens, the potential is there.   Be wary of making scripts using this code run on startup. Know how to enter "Safe Mode" in windows and disable startup of the scripts. Know mouse alternatives to emergency keyboard actions (Right click on clock for Task Manager!)     As they say - ***With great power comes great responsibility***.   If this all scares you and you don't really understand it, then TL/DR is you should probably stick to "Context Mode", it's safer.  警告!!! 因為Interception軟體是一個驅動,它位於windows系統之下,它甚至能夠攔截CTRL+ALT+DEL這樣的系統關鍵鍵,所以功能上它可以使得你的windows作業系統完全接受不到任何裝置的輸入訊號, 請謹慎!!!最壞的情況下,你要重灌系統啦~~~。(願願:當然,AutoHotInterception(AHI)包裝了Interception的功能,也避免了你直接用Interception的危險。) 例如,如果在“Subscription Mode”(願願:訂閱模式)下,將block引數啟用,你將遮蔽那個鍵,對於windows將不可見。 如果你用AHI遮蔽了你的電腦的唯一的鍵盤的Ctrl鍵,那麼CTRL+ALT+DEL也會被遮蔽。 AHI不支援滑鼠遮蔽,因為這樣做,可能讓你無法關閉AutoHotkey指令碼。但也有這個可能性,你需要注意的是,謹慎的設定指令碼開機啟動,牢記安全模式進入方法,牢記滑鼠右鍵可以在緊急情況下 可以開啟工作管理員,並關閉程式。 老話說,權利越大責任就越大 如果你不太瞭解,那麼在Context Mode(環境模式)下,使用TL/DR,這會更安全。 如何安裝請看csdn部落格“如何重新定義聯想m300多功能滑鼠的側鍵?願願原創。 ”文章。 # Setup 1. Download and install the [Interception Driver](http://www.oblita.com/interception)   2. Download an AHI release from the [releases page](https://github.com/evilC/AutoHotInterception/releases) and extract it to a folder.   DO NOT use the "Clone or Download" link on the main page.   This is the folder where (at least initially) you will be running scripts from.   It contains a number of sample `.ahk` scripts and a `lib` folder, which contains all the libraries and files needed for AHI.   3. Copy the `interception.dll` from the folder where you ran the interecption install into the `lib` folder that was created in step (2)   4. Right-click `Unblocker.ps1` in the lib folder and select `Run as Admin`.   This is because downloaded DLLs are often blocked and will not work.   This can be done manually by right clicking the DLLs, selecting Properties, and checking a "Block" box if it exists.   5. Edit the example script, enter the VID and PID of your keyboard   6. Run one of the sample scripts   7. (Optional) The contents of the `lib` folder can actually be placed in one of the AutoHotkey lib folders (eg `My Documents\AutoHotkey\lib` - make it if it does not exist), and the `#include` lines of the sample scripts changed to `#include <AutoHotInterception>`, to enable your AHI scripts to be in any folder, without each needing it's own copy of the library files.  

# Device IDs / VIDs PIDs etc   Interception identifies unique devices by an ID. This is a number from 1..21.   Devices 1-10 are always keyboards   Devices 11-21 are always mice   This ID scheme is totally unique to Interception, and IDs may change as you plug / unplug devices etc.   On PC, devices are often identified by VendorID (VID) and ProductID (PID). These are identifiers baked into the hardware at time of manufacture, and are identical for all devices of the same make / model.   Most AHI functions (eg to Subscribe to a key etc) use an Interception ID, so some handy functions are provided to allow you to find the (current) Interception ID of your device, given a VID / PID.   If you are unsure of what the VID / PID of your device is (or even if Interception can see it), you can use the included Monitor script to find it.  裝置ID,廠商ID,產品ID等等吧 Interception通過“ID”來區分不同的裝置 1至10代表鍵盤,11-21代表滑鼠。當裝置重插時,“ID”可能會改變。 對於個人電腦,裝置經常用廠商ID(VID)和產品ID(PID)來標識,這些資訊在出廠時就被燒進了硬體。 多數的AHI函式,比如訂閱一個按鍵,使用的是Interception ID,你可以很方便的使用AHI提供的函式得到它,需要提供的引數只有VID / PID。 如果不知道裝置的VID與PID,你可以用AutoHotInterception(AHI),自帶的Monitor指令碼來檢視。(願願:本人是用裝置管理器,檢視裝置例項資訊得到的,霍霍~) # Usage ## Initializing the Library Include the library ``` #Persistent ; (Interception hotkeys do not stop AHK from exiting, so use this)Inerception熱鍵排斥讓AHK程式碼執行,所以加了這句 #include Lib\AutoHotInterception.ahk ```

Initialize the library ``` <<<<<<< HEAD global AHI := InterceptionWrapper() ``` In this case, `AHI` is actually an AHK class - it wraps the AHI DLL and provides some extra functionality.   The majority of the documented commands can be called directly on the DLL itself by calling them on `AHI.Instance` instead of `AHI`.  這種用法下,我們用"AHI.Instance"來直接呼叫DLL中絕大多數的函式。而下面主要講的方法,是用`AHI`來呼叫,畢竟AHI事實上是AHK的一個類,它包裝了AHI DLL,並提供了一些額外功能。 ======= AHI := new AutoHotInterception() global Interception := AHI.GetInstance() ```

`AHI` is an AHK class that makes it easy to interact with the AutoHotInterception DLL. For example, it wraps `GetDeviceList()` to make it return a normal AHK array. Most of the time you will not need it.   For advanced users, if you wish to directly communicate with the AHI DLL (eg for best possible performance), you can call `AHI.Instance` instead of `AHI` for most functions (eg when sending of synthesized input using `SendMouseMove`).  AHI包裝了`GetDeviceList()`函式,使它能夠返回AHK的一個數組,通常情況下,你直接使用AHI。 如果你希望有更好的效能,並需要直接呼叫AHI DLL,你可以用"AHI.Instance",而不是`AHI`。比如:用SendMouseMove來發送模擬按鍵輸入。 >>>>>>> 612da55d842ed730fc4884b04d28356e3527e3b6

## Finding Device IDs   ### Finding a specific device   In most cases, you will want to hard-wire a script to a specific VID/PID - in this instance, use one of the following methods.     For all these methods, if you have multiple identical VID/PID devices, you can specify an `instance` (Starts from 1).  如果你有多個相同VID/PID的裝置,在指令碼中,你可以使用“instance”來表明,你使用的具體是哪一個,請參照以下方法。

#### GetDeviceId `AHI.GetDeviceId(<isMouse>, <VID>, <PID> [,<instance = 1>] )`   Where `isMouse` is `true` if you wish to find a mouse, or `false` if you wish to find a keyboard.   eg `AHI.GetDeviceId(false, 0x04F2, 0x0112)`  to find a keyboard with VID 0x04F2 and PID 0x0112  

如果你要得到滑鼠ID,則`isMouse`設定為true,如果要得到鍵盤ID,則,設定為false。 比如:`AHI.GetDeviceId(false, 0x04F2, 0x0112)`,是要得到VID為0x04F2,PID為0x0112的鍵盤ID #### GetKeyboardId `AHI.GetKeyboardId(<VID>, <PID> [,<instance = 1>] )`  

#### GetMouseId `AHI.GetMouseId(<VID>, <PID> [,<instance = 1>] )`  

### Getting a list of devices If you wish to get a list of all available devices, you can call `AHI.GetDeviceList()`, which will return an array of `DeviceInfo` objects, each of which has the following properties:  要得到所有可用裝置列表,可以用AHI.GetDeviceList(),返回的是`DeviceInfo`物件陣列,該物件有下列屬性: ``` Id isMouse Vid Pid ```

## Modes There are two modes of operation for AHI, and both can be used simultaneously.  AHI使用,有兩種模式,它們可以同時使用 ### Context mode(環境模式) Context mode is so named as it takes advantage of AutoHotkey's [Context Sensitive Hotkeys](https://autohotkey.com/docs/Hotkeys.htm#Context).   As such, only Keyboard Keys and Mouse Buttons are supported in this mode. Mouse Movement is not supported.  Context mode環境模式這樣命名,主要是源於AutoHotkey中的Context Sensitive Hotkeys(環境條件觸發熱鍵)(參考:https://autohotkey.com/docs/Hotkeys.htm#Context). In context mode, you create a "Context Manager" object which turns on/off a set of AHK hotkeys for you.   You wrap your hotkeys in an #if block which is controlled by the manager.  在環境模式中,你可以用"Context Manager"(環境管理器) 物件來開關AHK熱鍵。 Create a Context Manager for the keyboard or mouse, pass it the Interception ID of the device.   Then Create your hotkeys, wrapped in an `#if` block that checks the `.IsActive` property of your Context Manager  要建立一個環境管理器,可以把鍵盤或者滑鼠的ID傳給它,在使用時,將你的熱鍵包裹在#if塊中,並檢查`.IsActive`屬性。如下操作: (Complete, working script)   ``` #include Lib\AutoHotInterception.ahk

keyboard1Id := AHI.GetKeyboardId(0x04F2, 0x0112) cm1 := AHI.CreateContextManager(keyboard1Id)

#if cm1.IsActive    ; Start the #if block ::aaa::JACKPOT 1::     ToolTip % "KEY DOWN EVENT @ " A_TickCount     return      1 up::     ToolTip % "KEY UP EVENT @ " A_TickCount     return #if            ; Close the #if block ```

### Subscription mode In Subscription mode, you bypass AHK's hotkey system completely, and Interception notifies you of key events via callbacks.   All forms of input are supported in Subscription Mode.   Subscription Mode overrides Context Mode - that is, if a key on a keyboard has been subscribed to with Subscription Mode, then Context Mode will not fire for that key on that keyboard.  訂閱模式 在訂閱模式中,你的AHK熱鍵完全繞過了AHK熱鍵系統,Interception驅動會通過回撥函式來通知你按鍵事件。 所有的輸入都是被支援的,包括滑鼠和鍵盤。 訂閱模式會覆蓋環境模式,也就是說,如果一個鍵盤鍵被訂閱,那麼該鍵盤鍵的環境模式熱鍵定義,將不會被觸發。 #### Subscribing to Keyboard keys Subscribe to a key on a specific keyboard訂閱方法如下: 先是,訂閱指定鍵盤的按鍵的方法: `SubscribeKey(<deviceId>, <scanCode>, <block>, <callback>)` ``` Interception.SubscribeKey(keyboardId, GetKeySC("1"), true, Func("KeyEvent")) return ```

Callback function is passed state `0` (released) or `1` (pressed)回撥函式,state引數為0,表示被放開,1表示被按下。 ``` KeyEvent(state){     ToolTip % "State: " state } ```

#### Subscribing to Mouse Buttons其次,訂閱滑鼠鍵的方法 `SubscribeMouseButton(<deviceId>, <button>, <block>, <callback>)`   Where `button` is one of:   ``` 0: Left Mouse 1: Right Mouse 2: Middle Mouse 3: Side Button 1 4: Side Button 2 ```   Otherwise, usage is identical to `SubscribeKey`  `button`引數,是以上含義,除此之外,用法與`SubscribeKey` 相同。

#### Subscribing to Mouse Movement   **Warning!** When Subscribing to mouse movement, you will get **LOTS** of callbacks.   Note the CPU usage of the demo Monitor app.   AutoHotkey is *not good* for handling heavy processing in each callback (eg updating a GUI, like the monitor app does).   Keep your callbacks **short and efficient** in this mode if you wish to avoid high CPU usage.  最後,如何訂閱滑鼠移動 警告!!!當訂閱滑鼠移動時,將會產生大量的回撥函式事件,這會給電腦造成很大負擔,會拖慢電腦執行,所以訂閱滑鼠移動,並不是個 “好主意”。所以即使要這麼做,也要儘量使得你的回撥函式程式碼簡單短小。由於時間關係,加之該訂閱不常用,就不介紹了, 相信,只要是程式設計師,英文是必要的。 ##### Relative Mode   Relative mode is for normal mice and most trackpads.   Coordinates will be delta (change) `SubscribeMouseMove(<deviceId>, <block>, <callback>)`   For Mouse Movement, the callback is passed two ints - x and y.   ``` Interception.SubscribeMouseMove(mouseId, false, Func("MouseEvent"))

MouseEvent(x, y){     [...] } ```

##### Absolute Mode Absolute mode is used for Graphics Tablets, Light Guns etc.   Coordinates will be in the range 0..65535   ``` Interception.SubscribeMouseMoveAbsolute(mouseId, false, Func("MouseEvent"))

MouseEvent(x, y){     [...] } ``` ## Synthesizing Output Note that these commands will work in both Context and Subscription modes   Also note that you can send as any device, regardless of whether you have subscribed to it in some way or not.模擬輸出 以下命令,環境與訂閱模式通用,請注意不論你是否已經訂閱某個裝置的某個按鍵,你都可以傳送模擬輸出。

### Sending Keyboard Keys You can send keys as a specific keyboard using the `SendKeyEvent` method.  你可以模擬傳送某個鍵盤的按鍵,用`SendKeyEvent`方法。 `Interception.SendKeyEvent(<keyboardId>, <scanCode>, <state>)`   scanCode = the Scan Code of the key   state = 1 for press, 0 for release   keyboardId = The Interception ID of the keyboard

``` Interception.SendKeyEvent(keyboardId, GetKeySC("a"), 1) ```

If you subscribe to a key using Subscription mode with the `block` parameter set to true, then send a different key using `SendKeyEvent`, you are transforming that key in a way which is totally invisible to windows (And all apps running on it), and it will respond as appropriate.  For example, AHK `$` prefixed hotkeys **will not** be able to tell that this is synthetic input, and will respond to it.

(願願:解釋重點,請注意參考!!) 如果用Subscription模式,以block引數為true的條件,設定了一個鍵的回撥函式,那麼在該鍵的回撥函式中,如果用SendKeyEvent傳送了一個不同的按鍵(願願:也就是說,你在回撥函式中沒有傳送自身按鍵),那麼這個訂閱按鍵將對於windows是不可見的(包括其上的所有程式),但同時,它根據回撥函式的定義 正常響應。比如,以`$`為字首的熱鍵,我們知道是系統鉤子熱鍵,它不會被模擬按鍵所觸發,但如果是用SendKeyEvent傳送該熱鍵,它不會分辨出這是一個模擬 按鍵,它會像執行物理按鍵一樣,觸發系統鉤子熱鍵。舉個例子,假設用$f定義了一個熱鍵$f::send {f}{g},因為該熱鍵是 由windows系統鍵盤鉤子實現的。首先,如果用windows的send命令,它將輸出f,不會觸發windows系統鉤子,因為send命令不能觸發鍵盤鉤子實現的熱鍵。 其次,如果直接物理上按下f按鍵,它將輸出輸出fg。再次,如果用SendKeyEvent,傳送f鍵,將也輸出fg。$定義的windows系統鉤子熱鍵不能分辨這是 一個複合輸入,會像物理按下一樣正常響應。最後,這也說明了,AHI SendKeyEvent更接近物理層,並且位於windows系統鉤子管理之外,windows只能把它傳送的按鍵解 釋為一次真實的物理操作。但不論哪種情況,Subscription mode(分發模式)下,每個按鍵的回撥函式,都不會被send,或者SendKeyEvent的觸發,它只會被比 Interception Driver驅動更為底層的驅動,或者乾脆是物理層,所觸發。

比如:以下例子 AHI.SubscribeKey(id2, GetKeySC("x"), false, Func("x_KeyEvent")) AHI.SubscribeKey(id2, GetKeySC("s"), true, Func("s_KeyEvent")) s_KeyEvent(state) { ;   AHI.SendKeyEvent(id2, GetKeySC("m"), 1) ;true,時,s被吃掉了,windows接收不到。但能觸發$定義的m熱鍵,或酌情響應。 } x_KeyEvent(state) { ;   AHI.SendKeyEvent(id2, GetKeySC("m"), 1) ;相反,false時,該按鍵windows可以收到。 }所以block引數用來,阻止訂閱的按鍵本身是否對windows可見,或者說是否阻塞訂閱的按鍵本身的輸入請求傳遞給windows。 Normally, the windows API function RegisterHotkey() is used to implement a keyboard hotkey whenever possible. However, the responsiveness of hotkeys might be better under some conditions if the keyboard hook is used instead. 一般,鍵盤熱鍵是用windows的RegisterHotkey()API函式實現的,可以在一些情況下,如果用鍵盤鉤子實現,熱鍵的響應能力會好些。 用$字首和用#UseHook指令的作用是一樣的,都是為了定義一個鍵盤鉤子實現的熱鍵。相反,不使用它們修飾的熱鍵,都是用RegisterHotkey() 來實現的。 ### Sending Mouse Buttons

`Interception.SendMouseButtonEvent(<mouseId>, <button>, <state>)`   Where `button` is the button index, as used in `SubscribeMouseButton`  

### Sending Mouse Movement #### Relative `Interception.SendMouseMove(<mouseId>, <x>, <y>)`  

#### Absolute `Interception.SendMouseMoveAbsolute(<mouseId>, <x>, <y>)`  

## Monitor App ToDo: Add recording of monitor app