Page 1 of 1
reliable way to detect key state?
Posted: Sun Nov 27, 2016 3:06 am
by Damion12
I need to find out if keys are pressed (alt,ctrl, shift) (individually or combinations...)
I tried to use GetKeyState_(); but this seem to record a value and hold it, not always releasing it back to 0 when the key is released.
I tried a keyboard hook, but that seemed to screw up if keys are pressed/released quickly (ie: record a 'down' but not the 'up') There's got to be a good way to do this, is there?
Re: reliable way to detect key state?
Posted: Sun Nov 27, 2016 4:15 am
by Dude
For Windows only, you can do this:
Code: Select all
Macro KeyIsDown(key)
GetAsyncKeyState_(key) & $8000
EndMacro
Macro KeyIsUp(key)
GetAsyncKeyState_(key)=0
EndMacro
If KeyIsDown(#VK_CONTROL)
; ....do whatever.
EndIf
Re: reliable way to detect key state?
Posted: Sun Nov 27, 2016 5:04 am
by kenmo
Dude beat me to it.
Bool-ified:
Code: Select all
Macro KeyIsDown(key)
Bool(GetAsyncKeyState_(key) & $8000)
EndMacro
Macro KeyIsUp(key)
Bool(Not (GetAsyncKeyState_(key) & $8000))
EndMacro
Re: reliable way to detect key state?
Posted: Sun Nov 27, 2016 9:49 pm
by Damion12
Thanks; I'll try that!
Re: reliable way to detect key state?
Posted: Mon Nov 28, 2016 12:26 am
by Damion12
It doesn't seem to work inside of a keyboard hook procedure/callback. ;(
despite having 'ctrl' or 'alt' pressed while hitting 'esc'; it only 'sees' the esc key, using getasynckeystate_()&$8000 always says ctrl and alt are not pressed...
I'll try to distill it down to bare essence later and post code to replicate.
Re: reliable way to detect key state?
Posted: Mon Nov 28, 2016 3:41 am
by netmaestro
Just a bit of tooling around. Code is added to prevent the window minimizing on alt-esc. Should show all combinations of keys currently up/down using the three keys CTRL, ALT, and ESC. You may not need a hook, depending on your goals.
Code: Select all
Enumeration images
#down
#up
EndEnumeration
Enumeration gadgets
#ctrl
#alt
#escape
EndEnumeration
Enumeration message #PB_Event_FirstCustomValue
#buttonevent
EndEnumeration
Enumeration eventtype
#buttondown
#buttonup
EndEnumeration
CreateImage(#down, 64, 32, 24, #Red)
CreateImage(#up, 64, 32, 24, #Green)
Procedure thread(void)
Repeat
If GetAsyncKeyState_(#VK_CONTROL) & 32768
PostEvent(#buttonevent, 0, #ctrl, #buttondown )
Else
PostEvent(#buttonevent, 0, #ctrl, #buttonup )
EndIf
If GetAsyncKeyState_(#VK_MENU) & 32768
PostEvent(#buttonevent, 0, #alt, #buttondown )
Else
PostEvent(#buttonevent, 0, #alt, #buttonup )
EndIf
If GetAsyncKeyState_(#VK_ESCAPE) & 32768
PostEvent(#buttonevent, 0, #escape, #buttondown )
Else
PostEvent(#buttonevent, 0, #escape, #buttonup )
EndIf
Delay(50)
ForEver
EndProcedure
Procedure WinProc(hwnd, msg, wparam, lparam)
result = #PB_ProcessPureBasicEvents
Select msg
Case #WM_ACTIVATEAPP
If wparam = 0
SetForegroundWindow_(hwnd)
ProcedureReturn 0
EndIf
EndSelect
ProcedureReturn result
EndProcedure
Procedure ButtonProc()
If EventType() = #buttondown
SetGadgetState(EventGadget(), ImageID(#down))
Else
SetGadgetState(EventGadget(), ImageID(#up))
EndIf
EndProcedure
OpenWindow(0,0,0,320,240,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StickyWindow(0, 1)
SetWindowCallback(@WinProc())
ImageGadget(#ctrl, 20, 40, 0, 0, ImageID(#up))
ImageGadget(#alt, 90, 40, 0, 0, ImageID(#up))
ImageGadget(#escape, 160, 40, 0, 0, ImageID(#up))
tid = CreateThread(@thread(), 0)
BindEvent(#buttonevent, @buttonproc())
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
KillThread(tid)
WaitThread(tid)
End
Re: reliable way to detect key state?
Posted: Tue Nov 29, 2016 7:47 am
by Damion12
hmm. Your code is showing me (or I'm finally seeing) that it is not a global hook. getasynckeystate() only seems to work if your application has focus. So what I may be seeing is that something else is getting focus & locking out what I'm reading.
An easy demo is to press alt-esc a few times (leave alt pressed, and just press esc a few times) -- the 1st two are what you expect, teh 3rd leaves all three boxes green..
Definately gives me something to focus on to rule out causes...
thank you.
Re: reliable way to detect key state?
Posted: Tue Nov 29, 2016 8:10 am
by Mistrel
How about this? Test it with the W key on your keyboard.
Code: Select all
Repeat
Delay(1)
KeyStateDown=#False
If GetKeyState_(#VK_W)&$80
KeyStateDown=#True
EndIf
If KeyStateDown And Not KeyStateWasNotDown
KeyStateWasNotDown=#True
Debug "Key down!"
Else
If Not KeyStateDown And KeyStateWasNotDown
KeyStateWasNotDown=#False
Debug "Key up!"
EndIf
EndIf
ForEver
Re: reliable way to detect key state?
Posted: Fri Dec 02, 2016 11:57 pm
by Damion12
Thank you! That seems to work globally! Sorry for the late reply -- had a wicked thesis due.
That'll get me going! Works awesome.
Re: reliable way to detect key state?
Posted: Sat Dec 03, 2016 12:32 am
by Dude
Damion12 wrote:getasynckeystate() only seems to work if your application has focus
No, GetAsyncKeyState_() works globally, no matter what has the focus. I've been using my macros forever that way.

Re: reliable way to detect key state?
Posted: Sat Dec 03, 2016 10:22 pm
by Damion12
Dude wrote:Damion12 wrote:getasynckeystate() only seems to work if your application has focus
No, GetAsyncKeyState_() works globally, no matter what has the focus. I've been using my macros forever that way.

weird -- because it stops working using the demo above and repeatedly pressing ctrl-esc.
Re: reliable way to detect key state?
Posted: Sun Dec 04, 2016 3:46 am
by Dude
Damion12 wrote:An easy demo is to press alt-esc a few times (leave alt pressed, and just press esc a few times) -- the 1st two are what you expect, teh 3rd leaves all three boxes green.
Can't duplicate the problem here. Each key state works totally as expected, even when the window doesn't have the focus. That is, each key shows as green when released, and red while pressed. Is that not the case for you?
Re: reliable way to detect key state?
Posted: Mon Dec 05, 2016 6:44 am
by Damion12
Dude wrote:Damion12 wrote:An easy demo is to press alt-esc a few times (leave alt pressed, and just press esc a few times) -- the 1st two are what you expect, teh 3rd leaves all three boxes green.
Can't duplicate the problem here. Each key state works totally as expected, even when the window doesn't have the focus. That is, each key shows as green when released, and red while pressed. Is that not the case for you?
No, did I not say that already? sorry. No when I do it; it seems to 'not see' the keypress after a few presses. This mirrors what I was originally seeing with other methods....
Re: reliable way to detect key state?
Posted: Mon Dec 05, 2016 11:21 pm
by juror