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
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.