AutoHotkey doesn't natively support the differentiation between multiple keyboards. AHKHID tackles this problem but does not allow intercepting or eating the keypress. Alternatives include Quick Macros and GlovePIE, but that requires the learning of a new syntax. The final alternative then is HID macros which doesn't require the learning of a new language but is also very limited in its actions. To overcome this limitation you could have HID macros intercept a keypress and have it send some key combination like Alt+F15 that triggers AutoHotkey. If you require many keypads, you need something more extensive.
My solution
I have written a AutoHotkey script that passes its startup parameters to a running AutoHotkey instance for processing. HID macros intercepts the keys and runs the script with the keyboard ID and Key ID as parameters. This way keys are intercepted AND the keyboard is identified.
Another downside of HID macros is that it requires each key to be configured and it takes 11 lines of configuration per key. That's why I've also written a script to generate the configuration for HID macros.
Why
The motivation behind the script is that I want to place multiple USB keypads around the house all connected to the home server. The keypads control lights or locks switched by a relay board. Different keypads should switch different lighting and outside keypads should block after incorrect entries.
How to use
Copy the scrips to a file using the same names as provided.
Download HID macros to %A_ScriptDir%\HidMacros.
Run HIDmacros_KeypadScriptGenerator.ahk and go through the wizard, the HID macros script will be pasted to the clipboard.
Create a file %A_ScriptDir%\HidMacros\HidMacros.ini, paste the clipboard and save.
Run HIDmacros.ahk.
Configure the keypads in HID macros.
Hide HID macros by double clicking the tray icon.When using the code, but keep in mind: It's designed for keyPADS not keyBOARDS. If you wan't to use a full keyboard you need to add a LOT of extra keys to all three scripts.
HIDmacros_send.ahk
#NoTrayIcon SetTitleMatchMode,2 DetectHiddenWindows,On if 0=2 ;%0% holds the amount of parameters passed, if it equals 2, send the message ;%1% holds the keyboard number ;%2% holds the VK number { SendMessage,0x4530,%1%,%2%,,HIDmacros.ahk ahk_class AutoHotkey } ExitApp
HIDmacros.ahk Here I've also put some examples on how to detect a key presses or sequence inputs.
SetNumlockState,AlwaysOn HIDmacrosexe=%A_ScriptDir%\HidMacros\HidMacros.exe Menu,Tray,Icon,%HIDmacrosexe% Gosub,CheckHIDmacros SetTimer,CheckHIDmacros,60000 OnExit,ExitShow OnMessage(0x4530, "InputMsg") ;Begin definition VK codes: VK96=0 VK97=1 VK98=2 VK99=3 VK100=4 VK101=5 VK102=6 VK103=7 VK104=8 VK105=9 VK13=Enter VK8=BackSpace VK106=`* VK107=`+ VK109=`- VK111=`/ VK110=`. VK33=PgUp VK34=PgDn VK35=End VK36=Home VK37=Left VK38=Up VK39=Right VK40=Down VK45=Insert VK46=Delete VK144=NumLock ;End definition VK codes: InputMsg(KeyboardID,KeyID) { ;Critical Static Sequence1, Sequence2, Sequence3, TimeOfInput1, TimeOfInput2, TimeOfInput3 KeyID:=VK%KeyID% TimeOfInputDifference:=TimeOfInput%KeyboardID% TimeOfInputDifference-=A_Now,Seconds TimeOfInputDifference*=-1 TimeOfInput%KeyboardID%:=A_Now If (TimeOfInputDifference>20) Sequence%KeyboardID%= If (KeyID="BackSpace") Sequence%KeyboardID%= Else If (KeyID="Enter"){ Sequence:=Sequence%KeyboardID% ProcessSequence(KeyboardID,Sequence) Sequence%KeyboardID%= }Else If (KeyID="-"){ MsgBox,,Action,Lights ON,2 SetTimer,LightsOff,-30000 }Else If (KeyID="/"){ MsgBox,,Action,Bell,2 }Else Sequence%KeyboardID% .= KeyID } ProcessSequence(KeyboardID,Sequence){ static TimeOfInvalid1, TimeOfInvalid2, TimeOfInvalid3 TimeOfInvalidDifference:=TimeOfInvalid%KeyboardID% TimeOfInvalidDifference-=A_Now,Seconds TimeOfInvalidDifference*=-1 StringSplit,Parameter,Sequence,. If (TimeOfInvalidDifference<20) AND (TimeOfInvalidDifference<>0){ MsgBox,,,BLOCKED,2 Exit } If ((KeyboardID=2) OR (KeyboardID=3)) AND (Parameter1=123) MsgBox,,Action,Alarm ARMED,2 Else If (Parameter1=456) MsgBox,,Action,Alarm DISARMED,2 Else If (Parameter1=147896) MsgBox,,Action,Door Open,2 Else If (Parameter1="") MsgBox,,Action,Empty,2 Else If (KeyboardID=2){ TimeOfInvalid%KeyboardID%:=A_Now MsgBox,,,INVALID: %Parameter1%,2 } } #IfWinNotExist,HID macros ahk_class THIDMacrosForm ;HID macros not running! Block all keypads keys NumPad0:: NumPad1:: NumPad2:: NumPad3:: NumPad4:: NumPad5:: NumPad6:: NumPad7:: NumPad8:: NumPad9:: NumpadDot:: NumpadDiv:: NumpadMult:: NumpadAdd:: NumpadSub:: NumpadIns:: NumpadEnd:: NumpadDown:: NumpadPgDn:: NumpadLeft:: NumpadClear:: NumpadRight:: NumpadHome:: NumpadUp:: NumpadPgUp:: NumpadDel:: NumLock:: Return NumpadEnter::Gosub,CheckHIDmacros CheckHIDmacros: SetTitleMatchMode,2 DetectHiddenWindows,Off if (A_TimeIdlePhysical > 60000) AND WinExist("HID macros ahk_class THIDMacrosForm") Gosub,HideHID DetectHiddenWindows,On If !WinExist("HID macros ahk_class THIDMacrosForm"){ Gosub,ShowHID Gosub,HideHID }Else{ Menu,Tray,Add,Hide HID macros,HideHID Menu,Tray,Default,Hide HID macros } Return ShowHID: DetectHiddenWindows,On If !WinExist("HID macros ahk_class THIDMacrosForm"){ Run,%HIDmacrosexe% Menu,Tray,Add,Show HID macros,ShowHID WinWait,HID macros,,2 } GroupAdd,HIDmacros,HID macros WinShow,ahk_group HIDmacros WinActivate,ahk_group HIDmacros Menu,Tray,Delete,Show HID macros Menu,Tray,Add,Hide HID macros,HideHID Menu,Tray,Default,Hide HID macros Return HideHID: GroupAdd,HIDmacros,HID macros WinHide,ahk_group HIDmacros Menu,Tray,Delete,Hide HID macros Menu,Tray,Add,Show HID macros,ShowHID Menu,Tray,Default,Show HID macros Return ExitShow: DetectHiddenWindows,Off If !WinExist("HID macros ahk_class THIDMacrosForm") Gosub,ShowHID ExitApp Return LightsOff: MsgBox,,Action,Lights OFF,2 Return #IfWinActive
HIDmacros_KeypadScriptGenerator.ahk
;Set variables: VK96=0 VK97=1 VK98=2 VK99=3 VK100=4 VK101=5 VK102=6 VK103=7 VK104=8 VK105=9 VK13=Enter VK8=BackSpace VK106=`* VK107=`+ VK109=`- VK111=`/ VK110=`. VK33=PgUp VK34=PgDn VK35=End VK36=Home VK37=Left VK38=Up VK39=Right VK40=Down VK45=Insert VK46=Delete VK144=NumLock macroindex=0 configuration= keycodes:="8 13 96 97 98 99 100 101 102 103 104 105 106 107 109 110 111" ;NumLock On virtual key codes ;keycodes.=" 144" ;NumLock, does not work on my PC Loop{ InputBox, keypad, Keypad name, Enter the name of keypad #%A_Index%.`nLeave blank to continue. If (keypad=""){ keypad:=A_Index-1 Break } keypad%A_Index%:=keypad If (ErrorLevel) ExitApp } InputBox, exe, AutoHotkey executable location, Enter the location of the AutoHotkey executable file,,,,,,,, C:\Program Files (x86)\AutoHotkey\AutoHotkey.exe If (ErrorLevel) ExitApp InputBox, script, AutoHotkey script location, Enter the location of the HIDmacros_send.ahk file,,,,,,,, C:\Program Files (x86)\AutoHotkey\Domotica\HIDmacros_send.ahk If (ErrorLevel) ExitApp MsgBox, 291, NumLock off state, Should numlock off keys be included? IfMsgBox Yes keycodes.=" 33 34 35 36 37 38 39 40 45 46" ;NumLock Off virtual key codes Else IfMsgBox Cancel ExitApp Loop,%keypad% { keypadname:=keypad%A_Index% keypadnumber:=A_Index Loop, Parse, keycodes, %A_Space% { keyname:=VK%A_LoopField% configuration.="[Macro." . macroindex . "]`r`n" configuration.="Keyboard=" . keypadname . "`r`n" configuration.="Name=" . keypadname . ": " . keyname . "`r`n" configuration.="KeyCode=" . A_LoopField . "`r`n" configuration.="Direction=down`r`n" configuration.="Action=CMD`r`n" configuration.="Sequence=`r`n" configuration.="SCEvent=`r`n" configuration.="SCText=0`r`n" configuration.="SCParams=`r`n" configuration.="Command=""" . exe . """ """ . script . """ " . keypadnumber . " " . A_LoopField . "`r`n" macroindex++ } } Clipboard:=configuration MsgBox, 64, Configuration completed, The HidMacros key configuration has been copied to the clipboard, 5
Perhaps not the neatest or well commented code, but two month ago I've never heard of AHK. So your input is appreciated.