AHK keyboard hook + AHKHID causing buggy behavior

Get help with using AutoHotkey and its commands and hotkeys
Elgin
Posts: 115
Joined: 30 Sep 2013, 09:19

AHK keyboard hook + AHKHID causing buggy behavior

20 May 2016, 07:39

My goal is to distinguish on which of my two keyboards a key was pressed and perform different actions.
I found this:
https://autohotkey.com/board/topic/3801 ... ntry251836
and tried to implement it but ran into some very strange issues.

The demo code below should block the "c" when pressed and output "Logitech_c" if the key was pressed on a Logitech keyboard and "other_c" if it was pressed on any other keyboard independent in which application.

What I see is:
1. The behaviour depends on if I press "c" in the AHK Gui edit field or any other application:
- in AHK the "c" is not blocked, so I get both the original "c" and the output of the SendInput; the hotkey seems to be not working
- in any other application the "c" is blocked but also no WM_INPUT message is generated so that I get no output at all from pressing "c"
2. The Shift pressed by SendInput for the capital L and the underscore is stuck afterwards until manually pressed, so I get e.g. "cLOGITECH_C" instead of the expected "Logitech_c" as output in the AHK window

The problem seems to be the combination of the keyboard-hook hotkey $c:: and the RawInput handling from AHKHID. When I remove either one the script behaves as would be expected in that case. I tried this on Win10 with the latest AHK version but it also seems to occur on Win7 with an older 1.1.23 AHK version. It is also not necessary to have two keyboards connected to verify the behaviour.

I'm stuck... Is there anything I'm doing wrong? Is it a bug in AHK or somewhere else? Is there any way to work around this without installing other software?

Any help would be appreciated.

My example code:

Code: Select all

#Include AHKHID.ahk

;Create GUI
Gui +LastFound -Resize -MaximizeBox -MinimizeBox
Gui, Add, Edit, w1500 r15 vtxtres,
Gui, Add, Edit, w1500 r15 vtxtlst,

;Keep handle
GuiHandle := WinExist()

;Set up the constants
AHKHID_UseConstants()

; get keyboard events from all applications
AHKHID_Register(1, 6, GuiHandle, RIDEV_INPUTSINK)   

;Intercept WM_INPUT
OnMessage(0x00FF, "InputMsg")

; enable next line to demonstrate that shift gets stuck in SendInput
;~ Settimer, timer1, 2000

;Show GUI
Gui, Show
Return

GuiClose:
ExitApp

$c:: Return     ; block c

InputMsg(wParam, lParam) {
    Local r, h
    critical    ;Or otherwise you could get ERROR_INVALID_HANDLE
    
    ;Get device type
    r := AHKHID_GetInputInfo(lParam, II_DEVTYPE) 
	If (r = RIM_TYPEKEYBOARD) 
    {
        h := AHKHID_GetInputInfo(lParam, II_DEVHANDLE)
        lstvar.="`r`n"
            . " MakeCode: "    AHKHID_GetInputInfo(lParam, II_KBD_MAKECODE)
            . " Flags: "       AHKHID_GetInputInfo(lParam, II_KBD_FLAGS)
            . " VKey: "        AHKHID_GetInputInfo(lParam, II_KBD_VKEY)
            . " Message: "     AHKHID_GetInputInfo(lParam, II_KBD_MSG) 
            . " ExtraInfo: "   AHKHID_GetInputInfo(lParam, II_KBD_EXTRAINFO)
            . " Name: "   AHKHID_GetDevName(H, True)
        GuiControl,, txtlst, % lstvar
        ; is it a c-down event?
        If (AHKHID_GetInputInfo(lParam, II_KBD_FLAGS)=0 and AHKHID_GetInputInfo(lParam, II_KBD_VKEY)=67)
        {
            If (Instr(AHKHID_GetDevName(H, True),"HID#VID_046D")) ; is it a Logitech device?
            {
                SetTimer, timer1, -1
            } 
            Else If (AHKHID_GetDevName(H, True)<>"") ; make sure it's from another real device
            {
                SetTimer, timer2, -1
            }
        }
    }
    return, 0
}

timer1:
    SendInput Logitech_c 
return

timer2:
    SendInput Other_c 
return
IMEime
Posts: 750
Joined: 20 Sep 2014, 06:15

Re: AHK keyboard hook + AHKHID causing buggy behavior

