reliable way to detect key state?

Windows specific forum
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

reliable way to detect key state?

Post 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?
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: reliable way to detect key state?

Post 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
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: reliable way to detect key state?

Post 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
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

Re: reliable way to detect key state?

Post by Damion12 »

Thanks; I'll try that!
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

Re: reliable way to detect key state?

Post 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.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8433
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: reliable way to detect key state?

Post 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

BERESHEIT
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

Re: reliable way to detect key state?

Post 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.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: reliable way to detect key state?

Post 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
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

Re: reliable way to detect key state?

Post 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.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: reliable way to detect key state?

Post 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. :)
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

Re: reliable way to detect key state?

Post 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.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: reliable way to detect key state?

Post 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?
Damion12
User
User
Posts: 81
Joined: Tue Oct 30, 2012 1:39 am

Re: reliable way to detect key state?

Post 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....
juror
Enthusiast
Enthusiast
Posts: 228
Joined: Mon Jul 09, 2007 4:47 pm
Location: Courthouse

Re: reliable way to detect key state?

Post by juror »

You may find this to be of interest.

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