Context Hotkeys missed in GUI's if RegisterRawInputDevices active

Report problems with documented functionality
MrHue
Posts: 17
Joined: 01 Oct 2015, 02:51

Context Hotkeys missed in GUI's if RegisterRawInputDevices active

18 Nov 2015, 03:55

I have encountered a strange behaviour in AHK v1.1.2207.
If RegisterRawInputDevices has been registered, GUI's will fail to pick up context specific hotkeys (e.g. F1) for the GUI, but keyboard accelerators work.
A way to get around it is to enable & disable RawInputDevices as needed.
Keyboard hooking with $ prefix does not seem to work.

Universal hotkeys work in the gui in the example below (but ~ prefix will kill it) and in fact causes the context specific hotkey to work also.
.. but not in another more complex script with multiple GUIs and multiple context-specific hotkeys & hotstrings and SendLevel & InputLevel....

Example test script as follow:

Code: Select all

Gui, Add, Text,, Press F1 to test if hotkey is detected in GUI
Gui, Add, Button, gRegister, &Register RawInputDevices
Gui, Add, Button, gDeregister, &De-Register RawInputDevices
Gui, Show,, RID test
return

Register:
	EnablePriorKey(1)
return

DeRegister:
	EnablePriorKey(0)
return


#IfWinActive, RID test
F1::
	msgbox, Hotkeys detected in GUI!
return

;#If
;F1::
;	msgbox, Hotkeys detected not detected in GUI!
;return

EnablePriorKey(Enable=1) {					; This is really to enable barcode handling
	static Enabled=0					; Need to be disabled for hotkey handling in Gui's
	global PriorKeyTicks=A_TickCount			; initialize PriorKeyTicks
	VarSetCapacity(rawDevice, 8 + A_PtrSize, 0)
	NumPut(1,		rawDevice, 0, "UShort")		; usagePage = 1
	NumPut(6,		rawDevice, 2, "UShort")		; usagePage = 1 & usage = 6 for keyboard 

	if (Enable) && (!Enabled)
	{
		NumPut(0x100,		rawDevice, 4, "UInt")	; dwFlags = RIDEV_INPUTSINK (don't require foreground)
		NumPut(A_ScriptHWND,	rawDevice, 8, "Ptr")
		if Enabled:=DllCall("RegisterRawInputDevices"
			, Ptr,  &rawDevice			; pRawInputDevices (pointer to an array of RAWINPUTDEVICE)
			, UInt, 1				; uiNumDevices
			, UInt, 8 + A_PtrSize)			; cbSize (size of a RAWINPUTDEVICE structure)
			OnMessage(0xFF, "WM_INPUT")
		else traytip, RegisterRawInputDevices error, % "ErrorLevel: " ErrorLevel "`nA_lastError: " A_lastError
	} else if (!Enable) && (Enabled) {
		NumPut(1,	rawDevice, 4, "UInt")		; dwFlags = RIDEV_REMOVE (remove)
		if Enabled:=DllCall("RegisterRawInputDevices", Ptr,  &rawDevice, UInt, 1, UInt, 8 + A_PtrSize)
			OnMessage(0xFF, "")
		else traytip, De-RegisterRawInputDevices error, % "ErrorLevel: " ErrorLevel "`nA_lastError: " A_lastError
		Enabled^=1
	}
	traytip, Priorkey, % (Enabled ? "enabled" : "diabled")
}

WM_INPUT(wParam, lParam) {					; wParam = 0 if in foreground else background
	Critical						; prevent invalid handle error
	static _ := VarSetCapacity(raw, 40, 0)			; KEYBOARD DATA should be 40 bytes
	DllCall("GetRawInputData", "uint", lParam, "uint", 0x10000003, "Ptr", &raw, "uint*", 40, "uint", 8 + A_PtrSize*2)
	global PriorKey, PriorKeyTicks, Barcode
	PriorKey:=NumGet(raw, 14+A_PtrSize*2, "UShort")		; Get vk code of all keys including emulated keys
	TickCount := A_TickCount-PriorKeyTicks
	if NumGet(raw, 8)					; AHK / RDP emulated keys have handle = 0
	{
		IfGreater, TickCount, 50, SetEnv, Barcode	; Use tick count to detect barcode
		Else if (PriorKey>31) 				; If vk code is not a control code
		&& (NumGet(raw, 10+A_PtrSize*2, "UChar")=1) 	; USHORT Flags: 0 KeyDown, 1 KeyUp, 2 LeftKey, 4 RightKey
			Barcode .= Chr(PriorKey)		; save barcode because AHK not fast enough to keep up with barcode
	} 
	PriorKeyTicks+=TickCount
	traytip, WM_INPUT, % PriorKey
}

GuiClose:
GuiEscape:
ExitApp
To put the code in context, the reason that I use RegisterRawInputDevices is to capture Barcodes.
The full script contains a hotkey definition for Enter:: which then uses PriorKeyTicks to determine if the Enter comes from the barcode reader
(the tick count to the previous key will be <30ms if it's a barcode reader). It then enters the barcode in the appropriate input box of a software
by using PixelSearch.

I have tried to use other methods to capture barcodes but the barcode arrives so fast (and the computer is not a fast computer)
that occasional codes will be dropped or re-arranged if I use readinput or hotstrings. I have also tried shell-hooking to try put the
caret in the right input box with WinWaitActivate, but that is also too unreliable (it seems a window can appear to be activated
without actually being activated when it is minimized/maximized by clicking on its icon on the taskbar).

The only surefire way is to use keyboard monitoring (such as RegisterRawInputDevices). I have also tried keyboard hooking, but
keyboard hooking does not allow the source of the keystrokes to be recognised (i.e. rapid key inputs by other programs such as
AHK will be interpreted as barcodes).

The reason I would like to use hotkeys in GUI's other than keyboard accelerators is to allow users to press F1 to bring up help.
At the moment I just put a help button in the GUI that the user can click on, so it is not essential, but I just thought I'd bring
up the issue as a potential bug that can be fixed.

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 21 guests