Author Topic: Keyboard Library Keyhit vs _KEYHIT  (Read 411 times)

0 Members and 1 Guest are viewing this topic.

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Keyboard Library Keyhit vs _KEYHIT
« on: November 25, 2020, 05:59:41 PM »
But it is definitely very sad to have to type own keyboard solution. But I believe that if you combine INKEY$ and _KEYHIT, you would probably achieve the same effect. Or really not?

I didn't want to jump off topic from my little splash screen demo just to talk about the differences in keyboard handling routines, so I thought I'd hold his discussion here.

To follow along with what I'm illustrating, grab the two attachments below and put them in your QB64 program, and then you can run the following code:

Code: QB64: [Select]
  1. '$INCLUDE:'Keyboard Library.BI'
  2.  
  3. PRINT "CTRL-TAB"
  4.     k = _KEYHIT
  5.     IF k <> 0 THEN PRINT k
  6.     _LIMIT 10
  7. LOOP UNTIL k = -27
  8.  
  9. PRINT "------"
  10.  
  11.     k = KeyHit
  12.     IF k <> 0 THEN PRINT k
  13.     _LIMIT 10
  14. LOOP UNTIL k = -27
  15.  
  16. '$INCLUDE:'Keyboard Library.BM'

Now for our first test, test a simple little CTRL-TAB:

CTRL-TAB
 100306
-105
-100306
-17
 27
-27
------
 100017
 100306
 9
-9
-100017
-100306

Now, run the same program once again, only this time you want to hit CTRL-I:

CTRL-TAB
 100306
 105
-105
-100306
-17
 27
-27
------
 100017
 100306
 105
-105
-100017
-100306

Take a moment and compare the results. 

With TAB: 
For _KEYHIT, we don't have a positive keydown code, but we have a key-up code of -105.
With KeyHit, we have codes of 9 and -9.

With I:
For _KEYHIT, we have codes of 105 and -105.
With KeyHit, we have codes of 105 and -105.

So with _KEYHIT, we can't even generate a key down event for CTRL-TAB, and our key up code is the one for CTRL-I instead!! 



Run the same test again, and this time all you want to do is simply hit the CAPSLOCK key for both routines:

CTRL-TAB
-100301
-20
 27
-27
------
 100301
-100301

Now for QB64, we get some really mixed results for this key with _KEYHIT.  On one hit, we get a value of -100301 for when we press the key down.  On the next hit, we get a value of +100301 for the same key down.  It all depends on if _CAPSLOCK = TRUE or not.  And, for some odd reason, we have a key up code of -20??

With KeyHit, from the library, we get a sensible 100301 for key down and -100301 for keyup, regardless of whether _CAPSLOCK is up or down.



And these are just two of the many differences between the two routines.  QB64 has some serious failure in its built-in keyboard scan codes.  For most applications, where all you have to worry about is an user typing in A-Z and 0-9 type keys, they work fine.  (If they didn't, our boards would be full of bug reports on the issue, and most people have no clue how badly those commands actually fail to work properly.) 

For my game, I'm allowing the user to assign keys to whatever mapping they want on their keyboard, so I have no idea if somebody, somewhere, might want to use CTRL-TAB to swap weapons and CTRL-I to open their inventory...  If they do, I need to be able to read each of those as independent keystrokes and not have them return the same values, so I wrote my own keyboard library which completely ignores QB64's flawed input routines.  Honestly, as one of the guys who helps contribute to the QB64 source, I'd swap our existing _KEYHIT out for this KeyHit, except for one big thing:  I'm just a Windows-guy.  This relies on the windows API calls to work and won't work in Linux or Mac, and I have no idea about their internal keyhandling routines to even start to make it work for them.

In my opinion, KeyHit is leagues better than _KEYHIT for Windows, but unfortunately, it doesn't work at all for Linux or Mac users. 

« Last Edit: November 25, 2020, 06:33:14 PM by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #1 on: November 25, 2020, 06:41:28 PM »
Another difference in this library and what QB64 comes with by default is the addition of Extended Input.

Code: QB64: [Select]
  1. '$INCLUDE:'Keyboard Library.BI'
  2.  
  3. ExtendedInput a$
  4.  
  5.  
  6. _KEYCLEAR 'Without this in here, INPUT will read from our existing _KEYHIT buffer
  7. '         (which ExtendedInput doesn't use since it uses KeyHit from the library)
  8. '         This causes a$ to instantly fill and mirror our previous input as close as it can.
  9.  
  10.  
  11.  
  12. '$INCLUDE:'Keyboard Library.BM'


