LB Booster
General >> General Board >> Detecting a key release?
http://lbb.conforums.com/index.cgi?board=general&action=display&num=1517755985

Detecting a key release?
Post by Monkfish on Feb 4th, 2018, 1:53pm

Hi all. I have an event-driven program that hangs around at a WAIT command waiting for an event (key press, mouse move, etc). I need to detect when the SHIFT key is released as an event. Any ideas?

Actually I may have thought of a solution as I type this. As I know the last known state of the SHIFT, and if this happens to be down, then if I detect the SHIFT key being pressed as an event it must have been released sometime during the waiting period. Might work.
Re: Detecting a key release?
Post by Rod on Feb 4th, 2018, 7:17pm

LB can detect the shift release but not LBB I tried a timer and getasynckeystate but it isn't pretty.

Perhaps some more meat on the bones about the key detection strategy?
Re: Detecting a key release?
Post by Monkfish on Feb 4th, 2018, 8:52pm

Thanks Rob. Luckily my solution worked. It doesn't tell me exactly when the SHIFT key is released, just that it has been released since the last event. That is good enough for my purposes. grin
Re: Detecting a key release?
Post by Richard Russell on Feb 4th, 2018, 9:24pm

on Feb 4th, 2018, 7:17pm, Rod wrote:
LB can detect the shift release but not LBB

The LB Help file says of the characterInput event: "a key was pressed while the graphics window has input focus". The description of Inkey$ also refers consistently to a key having been pressed. I had no idea that an event was ever generated when a key was released, and nobody has ever mentioned that before. shocked