20 May 2016, 11:58

Code: Select all

#SingleInstance Force
DetectHiddenWindows, ON

Soundbeep
Soundbeep

Gui, Font, cBlue
Gui, Add, Edit, 			h300 ReadOnly -VScroll vThatOne
Gui, Font, cRed
Gui, Add, Edit, x+10 	h300 ReadOnly -VScroll vThisOne
Gui, Show,, Two Keyboards

OnMessage( 0x00FF, "YouPressed")
SizeofRawInputDeviceList	:= A_PtrSize * 2
SizeofRawInputDevice		:= 8 + A_PtrSize
RIDI_DEVICENAME				:= 0x20000007
RIDI_DEVICEINFO				:= 0x2000000b
RIDEV_INPUTSINK				:= 0x00000100
RID_INPUT						:= 0x10000003
HWND := WinExist( "Two Keyboards" )
Res := DllCall( "GetRawInputDeviceList", "Ptr", 0, "UInt*", Kount, UInt, SizeofRawInputDeviceList)
VarSetCapacity( RawInputList, SizeofRawInputDeviceList * Kount)
Res := DllCall( "GetRawInputDeviceList", "Ptr", &RawInputList, "UInt*", Kount, "UInt", SizeofRawInputDeviceList)
KeyboardRegistered := 0
Loop % Kount 
{
	Handle := NumGet( RawInputList, ( A_Index - 1) * SizeofRawInputDeviceList, "UInt")
	Type := NumGet( RawInputList, (( A_Index - 1) * SizeofRawInputDeviceList) + A_PtrSize, "UInt")
	If (Type <> 1)
		Continue
	KBDCount ++
	KbD%KBDCount% := Handle		
	Res := DllCall( "GetRawInputDeviceInfo", "Ptr", Handle, "UInt", RIDI_DEVICENAME, "Ptr", 0, "UInt *", nLength)
	VarSetCapacity( Name, ( nLength + 1) * 2)
	Res := DllCall( "GetRawInputDeviceInfo", "Ptr", Handle, "UInt", RIDI_DEVICENAME, "Str", Name, "UInt*", nLength)
	Res := DllCall( "GetRawInputDeviceInfo", "Ptr", Handle, "UInt", RIDI_DEVICEINFO, "Ptr", 0, "UInt *", iLength)
	VarSetCapacity( Info, iLength)
	NumPut( iLength, Info, 0, "UInt")
	Res := DllCall( "GetRawInputDeviceInfo", "Ptr", Handle, "UInt", RIDI_DEVICEINFO, "UInt", &Info, "UInt *", iLength)
	VarSetCapacity( RawDevice, SizeofRawInputDevice, 0)
	NumPut( RIDEV_INPUTSINK, RawDevice, 4)
	NumPut( HWND, RawDevice, 8)
	DoRegister := 0
	If ( KeyboardRegistered = 0)
	{
		DoRegister := 1
		NumPut( 1, RawDevice, 0, "UShort")
		NumPut( 6, RawDevice, 2, "UShort")
		KeyboardRegistered := 1
	}
	If (DoRegister)
		Res := DllCall( "RegisterRawInputDevices", "Ptr", &RawDevice, "UInt", 1, "UInt", 8 + A_PtrSize ) 
}
Kount := 1 
Return

GuiClose:
Soundbeep
Soundbeep
ExitApp

YouPressed( wParam, lParam, msg, hwnd )
{
	Global
	Res := DllCall( "GetRawInputData", "UInt", lParam, "UInt", RID_INPUT, "Ptr", 0, "UInt *", Size, "UInt", 8 + A_PtrSize * 2)
	VarSetCapacity( Buffer, Size)
	Res := DllCall( "GetRawInputData", "UInt", lParam, "UInt", RID_INPUT, "Ptr", &Buffer, "UInt *", Size, "UInt", 8 + A_PtrSize * 2)
	If ( NumGet( Buffer, 0 * 4, "UInt") = 1)								
	{
		VKey := NumGet( Buffer, (14 + A_PtrSize * 2 ), "UShort")
		If ( NumGet( Buffer, (16 + A_PtrSize * 2 )) = 256 )    	
			{
			SetFormat, Integer, H					
			VKey += 0
			If ( NumGet( Buffer, 2 * 4, "UInt") = KbD1 ) 				
				ThisWay( GetKeyName( "vk" VKey) "`r`n")
			Else
				ThatWay( GetKeyName( "vk" VKey) "`r`n")				
			}
	}	
	Return
}
ThatWay( Text)
{
	GuiControlGet, 	ThatOne
	GuiControl,, 	ThatOne, % Text ThatOne 
	Return
}
ThisWay( Text)
{
	GuiControlGet,	ThisOne
	GuiControl,, 	ThisOne, % Text ThisOne 
	Return
}
NOTE
This is not mine.
I just twisted a little bit of someone else's smart codes.
I've forgot the exact name ot him/her.
Anyways, alwasy thanks to him/her.
Elgin
Posts: 115
Joined: 30 Sep 2013, 09:19