With the above, type in something simple such as:

"A" + "S" + "D" +"F"  + Left Arrow + Left Arrow + "G"

The first extended input should end up giving you ASGDF for an input.  Extended Input supports using arrow keys for editing.

Try the same with INPUT and all you end up with is ASDFG.  There's no arrow key support at all.



Want an even better example of what Extended Input can do for us?  Copy some text into your clipboard and run the program.  Then hit a standard CTRL-V to paste that text into your input field. 

Works just fine with ExtendedInput, but you can't do that at all with just INPUT...

And then test those routines with CTRL-Z for undo.  Paste some junk into the input field and then CTRL-Z  and you can see your change instantly disappear...

That little Keyboard Library I attached above for download, can do a whole lot of little things for us to expand how QB64 interacts with our most common input device.  :)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #2 on: November 25, 2020, 08:13:19 PM »
Hi SMcNeil

Quote
So with _KEYHIT, we can't even generate a key down event for CTRL-TAB, and our key up code is the one for CTRL-I instead!!

Try doing alternate ctrl -tab and ctrl-k tests and see if  the  _KEYHIT upcode for ctrl-tab = the keyhit upcode for ctrl-k

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #3 on: November 25, 2020, 08:41:33 PM »
The _KEYHIT codes for ctrl-tab is (none)/-105.
The KeyHit codes for ctrl-k is +107/-107.

