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
You may find this to be of interest.

http://www.purebasic.fr/english/viewtop ... ncKeyState