AHK keyboard hook + AHKHID causing buggy behavior

Get help with using AutoHotkey and its commands and hotkeys
Elgin
Posts: 110
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: 110
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.

Return to “Ask For Help”

Who is online

Users browsing this forum: DRocks, flyingDman, Getfree, Google [Bot] and 38 guests