(Not counting the 100000+ code for ctrl itself, which you see before either.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #4 on: November 25, 2020, 08:50:06 PM »
Is that data from running _KEYHIT  after KEYHIT?

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #5 on: November 25, 2020, 08:53:57 PM »
KeyHit and _KEYHIT are on two different buffers.  You need a _KEYCLEAR to clear your _KEYHIT buffer, before relying on it, as you’re not reading from it with KeyHit.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #6 on: November 25, 2020, 09:11:41 PM »
Ok Thanks

I still think in DOS v6.2 terms when there was one keyboard buffer.  It was at an absolute address in ram. AFAIK

Now with the WIndows API there can be multiple buffers.  Is there a limit on number of buffers that are effected by keyboard input.

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #7 on: November 25, 2020, 09:50:27 PM »

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #8 on: November 25, 2020, 09:50:53 PM »
QB45 had INP for direct access, and INKEY$ had a buffer.  For instance, just try something like the following:

SLEEP
a$ = INKEY$
PRINT a$

SLEEP pauses program execution until you hit a key, but it doesn't read from the buffer.  If you hit "A" to break sleep, a$ is going to instantly be "A".   One checked direct presses, the other uses a buffer.



QB64 has INP, INKEY$, and _KEYHIT -- all of which use different buffers, as you can see with this little program below:

Code: QB64: [Select]
  1.     i = INP(&H60)
  2.     IF i <> oldi THEN PRINT i;
  3.     oldi = i
  4. LOOP UNTIL i = 156
  5.  
  6.     i$ = INKEY$
  7.     IF i$ <> "" THEN PRINT i$;
  8. LOOP UNTIL i$ = CHR$(13)
  9.  
  10.     k = _KEYHIT
  11.     IF k <> 0 THEN PRINT k;
  12. LOOP UNTIL k = 0

The KeyHit from the library above works the most like INP does, in the fact that it doesn't natively have a buffer built in, so it doesn't affect the _KEYHIT or INKEY$ buffers at all.  If you're going to use KeyHit as a replacement for _KEYHIT, it's best to just forget about _KEYHIT completely, or else you'll need to be manually clearing those buffers with _KEYCLEAR, much like you would if you intermingled INKEY$ and _KEYHIT both into a program.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #9 on: November 25, 2020, 09:56:53 PM »
I'm looking at
https://docs.microsoft.com/en-us/windows/win32/api/_inputdev/

kinda complicated.

At the heart of them, they're not all that complicated.  Basically, what you need is just a simple:

DECLARE LIBRARY 'function is already used by QB64 so "User32" is not required
    FUNCTION GetKeyState% (BYVAL vkey AS LONG)
    FUNCTION GetAsyncKeyState% (BYVAL vkey AS LONG)
END DECLARE

Of course, these just tell you if a physical key is pressed, such as "A".  It doesn't tell you if it's "a" or "A", or if SHIFT is modifying the return value, or if CAPSLOCK is in effect...  All they tell you is "the button right of CAPSLOCK and left of S" was pressed, or released.

You'll have to decode the particulars of what it is, on your own, much like the library above does.  Look down at the function KeyHit&, and you'll see where it sorts out all the logic for what values to return for us.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #10 on: November 25, 2020, 11:51:20 PM »

SMcNeil
 This windows programming is challenging

Looking at
DECLARE LIBRARY 'function is already used by QB64 so "User32" is not required
    FUNCTION GetKeyState% (BYVAL vkey AS LONG)
    FUNCTION GetAsyncKeyState% (BYVAL vkey AS LONG)
END DECLARE

now.   

 FUNCTION GetKeyState% (BYVAL vkey AS LONG)
is vkey an input and is the asc of a character returned in GetKeyState%

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #11 on: November 26, 2020, 12:21:32 AM »
Is the following TYPE required by the API ?

 
Quote
TYPE KeyboardInfo_Type
    Index AS LONG
    ASCII AS LONG
    Ctrl AS LONG
    Shift AS LONG
    Alt AS LONG
    AltGr AS LONG
    Repeat AS _FLOAT
    LastHit AS _FLOAT
    Down AS LONG
    AltShift AS LONG
    AltCtrl AS LONG
    AltAltGr AS LONG
    CtrlShift AS LONG
    CtrlAlt AS LONG
    CtrlAltGr AS LONG
    ShiftAltGr AS LONG
    CtrlAltShift AS LONG
END TYPE

Does the &H8000 in

 
Quote
r = GetKeyState(Keys(i).Index) AND &H8000

set the MSB bit and for what purpose?

OK found out what the &H8000 was for from here:
https://stackoverflow.com/questions/6331868/using-getkeystate

Quote
The highest bit tells if key is pressed. The lowest tells if key is toggled (like, if caps lock is turned on).

This is a lot different from INKEY$.  You gotta give the GetKeyState function the ASC of the key to look for.  That is totally redundant.

 I'm not sure why windows does not give us a function similar to INKEY$ or better yet a universal API that returns an array that contains all the data, you'd ever need,  as to user input, be it network, mouse, keyboard etc.

I would rather be parsing an array of raw return data than trying to interact with windows messages any day.

Anyway there is probably a reason for it.
« Last Edit: November 26, 2020, 01:48:24 AM by NOVARSEG »

Online SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3232
    • Steve’s QB64 Archive Forum
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #12 on: November 26, 2020, 01:45:40 AM »
Windows gives us these values: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

Now, I didn’t want folks to have to go around learning a whole new set of codes and syntax to use my library routine, so I remapped all those values to match what _KEYHIT should give us. 

For example, windows reports 0xA0 for left shift.  _KEYHIT calls it 100305 (I think, off the top of my head.)  I remapped those values for us.

While doing the remapping, I expanded it so we can customize for any sort of keybinding we want.

A is 65
a is 92

What if I want Ctrl-A to be a code for Ã, Å, Ā, À, Á, Â, Ä, or Æ?  No problem!  I find an unicode font that supports those characters, find the value for that font in the character set, and I remap it to respond to Ctrl-A.

Every one of those types can return a different code for us, if we want them to.

By default, ctrl-a isn’t any different than just plain a, but that doesn’t mean it can’t be.  Some foreign language keyboards use extra combinations for accents over letters.  The library allows you to custom set for those, and make certain your input responds to match your desires.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Regular
  • Posts: 174
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #13 on: November 26, 2020, 02:02:08 AM »
Ok thanks

I did not think of remapping etc

Now if everyone's keyboard was the same it would be easier!

Offline Petr

  • Forum Resident
  • Posts: 1540
  • The best code is the DNA of the hops.
Re: Keyboard Library Keyhit vs _KEYHIT
« Reply #14 on: November 26, 2020, 05:12:30 AM »
Thank you for the detailed explanation and analysis of the problem. Also thank you for the library, it will be very useful for everyone.