Get pressed modifier key(s) + mouse click + mouse movement?
Get pressed modifier key(s) + mouse click + mouse movement?
Hello,
I bought PB a few days ago and I'm searching for some help now
What I want to do:
I need to detect which mouse button is clicked while the mouse is hovering over a window (which is NOT my own!).
That window can be e.g. the Windows inbuilt file manager (aka Windows Explorer). The window
can already be the active one but this isn't a necessity (so it must work while the mouse is
hovering over it as well).
Additionally I need the information if one of the mouse buttons is not only clicked but hold
as well. There would be a minimal timeout that needs to be reached until such a "hold" would
count as a "hold", e.g. 200 ms (but this value would be user configurable).
Additionally (sorry!), it matters if the mouse gets moved while the first click was initiated.
E.g. the right mouse button is pressed and the mouse is moved 50px to somewhere else in
e.g. 1500 ms would be different from just clicking it and releasing it immediately after.
And the last thing: I need to be able to detect if a modifier key (or a combination of them)
is pressed when an initial click is happening (it doesn't matter if the keys are still pressed
when a mouse button is released). Modifier keys are shift, ctrl + alt. Win would be nice
but isn't a necessity.
The whole thing isn't ultra complicated in AutoHotkey (which I can't use for this application)
but I struggle to find anything that gets this done in PureBasic...
This does not need be cross-platform, the only supported platform is Windows...
Can a forum member help me out please?
Thank you,
Jacky
I bought PB a few days ago and I'm searching for some help now
What I want to do:
I need to detect which mouse button is clicked while the mouse is hovering over a window (which is NOT my own!).
That window can be e.g. the Windows inbuilt file manager (aka Windows Explorer). The window
can already be the active one but this isn't a necessity (so it must work while the mouse is
hovering over it as well).
Additionally I need the information if one of the mouse buttons is not only clicked but hold
as well. There would be a minimal timeout that needs to be reached until such a "hold" would
count as a "hold", e.g. 200 ms (but this value would be user configurable).
Additionally (sorry!), it matters if the mouse gets moved while the first click was initiated.
E.g. the right mouse button is pressed and the mouse is moved 50px to somewhere else in
e.g. 1500 ms would be different from just clicking it and releasing it immediately after.
And the last thing: I need to be able to detect if a modifier key (or a combination of them)
is pressed when an initial click is happening (it doesn't matter if the keys are still pressed
when a mouse button is released). Modifier keys are shift, ctrl + alt. Win would be nice
but isn't a necessity.
The whole thing isn't ultra complicated in AutoHotkey (which I can't use for this application)
but I struggle to find anything that gets this done in PureBasic...
This does not need be cross-platform, the only supported platform is Windows...
Can a forum member help me out please?
Thank you,
Jacky
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Got an AutoHotKey source that does it? Post it here and someone will easily convert it to PureBasic, because both languages are so similar in syntax.jacky wrote:The whole thing isn't ultra complicated in AutoHotkey
Welcome to PureBasic, too.
Re: Get pressed modifier key(s) + mouse click + mouse moveme
In AHK I would use a timer, for example like this (note: It doesn't take into account
that it can be a window that the mouse is hovering over but it would just a simple
thing to include that):
that it can be a window that the mouse is hovering over but it would just a simple
thing to include that):
Code: Select all
Timer_MouseButton() {
static lastCallTime := 0
static lastMouseButton, lastModifier
; Do not proceed if app is not the active window
IfWinNotActive, % "ahk_class" C["OWN"]["Some_Window_Class_Name"]
return
; If app is paused, do not process the timer at all
if (G["INT"]["IsPaused"])
return
; If a double click action is in progress, do not process the timer at all
if (G["INT"]["DoubleClickInProgress"]) {
return
}
G["INT"]["ClickType"] := 0
; Reset the mouse button hold state on enter
mouseButtonState := 0
; =======================
; = GET MOUSE BUTTON(S) =
; =======================
; 1 = down, 0 = up
mb1State := GetKeyState("LButton")
mb2State := GetKeyState("RButton")
mb3State := GetKeyState("MButton")
if (G["INI"]["General"]["MouseButtonVK4"]) {
vkState := "vk" G["INI"]["General"]["MouseButtonVK4"]
mb4State := GetKeyState(vkState)
} else {
mb4State := GetKeyState("XButton1")
}
if (G["INI"]["General"]["MouseButtonVK5"]) {
vkState := "vk" G["INI"]["General"]["MouseButtonVK5"]
mb5State := GetKeyState(vkState)
} else {
mb5State := GetKeyState("XButton2")
}
; No left + right mouse click
if (mb1State && mb2State)
return
; Set the click type correctly
G["INT"]["ClickType"] := 1
; Swapped left & right button?
if (mb1State || mb2State)
SysGet, swappedMouseButtons, 23
if (mb1State) {
mouseButtonState := mb1State
G["INT"]["MouseButton"] := "MB1"
mouseButtonName := "LButton"
if (swappedMouseButtons)
mouseButtonName := "RButton"
} else if (mb2State) {
mouseButtonState := mb2State
G["INT"]["MouseButton"] := "MB2"
mouseButtonName := "RButton"
if (swappedMouseButtons)
mouseButtonName := "LButton"
} else if (mb3State) {
mouseButtonState := mb3State
G["INT"]["MouseButton"] := "MB3"
mouseButtonName := "MButton"
} else if (mb4State) {
mouseButtonState := mb4State
G["INT"]["MouseButton"] := "MB4"
mouseButtonName := "XButton1"
} else if (mb5State) {
mouseButtonState := mb5State
G["INT"]["MouseButton"] := "MB5"
mouseButtonName := "XButton2"
}
; As long as one of the two mouse buttons isn't pressed
; get out of it again and reset the loop counter
if !(mouseButtonState) {
cntTimer := 0
return
}
; Now we passed the prechecks, now increase the timer
cntTimer++
; Found an elevated app instance
if !(CanWeCommunicate()) {
cntTimer := 0
SelfElevate(true)
}
; =======================
; = GET MODIFIER KEY(S) =
; =======================
; ctrl = ^, shift = +, alt = !, win = #
; 0 = None, 1 = Shift, 2 = Ctrl, 3 = Shift + Ctrl, 4 = Alt
; 5 = Shift + Alt, 6 = Ctrl + Alt, 7 = Shift + Ctrl + Alt
shiftState := GetKeyState("Shift", "P") ? 1 : 0
ctrlState := GetKeyState("Ctrl", "P") ? 2 : 0
altState := GetKeyState("Alt", "P") ? 4 : 0
lWinState := GetKeyState("LWin", "P") ? 8 : 0
state := ctrlState + shiftState + altState + lWinState
G["INT"]["PressedModifier"] := state
; Check for same hotkey (same mouse button + same modifier)
sameMouseButton := false, sameModifier := false, sameHotkey := false
if (mouseButtonName = lastMouseButton)
sameMouseButton := true
if (G["INT"]["PressedModifier"] = lastModifier)
sameModifier := true
if (sameMouseButton && sameModifier)
sameHotkey := true
lastMouseButton := mouseButtonName
lastModifier := G["INT"]["PressedModifier"]
DllCall("QueryPerformanceCounter", "Int64*", curCallTime)
DllCall("QueryPerformanceFrequency", "Int64*", frequencyQPC)
passedTime := (curCallTime - lastCallTime) * (1000 / frequencyQPC)
if (passedTime > (C["Timers"]["MouseButton"] * 1.5)) {
lastCallTime := curCallTime
;OutputDebug, % "Mouse button wasn't hold long enough, returning..."
return
}
; Get mouse position and "save" it as the reference for movement detection
if (cntTimer == 1)
MouseGetPos, x1, y1
mouseButtonHoldTime := G["INI"]["General"]["MouseButtonHoldTime"] / 10
KeyWait, % mouseButtonName, % "T" mouseButtonHoldTime
if (ErrorLevel) { ; Not released in T<number>
MouseGetPos, x2, y2
; Only show the menu if mouse position didn't change beyond the ini value
mouseMaxMovedDistance := G["INI"]["General"]["MouseMaxMovedDistance"]
if !(x2 < (x1 - mouseMaxMovedDistance)
|| x2 > (x1 + mouseMaxMovedDistance)
|| y2 < (y1 - mouseMaxMovedDistance)
|| y2 > (y1 + mouseMaxMovedDistance)) {
cntTimer := 0
G["INT"]["AppHwnd"] := WinExist("A")
; Do something now...
; Stop the timer from firing again
; If we'd use this loop without the single item check we wouldn't be able
; to click from one item on another one because the loop prevents that...
if (G["INT"]["SingleMenu"]) {
Loop { ; Now loop until the mouse button is released
Sleep, 25
if !(GetKeyState(mouseButtonName))
break
}
}
}
}
; Reset button state
mouseButtonState := 0
return
}
Thank you!Welcome to PureBasic, too
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Hi jacky,
Most of your requirements can be found in my Video Snipping Tool; see the Procedure MouseHook.
If you have trouble with any of the code, just post back and I or another forum member should be able to help.
Welcome to PureBasic.
Most of your requirements can be found in my Video Snipping Tool; see the Procedure MouseHook.
If you have trouble with any of the code, just post back and I or another forum member should be able to help.
Welcome to PureBasic.
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Try theese MouseHook's
Code: Select all
; RASHAD: https://www.purebasic.fr/english/viewtopic.php?p=523064#p523064
Global oTime
Procedure MouseHook(nCode, wParam, lParam)
Select wParam
Case #WM_LBUTTONDOWN
If GetTickCount_() < (oTime + GetDoubleClickTime_())
SetGadgetText(0, "Left Mouse DblClicked")
;MoveWindow_(WindowID(0),100,100,240,140,1)
Else
SetGadgetText(0, "Left Mouse Clicked")
EndIf
oTime = GetTickCount_()
Case #WM_MBUTTONDOWN
SetGadgetText(0, "Middle Mouse Clicked")
EndSelect
ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
EndProcedure
OpenWindow(0, 0, 0, 240, 140, "Mouse Hook", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
TextGadget(0, 10, 10, 180, 20, "")
hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseHook(), GetModuleHandle_(0), 0)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
UnhookWindowsHookEx_(hhkLLMouse)
Code: Select all
; idle: http://www.purebasic.fr/english/viewtopic.php?p=302739#p302739
#WH_MOUSE_LL = 14
#WM_MOUSEHWHEEL = 526
Structure MSLLHOOKSTRUCT
pt.POINT;
mouseData.l;
flags.l;
time.l;
dwExtraInfo.l;
EndStructure
Global myKeyHook.l
Procedure.l MouseProc(ncode.l, wParam.l, lParam.l)
Static lbStarttime.i, lbEndtime.i
Static rbStarttime.i, rbEndtime.i
Static sx, ex, sy, ey
Protected px, py
Static mMouseInput.MSLLHOOKSTRUCT
CopyMemory(lparam, @mMouseInput, SizeOf(MSLLHOOKSTRUCT))
Static mInput.MOUSEINPUT
If ncode = #HC_ACTION
If wParam
Select wParam
Case #WM_LBUTTONDOWN
sx = mMouseInput\pt\x
sy = mMouseInput\pt\y
lbStartTime = mMouseInput\time
AddGadgetItem(0, -1, "Left Button Down")
Case #WM_LBUTTONUP
ex = mMouseInput\pt\x
ey = mMouseInput\pt\y
lbEndtime = mMouseInput\time
AddGadgetItem(0, -1, "Left Button Up (" + Str(lbEndTime - lbStartTime) + " ms elapsed)")
Case #WM_MBUTTONDOWN
sx = mMouseInput\pt\x
sy = mMouseInput\pt\y
lbStartTime = mMouseInput\time
AddGadgetItem(0, -1, "Middle Button Down")
Case #WM_MBUTTONUP
ex = mMouseInput\pt\x
ey = mMouseInput\pt\y
lbEndtime = mMouseInput\time
AddGadgetItem(0, -1, "Middle Button Up (" + Str(lbEndTime - lbStartTime) + " ms elapsed)")
Case #WM_RBUTTONDOWN
sx = mMouseInput\pt\x
sx = mMouseInput\pt\y
rbStartTime = mMouseInput\time
AddGadgetItem(0, -1, "Right Button Down")
Case #WM_RBUTTONUP
ex = mMouseInput\pt\x
ey = mMouseInput\pt\y
rbEndtime = mMouseInput\time
AddGadgetItem(0, -1, "Right Button Up (" + Str(rbEndTime - rbStartTime) + " ms elapsed)")
Case #WM_MOUSEMOVE
px = mMouseInput\pt\x
py = mMouseInput\pt\y
Case #WM_MOUSEWHEEL
If mMouseInput\mouseData > 0
Debug "up"
Else
Debug "down"
EndIf
EndSelect
EndIf
EndIf
ProcedureReturn CallNextHookEx_(myMousehook, nCode, wParam, lParam)
EndProcedure
Procedure SetMouseHook()
hInstance = GetModuleHandle_(0)
If hInstance
myMouseHook = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseProc(), hInstance, 0)
Else
MessageRequester("hook", "can't get module handle")
EndIf
EndProcedure
Procedure KillMouseHook()
UnhookWindowsHookEx_(myMouseHook)
MyMouseHook = 0
EndProcedure
If OpenWindow(0, 0, 0, 500, 300, "Mouse Test", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
SetMouseHook()
EditorGadget (0, 10, 10, 480, 260)
TextGadget(1, 10, 280, 250, 20, "Click in this here area down here")
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
KillMouseHook()
Re: Get pressed modifier key(s) + mouse click + mouse moveme
@JHPJHP & eJan
Thanks for your kind words and the examples!
@JHPJHP
I'm currently trying to understand how these hooks work, so...
does *lParam\vkCode only ever contain one pressed key at once or all keys?
If it does contain more than one key, how can I check if a combination of
them is pressed, e.g. shift+ctrl or shift+ctrl+alt, etc.?
Thanks for your kind words and the examples!
@JHPJHP
I'm currently trying to understand how these hooks work, so...
does *lParam\vkCode only ever contain one pressed key at once or all keys?
If it does contain more than one key, how can I check if a combination of
them is pressed, e.g. shift+ctrl or shift+ctrl+alt, etc.?
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Hi jacky,
Read the following acticles:
SetWindowsHookExA function
GetAsyncKeyState function
GetKeyState function
Here is a local example posted by RASHAD: viewtopic.php?p=530624#p530624
Alternately and including, the following can be used for Caps Lock, Num Lock, and Scroll Lock
- see Windows Services & Other Stuff\Other_Stuff\OtherStuff\GlobalKeyboardHook.pb
Read the following acticles:
SetWindowsHookExA function
GetAsyncKeyState function
GetKeyState function
Here is a local example posted by RASHAD: viewtopic.php?p=530624#p530624
Single key. With other keys such as CTRL, Shift, and ALT the following can be used:jacky wrote:does *lParam\vkCode only ever contain one pressed key at once or all keys?
Code: Select all
#SHIFTED = $8000
keyCTRL = GetAsyncKeyState_(#VK_CONTROL)
If keyCTRL & #SHIFTED
;...
EndIf
- see Windows Services & Other Stuff\Other_Stuff\OtherStuff\GlobalKeyboardHook.pb
Code: Select all
#SHIFTED = $8000
CapsLock = GetKeyState_(#VK_CAPITAL) & #SHIFTED
NumLock = GetKeyState_(#VK_NUMLOCK) & #SHIFTED
ScrollLock = GetKeyState_(#VK_SCROLL) & #SHIFTED
Last edited by JHPJHP on Thu Jan 24, 2019 11:00 pm, edited 2 times in total.
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Hi JHPJHP, in my apps I've had to use "& 1" with the LED keys, like so:
Otherwise getting the state is not reliable and can return unexpected values.
Code: Select all
CapsLock = GetKeyState_(#VK_CAPITAL) & 1
NumLock = GetKeyState_(#VK_NUMLOCK) & 1
ScrollLock = GetKeyState_(#VK_SCROLL) & 1
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Hi Dude,
Thank you, it made me re-read the documentation.
- my previous post has been updated
- same as the GetAsyncKeyState function (check for most significant bit)
Thank you, it made me re-read the documentation.
- my previous post has been updated
See the following MS example: https://docs.microsoft.com/en-ca/window ... oard-inputReturn Value
Type: SHORT
The return value specifies the status of the specified virtual key, as follows:
If the high-order bit is 1, the key is down; otherwise, it is up.
If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.
- same as the GetAsyncKeyState function (check for most significant bit)
Code: Select all
#SHIFTED = $8000
CapsLock = GetKeyState_(#VK_CAPITAL) & #SHIFTED
NumLock = GetKeyState_(#VK_NUMLOCK) & #SHIFTED
ScrollLock = GetKeyState_(#VK_SCROLL) & #SHIFTED
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Hi JHPJHP,
I just tried it, and I see that $8000 indicates the toggle state. My tip was for determining the current state (on/off):
Both methods have benefits.
I just tried it, and I see that $8000 indicates the toggle state. My tip was for determining the current state (on/off):
Code: Select all
Repeat
Debug GetKeyState_(#VK_CAPITAL) & 1 ; Returns 1 if on, or 0 if off.
Sleep_(100)
ForEver
Re: Get pressed modifier key(s) + mouse click + mouse moveme
Thanks a lot, JHPJHP!
I'm currently using this:
I will probably just store the keyState in a global available structure and then
read it from the mouse hook (which I haven't looked at yet)
I left out wParam and the check for #WM_KEYUP / #WM_KEYDOWN because
it's possible that sometimes a #WM_KEYUP event isn't detected / ignored / whatever
leading to situations where the state isn't reset correctly and pressing ctrl is interpreted
as e.g. a shift instead.
I'm currently using this:
Code: Select all
#SHIFTED = $8000
Global.i hKeyboardHook
Procedure KeyboardHook(nCode, wParam, *lParam.KBDLLHOOKSTRUCT)
Protected.i shiftState, ctrlState, altState, keyState
If nCode <> #HC_ACTION
ProcedureReturn CallNextHookEx_(hKeyboardHook, nCode, wParam, *lParam)
EndIf
If GetAsyncKeyState_(#VK_SHIFT) & #SHIFTED : shiftState = 1 : Else : shiftState = 0 : EndIf
If GetAsyncKeyState_(#VK_CONTROL) & #SHIFTED : ctrlState = 2 : Else : ctrlState = 0 : EndIf
If GetAsyncKeyState_(#VK_MENU) & #SHIFTED : altState = 4 : Else : altState = 0 : EndIf
keyState = shiftState + ctrlState + altState
If keyState = 7 : Debug "Shift+Ctrl+Alt"
ElseIf keyState = 6 : Debug "Ctrl+Alt"
ElseIf keyState = 5 : Debug "Shift+Alt"
ElseIf keyState = 4 : Debug "Alt"
ElseIf keyState = 3 : Debug "Shift+Ctrl"
ElseIf keyState = 2 : Debug "Ctrl"
ElseIf keyState = 1 : Debug "Shift" : EndIf
ProcedureReturn CallNextHookEx_(hKeyboardHook, nCode, wParam, *lParam)
EndProcedure
read it from the mouse hook (which I haven't looked at yet)
I left out wParam and the check for #WM_KEYUP / #WM_KEYDOWN because
it's possible that sometimes a #WM_KEYUP event isn't detected / ignored / whatever
leading to situations where the state isn't reset correctly and pressing ctrl is interpreted
as e.g. a shift instead.
Re: Get pressed modifier key(s) + mouse click + mouse moveme
My previous version isn't 100% reliable, the 0 state isn't always returned correctly (depending on how short / long a combination of key modifiers are pressed)...
I'm trying to use this one instead now:
But it isn't optimal as well. It works rather fine on my main mechanical keyboard, but this happens:
So it returns the <None> state correctly but when pressing more than one modifier at the same time,
all of them (apart from the last) are logged instantly (in this case the first three) but there is always a small delay until
the last pressed modifier is recognized as well.
It's the same when I press just e.g. only two of them at the same time. For example Shift+Ctrl.
Then either of them appears instantly in the log while there is again a small delay before the log shows that both of them
are pressed.
On a second mechanical keyboard the <None> state isn't always reported correctly. E.g.:
After releasing Win+Ctrl+Alt (they were pressed only for a very short amount of time), not <None> was logged
but Win+Ctrl instead (which is ofc BAD, because my mouse hook reads the kbd\kbdState variable and gets wrong
information).
Any guide how to make this hook 100% reliable and without the delay until all pressed keys are recognized correctly?
I'm trying to use this one instead now:
Code: Select all
Procedure KeyboardHook(nCode, wParam, *lParam.KBDLLHOOKSTRUCT)
Static.i shiftState, ctrlState, altState, winState, lastState
If nCode <> #HC_ACTION
ProcedureReturn CallNextHookEx_(hKeyboardHook, nCode, wParam, *lParam)
EndIf
; #SHIFTED tests for "if a key is currently pressed"
; Using 1 instead would test for "on / off", e.g. for #VK_CAPITAL, #VK_NUMLOCK or #VK_SCROLL
Select wParam
Case #WM_KEYDOWN, #WM_SYSKEYDOWN
If shiftState = #False And GetAsyncKeyState_(#VK_SHIFT) & #SHIFTED : shiftState = #KM_S : EndIf ; Shift down
If ctrlState = #False And GetAsyncKeyState_(#VK_CONTROL) & #SHIFTED : ctrlState = #KM_C : EndIf ; Ctrl down
If altState = #False And GetAsyncKeyState_(#VK_MENU) & #SHIFTED : altState = #KM_A : EndIf ; Alt down
If winState = #False And ((GetAsyncKeyState_(#VK_LWIN) & #SHIFTED) Or (GetAsyncKeyState_(#VK_RWIN) & #SHIFTED)) : winState = #KM_W : EndIf ; Win down
Case #WM_KEYUP
If shiftState = #KM_S And GetAsyncKeyState_(#VK_SHIFT) & #SHIFTED : shiftState = #False : EndIf ; Shift up
If ctrlState = #KM_C And GetAsyncKeyState_(#VK_CONTROL) & #SHIFTED : ctrlState = #False : EndIf ; Ctrl up
If altState = #KM_A And GetAsyncKeyState_(#VK_MENU) & #SHIFTED : altState = #False : EndIf ; Alt up
If winState = #KM_W And ((GetAsyncKeyState_(#VK_LWIN) & #SHIFTED) Or (GetAsyncKeyState_(#VK_RWIN) & #SHIFTED)) : winState = #False : EndIf ; Win up
EndSelect
; Put the state into the structure
kbd\kbdState = shiftState + ctrlState + altState + winState
; Logging
;CompilerIf #False
With kbd
If \kbdState <> lastState
If \kbdState = #KM_WSCA : Dbg::DebugString("kbd hook: Win+Shift+Ctrl+Alt") ; 15
ElseIf \kbdState = #KM_WCA : Dbg::DebugString("kbd hook: Win+Ctrl+Alt") ; 14
ElseIf \kbdState = #KM_WSA : Dbg::DebugString("kbd hook: Win+Shift+Alt") ; 13
ElseIf \kbdState = #KM_WA : Dbg::DebugString("kbd hook: Win+Alt") ; 12
ElseIf \kbdState = #KM_WSC : Dbg::DebugString("kbd hook: Win+Shift+Ctrl") ; 11
ElseIf \kbdState = #KM_WC : Dbg::DebugString("kbd hook: Win+Ctrl") ; 10
ElseIf \kbdState = #KM_WS : Dbg::DebugString("kbd hook: Win+Shift") ; 9
ElseIf \kbdState = #KM_W : Dbg::DebugString("kbd hook: Win") ; 8
ElseIf \kbdState = #KM_SCA : Dbg::DebugString("kbd hook: Shift+Ctrl+Alt") ; 7
ElseIf \kbdState = #KM_CA : Dbg::DebugString("kbd hook: Ctrl+Alt") ; 6
ElseIf \kbdState = #KM_SA : Dbg::DebugString("kbd hook: Shift+Alt") ; 5
ElseIf \kbdState = #KM_A : Dbg::DebugString("kbd hook: Alt") ; 4
ElseIf \kbdState = #KM_SC : Dbg::DebugString("kbd hook: Shift+Ctrl") ; 3
ElseIf \kbdState = #KM_C : Dbg::DebugString("kbd hook: Ctrl") ; 2
ElseIf \kbdState = #KM_S : Dbg::DebugString("kbd hook: Shift") ; 1
ElseIf \kbdState = #False : Dbg::DebugString("kbd hook: <None>") ; 0
EndIf
EndIf
lastState = \kbdState
EndWith
;CompilerEndIf
ProcedureReturn CallNextHookEx_(hKeyboardHook, nCode, wParam, *lParam)
EndProcedure
Code: Select all
[09:12:44] kbd hook: Alt
[09:12:44] kbd hook: Ctrl+Alt
[09:12:44] kbd hook: Win+Ctrl+Alt
<a small delay>
[09:12:45] kbd hook: Win+Shift+Ctrl+Alt
[09:12:45] kbd hook: <None>
all of them (apart from the last) are logged instantly (in this case the first three) but there is always a small delay until
the last pressed modifier is recognized as well.
It's the same when I press just e.g. only two of them at the same time. For example Shift+Ctrl.
Then either of them appears instantly in the log while there is again a small delay before the log shows that both of them
are pressed.
On a second mechanical keyboard the <None> state isn't always reported correctly. E.g.:
Code: Select all
[09:20:19] kbd hook: Ctrl
[09:20:19] kbd hook: Ctrl+Alt
[09:20:19] kbd hook: Win+Ctrl+Alt
[09:20:19] kbd hook: Win+Ctrl
but Win+Ctrl instead (which is ofc BAD, because my mouse hook reads the kbd\kbdState variable and gets wrong
information).
Any guide how to make this hook 100% reliable and without the delay until all pressed keys are recognized correctly?