Re: AHK keyboard hook + AHKHID causing buggy behavior

20 May 2016, 12:47

Hi IMEime,

that code can only distinguish between two keyboards. Basically the same as my example when you remove the line "$c:: Return", which works fine. My problems as described start when I try to suppress the original keystrokes...

As soon as you insert "$c:: Return" (or any other letter/number hotkey) into your script, it shows the same weird behavior as mine.
Death Star
Posts: 1
Joined: 26 Jan 2020, 13:15

Re: AHK keyboard hook + AHKHID causing buggy behavior

27 Jan 2020, 13:29

Elgin wrote:
20 May 2016, 07:39
What I see is:
1. The behaviour depends on if I press "c" in the AHK Gui edit field or any other application:
- in AHK the "c" is not blocked, so I get both the original "c" and the output of the SendInput; the hotkey seems to be not working
- in any other application the "c" is blocked but also no WM_INPUT message is generated so that I get no output at all from pressing "c"
I'm having your exact same problem, did you manage to solve it?
martinPQ
Posts: 3
Joined: 23 Jul 2017, 12:17

Re: AHK keyboard hook + AHKHID causing buggy behavior

28 Jan 2020, 21:32

Hi
Try this:

Code: Select all

#Include AHKHID.ahk

Global _KEYBOARD_

;Create GUI
Gui +LastFound -Resize -MaximizeBox -MinimizeBox
Gui, Add, Edit, w1500 r15 vtxtres,

;Keep handle
GuiHandle := WinExist()

;Set up the constants
AHKHID_UseConstants()

; get keyboard events from all applications
AHKHID_Register(1, 6, GuiHandle, RIDEV_INPUTSINK)   

;Intercept WM_INPUT
OnMessage(0x00FF, "InputMsg")

;Show GUI
Gui, Show
Return

GuiClose:
ExitApp

;===== HOTKEYS
c::
{
    check_keyboard() 
    if (InStr( _KEYBOARD_, "HID#VID_046D") )
        s := "L{shift up}ogitech_{shift up}c "   ;There seems to be a bug. After a capital letter we have to force a {Shift UP}
    else
        s := "O{shift up}ther_{shift up}c "
    Suspend on    ; for avoid the hotkey
    SendInput %s%
    Suspend off
    Return     
}

;=============
check_keyboard()
{
    _KEYBOARD_ := ""
    t  := A_TickCount + 1000  ; 1000 ms awating to release the key
   while (_KEYBOARD_="")   ;for eternity until the condition is FALSE
   {
    	if (A_TickCount > t)   ;to avoid an infinite loop
    	    break
    } 
} 


InputMsg(wParam, lParam)
{
    Local r, h

    Critical    ;Or otherwise you could get ERROR_INVALID_HANDLE
  
    ;Get device type
    r := AHKHID_GetInputInfo(lParam, II_DEVTYPE)         
    if (r != RIM_TYPEKEYBOARD)      ; only keyboards
        return

    h := AHKHID_GetInputInfo(lParam, II_DEVHANDLE)
	_KEYBOARD_ := AHKHID_GetDevName(h,True)
}

How does it work?
When the hotkey is pressed, the WM_INPUT message is proccesed by AHK in first place, so we can do nothing about it.
But we can wait until the key is released and then identify the keyboard.
This method has its limitations, but it is the best I have achieved without using external software.
Knowing those limitations, I can handle multiple keyboards without problems. Keyboard shortcuts for blender, premier, photoshop, freecad, ... one keyboard for each of them.
I hope it helps.

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], erikals, Google [Bot], k4rkarin, Kellyzkorner_NJ and 32 guests