So is this a bug in LB 4 or an undocumented feature (or indeed is it documented somewhere that I haven't found)? If it's something that is expected, I ideally ought to modify LBB to support it, although it would not be trivial because currently key release events are completely ignored.

Richard.

Re: Detecting a key release?
Post by SarmedNafi on Feb 5th, 2018, 01:25am

A Strange talking I just read from Rob.
I have used release key event in my code, it's worked fine with LBB.
By the way, LBB timer is the best timer I ever saw. While LB timer is the worse ever.
I said that in the moment I love LB also I respect Rod very much.

Regards
Re: Detecting a key release?
Post by tsh73 on Feb 5th, 2018, 05:23am

Hello SarmedNafi.
Please post your code for release key event.


Re: Detecting a key release?
Post by Richard Russell on Feb 5th, 2018, 08:49am

on Feb 5th, 2018, 01:25am, SarmedNafi wrote:
I have used release key event in my code, it's worked fine with LBB.

No it doesn't, Rod is right. Indeed I have looked at the code of LBB, and - as I confirmed - key release events (technically the WM_KEYUP message) are completely ignored.

LB 4 seems to create an event from the release of the Shift and Ctrl keys, but no others that I have noticed. Although it would be possible to modify LBB to do the same, it would not be straightforward.

I wonder if it is happening 'by accident' in LB, particularly as it is undocumented, but I can't think of an obvious mechanism.

Richard.

Re: Detecting a key release?
Post by Monkfish on Feb 5th, 2018, 11:37am

I'm not doing anything special, just detecting how many times the UP_ARROW key is pressed while the SHIFT key is being held down. Something like this...

Code:
	print #main.gfx, "when characterInput [keypressed]"
'otherstuff
	wait

'check if shift key or up_arrow pressed
[keypressed]
	key$ = left$(Inkey$,2): a$ = right$(key$,1)
	if len(key$) = 2 then
		if a$ = chr$(_VK_SHIFT) then keycount = 0
		if a$ = chr$(_VK_UP) then goto [up_pressed]
	end if
'other stuff
	wait

[up_pressed]
	calldll #user32,"GetKeyState", _VK_SHIFT as long, r as long
	if (r and 32768) then keycount = keycount + 1
'other stuff
	wait
 

Re: Detecting a key release?
Post by Rod on Feb 5th, 2018, 4:23pm

If you want to react to Shift Up Arrow then Inkey$ should contain chr$(4)+chr$(38). It will be chr$(0)+chr$(38) if the shift key is not down.

I would not bother about key releases. You can always check the keystate or check for the specific combination as above.
Re: Detecting a key release?
Post by Richard Russell on Feb 5th, 2018, 4:34pm

on Feb 5th, 2018, 11:37am, Monkfish wrote:
I'm not doing anything special, just detecting how many times the UP_ARROW key is pressed while the SHIFT key is being held down.

Testing for Shift+UpArrow is surely just a case of comparing Inkey$ with chr$(4)+chr$(38):

Code:
    open "Test" for graphics as #main
    print #main, "when characterInput [keypressed]"
'otherstuff
    wait

'check if shift + up_arrow pressed
[keypressed]
    if Inkey$ = chr$(4) + chr$(38) then
        keycount = keycount + 1
        print keycount
    end if
    wait 

I don't see the need to use an API call to test the state of the Shift key when that information is conveyed in Inkey$ anyway. Am I missing something?

Richard.

Re: Detecting a key release?
Post by Monkfish on Feb 5th, 2018, 9:07pm

That's why I rarely post any of my code... it's just an embarrassment rolleyes

Thanks guys smiley
Re: Detecting a key release?
Post by Rod on Feb 5th, 2018, 9:19pm

Slight tweak to increase keycount if sequence of shift / up arrow else zero keycount.

After putting my ipad aside I see it also needed code to handle the stream of shift key presses from auto repeat.

Ahh defeated again! it is the final shift up message that makes my code work in LB but it fails to zero the counter in LBB till another key is pressed.


Code:
open "Test" for graphics as #main
#main "when characterInput [keypressed]"
#main "setfocus"

'otherstuff
wait

'check if shift + up_arrow pressed
[keypressed]
if Inkey$ = chr$(4) + chr$(38) then
    keycount = keycount + 1
else
    if Inkey$ <> chr$(4)+chr$(16) then
        keycount = 0
    end if
end if
print keycount
wait
 

Re: Detecting a key release?
Post by Monkfish on Feb 6th, 2018, 07:56am

Thanks Rob and Richard. I guess I was assuming that the shift+uparrow inkey$ code would only be generated the first time shift was pressed and that holding the shift key down and repeatedly pressing uparrow would subsequently only generate uparrow codes. Which is why I was using the dll call to determine whether the shift key was still down.
Re: Detecting a key release?
Post by Richard Russell on Feb 6th, 2018, 08:17am

on Feb 6th, 2018, 07:56am, Monkfish wrote:
I was assuming that the shift+uparrow inkey$ code would only be generated the first time shift was pressed

I can't speculate on how it works in LB 4, but in LBB the first byte of Inkey$ (which contains the Shift, Ctrl and Alt status) is derived by calling exactly the same API that you were using! You might as well let LBB do the work.

Richard.
Re: Detecting a key release?
Post by SarmedNafi on Feb 6th, 2018, 08:48am

Richard said,

>>> No it doesn't, Rod is right. Indeed I have looked at the code of LBB, and - as I confirmed - key release events (technically the WM_KEYUP message) are completely ignored.

I believe Richard, but it could be broken since many versions of LBB was released.

Anatoly,
We spent many nights offline, I will prepare the code.

Regards
Re: Detecting a key release?
Post by Rod on Feb 6th, 2018, 10:46am

Quote:
I was assuming that the shift+uparrow inkey$ code would only be generated the first time shift was pressed and that holding the shift key down and repeatedly pressing uparrow would subsequently only generate uparrow codes.


No, it is a little more complex but fairly straightforward. If any control key is down Inkey$ will return two characters. The first tells you what control keys are down. If only one control key is down you simply get its code so chr$(4) for shift, chr$(8) for ctrl. If both are down you would get chr$(12). So you might need to AND out the specific key you are looking to check. The second character will contain the code of the control key itself IF, nothing else is pressed. If anything else is pressed then you get that keys code. Chr$(38) in the case of Up Arrow.

Over and above that Auto Repeat kicks in. So your handler will receive a stream of keypress events. Most will be chr$(4)+chr$(16) ie shift is down and interspersed some chr$(4)+chr$(38) telling you both shift and up arrow are down.

In LB there is a final keypress message telling us shift is up. This is not ported through in LBB. So big deal or not?

Well in fifteen years of playing with LB I have never seen anyone code for a keyup event. Most often it will be completely ignored.

How about a change of control strategy? How else could you zero or reset your counter?
Re: Detecting a key release?
Post by Richard Russell on Feb 6th, 2018, 11:49am

on Feb 6th, 2018, 10:46am, Rod wrote:
Well in fifteen years of playing with LB I have never seen anyone code for a keyup event.

Hardly surprising, given that it's undocumented! Indeed, as the LB Help file always refers to 'key press' events there is no reason for anybody (including me!) to guess that 'key release' events are ever generated.

When designing LBB to be as compatible with LB 4 as I reasonably could, my sources of information were (1) the LB Help file and (2) existing programs that I gathered from wherever I could. Neither of those sources led me to suspect that there are any key release events.

Richard.

Re: Detecting a key release?
Post by SarmedNafi on Feb 6th, 2018, 1:24pm

Anatoly,

Here is the demo,

Code:
REM Keypress Key Release Demo By Sarmed Nafi'
REM Keys and Shift + Key
REM Keys F2  F3  Up  Down  Left  Right  Shift + Left  Shift + Right
REM Works with LBB better than LB
timer 1, [loop]   
[loop]
  scan
    if (keyState(_VK_F2 )=1) AND (F2=0) then '      >>  >>  F2
      F2=1
      PRINT "F2  pressed" : PRINT
    else
    if (keyState(_VK_F2 )=0) AND (F2=1) then 'Reset
      F2=0
      PRINT "F2  released" : PRINT
    else 
    if (keyState(_VK_F3 )=1) AND (F3=0) then '      >>  >>  F3
      F3=1
      PRINT "F3  pressed" : PRINT
    else
    if (keyState(_VK_F3 )=0) AND (F3=1) then 'Reset
      F3=0
      PRINT "F3  released" : PRINT
    else
    if (keyState(_VK_UP )=1) AND (up=0) AND (Fhndl=hDate) then ' >>  >>  UP 
      up=1
      PRINT "Up Arrow  pressed" : PRINT
    else
    if (keyState(_VK_UP )=0) AND (up=1) then 'Reset
      up=0
      PRINT "Up Arrow  released" : PRINT
    else
    if (keyState(_VK_DOWN )=1) AND (dwn=0) AND (Fhndl=hDate) then '  >>  >>  Dwn 
      dwn=1
      PRINT "Down Arrow  pressed" : PRINT
    else
    if (keyState(_VK_DOWN )=0) AND (dwn=1) then 'Reset
      dwn=0
      PRINT "Down Arrow  released" : PRINT
    else
    if (keyState(_VK_RIGHT )=1) AND (Rt=0) AND (keyState(_VK_SHIFT )=0) then ' >>  >>  Right
      Rt=1
      PRINT "Right Arrow  pressed" : PRINT
    else
    if (keyState(_VK_RIGHT )=0) AND (Rt=1) AND (keyState(_VK_SHIFT )=0) then 'Reset
      Rt=0
      PRINT "Right Arrow  released" : PRINT
    else
    if (keyState(_VK_RIGHT )=1) AND (shRt=0) AND (keyState(_VK_SHIFT )=1) then ' >>  >>  Shift + Right
      shRt=1
      PRINT "Shift + Right Arrow  pressed" : PRINT
    else
    if (keyState(_VK_RIGHT )=0) AND (shRt=1) AND (keyState(_VK_SHIFT )=1) then 'Reset
      shRt=0
      PRINT "Shift + Right Arrow  released" : PRINT
    else
    if (keyState(_VK_LEFT )=1) AND (lft=0) AND (keyState(_VK_SHIFT )=0) AND Grd=0 then '  >>  >>  Left
      lft=1
      PRINT "Left Arrow  pressed" : PRINT
    else
    if (keyState(_VK_LEFT )=0) AND (lft=1) AND (keyState(_VK_SHIFT )=0) then 'Reset
      lft=0
      PRINT "Left Arrow  released" : PRINT
    else
    if (keyState(_VK_LEFT )=1) AND (shlft=0) AND (keyState(_VK_SHIFT )=1) AND Grd=0 then ' >>  >>  Shift + Left
      shlft=1
      PRINT "Shift + Left Arrow  pressed" : PRINT
    else
    if (keyState(_VK_LEFT )=0) AND (shlft=1) AND (keyState(_VK_SHIFT )=1) then 'Reset
      shlft=0
      PRINT "Shift + Left Arrow  released" : PRINT
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    end if
    
  WAIT  
'------    
function keyState(keycode)
  calldll #user32, "GetAsyncKeyState", keycode AS Ulong, state AS short
  if state<0 then 
  keyState = 1
  else
  keyState = 0
  end if
  end function
'------
 


The code works under LBB better than LB.

Regards,
Sarmed.
Re: Detecting a key release?
Post by Richard Russell on Feb 6th, 2018, 2:58pm

on Feb 6th, 2018, 1:24pm, SarmedNafi wrote:
The code works under LBB better than LB.

That code uses polling. This thread has been about the triggering (or not) of an event when a key is pressed or released.

Polling in a timer handler, as you do, and then calling the 'event' handler accordingly can be an acceptable workaround, but as Rod said it's not always a very satisfactory approach. For example it ties up the timer and, potentially, has a much greater latency than a true event.

Richard.

Re: Detecting a key release?
Post by SarmedNafi on Feb 6th, 2018, 9:38pm

I remember that days I worked hard to find a way using INKEY$, unfortunately, INKEY$ is a simple command.
I think VB6 has the same mechanism inside its engine or similar to that I used to trap keyboard event.

Quote:
but as Rod said it's not always a very satisfactory approach.

Rod said that because he knows TIMER is broken under Liberty Basic.
I was made a very large search to discover how that big 3d games written under LB using TIMER command. The shock was they don't use the TIMER at all.
If anyone uses my code under LB he will put himself in trouble and be wasting his time. Then he will find there is no way but to use LBB.
When we were kids at sixties we advised each other "Don't ride a bicycle from Japan ride a bicycle from ENGLAND", It seems nothing change.

Sarmed
Re: Detecting a key release?
Post by Monkfish on Feb 7th, 2018, 09:32am

Thanks guys, and thanks Rob for clearing up exactly how Inkey$ works. smiley

Btw, I haven't looked at LB for a while. I only use LBB. Thanks Richard for still being here for us grin