Author Topic: Windows Console INP Scancodes  (Read 2293 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Windows Console INP Scancodes
« on: July 26, 2019, 09:54:31 am »
Step 1: Copy the following and paste it into your QB64 folder as "Test1.h"

Code: C++: [Select]
  1. int32 ConsoleKeyhit (int32 toggle);
  2.  
  3. int32 ConsoleKeyhit (int32 toggle)
  4. {
  5.   HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE);
  6.   INPUT_RECORD irInputRecord;
  7.   DWORD dwEventsRead;
  8.   INT32 cChar;
  9.  
  10.   while(ReadConsoleInputA (hStdin, &irInputRecord, 1, &dwEventsRead)) /* Read key press */
  11.     if (irInputRecord.EventType == KEY_EVENT)
  12.     {
  13.       cChar = irInputRecord.Event.KeyEvent.wVirtualScanCode;
  14.       if (toggle) {
  15.           if (!irInputRecord.Event.KeyEvent.bKeyDown) cChar = -cChar;
  16.       }else{
  17.           if (!irInputRecord.Event.KeyEvent.bKeyDown) cChar = cChar +128;
  18.       }
  19.           return cChar;
  20.     }
  21.   return EOF;
  22. }

Step 2: Copy and paste the following code in QB64.

Code: QB64: [Select]
  1.     FUNCTION ConsoleKeyhit (BYVAL Toggle AS LONG)
  2.  
  3.  
  4. _DEST _CONSOLE 'Required to get the scan codes, and I haven't sorted out a way to bypass this line yet.
  5. _ECHO "Hello"
  6.  
  7. TOGGLE = -1 'Change TRUE/FALSE value to see the different return values for codes.
  8.  
  9.     'See the INP Scan Codes at https://www.qb64.org/wiki/Keyboard_scancodes
  10.     IF TOGGLE THEN
  11.         a = ConsoleKeyhit(0) 'To retrieve the INP Scancodes as QB64 lists them
  12.     ELSE
  13.         a = ConsoleKeyhit(1) 'To retrieve positive/negative codes for down/up codes
  14.     END IF
  15.     PRINT a
  16.     IF a = 57 THEN TOGGLE = NOT TOGGLE 'Spacebar to Swap toggle values
  17. LOOP UNTIL a = 1 'ESC key to quit

Step 3: Compile, Run, and Test.



As QB64 currently exists, we can only get INPUT from the CONSOLE, which necessitates typing something and then hitting ENTER.

This code allows us to get single character presses, one at a time, from the console.

Now, I was playing around with trying to have this return the _KEYHIT codes for us, but it never seemed to work quite perfect to me.  Keystrokes like SHIFT-A would require 2 key presses to register, or else hitting A would return 2 different key strokes.  It just doesn't work as one would expect -- at least not without a little more work than I'm willing to put into it, at the moment, with my limited freetime.

Instead, what I've came up with is the above, which returns INP scan codes for us, without any issues arising from SHIFT being up/down and trying to read a key release that just hasn't happened yet.

INP ScanCodes can be viewed here: https://www.qb64.org/wiki/Keyboard_scancodes



NOTE: Currently this has a toggle parameter which an user can make use of.

Personally, I'm not so keen on the Code + 128 method to detect key releases; I find it much simpler to simply have a positive and negative value for them.  Positive value means the key was pressed.  Negative value means the key was released.

Other folks might like the way QB64 deals with the INP codes, so I've implemented a toggle so you can choose withever method you prefer.  Keypresses are the same code, no matter what toggle method you choose -- just the release codes are different. 

NOTE 2: Since this uses Windows API routines, it's *NOT* going to work for Mac/Linux folks.  I don't have a PC with either of those OSes on them, and no great experience coding for either system, so I don't have a clue how we'd get the same functionality on those systems.  I'm afraid this is a Windows-Only method, unless somebody more familiar than me wants to take up the effort to write us their equivalent code.



Test this out for a while, and offer any feedback or issues which you folks might have with it.  It should be easy enough to add to QB64 itself -- if folks would like to see it added to the language -- but it deserves a good set of testing first to make certain it doesn't do anything unexpected for us.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: Windows Console INP Scancodes
« Reply #1 on: July 26, 2019, 10:33:04 am »
Issue found and fixed, regarding the requirement that _DEST _CONSOLE be used. 

Code: QB64: [Select]
  1.     FUNCTION ConsoleKeyhit (BYVAL Toggle AS LONG)
  2.  
  3.  
  4. '_DEST _CONSOLE '**NOT** Required to get the scan codes, and I haven't sorted out a way to bypass this line yet.
  5.  
  6. 'I was thinking the above was required, and it's **NOT**.  We read the codes just fine without it...
  7. 'We just need it so we can PRINT the results to the console, since I didn't make use of _ECHO, like an
  8. '    XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  9. '  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  10. ' XXXXXXXXXXXXXXXXXX         XXXXXXXX
  11. 'XXXXXXXXXXXXXXXX              XXXXXXX
  12. 'XXXXXXXXXXXXX                   XXXXX
  13. ' XXX     _________ _________     XXX      What can I say?
  14. '  XX    I  _xxxxx I xxxxx_  I    XX        Even I have simple brainfarts,
  15. ' ( X----I         I         I----X )           From time to time!!
  16. '( +I    I      00 I 00      I    I+ )
  17. ' ( I    I    __0  I  0__    I    I )
  18. '  (I    I______ /   \_______I    I)
  19. '   I           ( ___ )           I
  20. '   I    _  :::::::::::::::  _    i
  21. '    \    \___ ::::::::: ___/    /
  22. '     \_      \_________/      _/
  23. '       \        \___,        /
  24. '         \                 /
  25. '          |\             /|
  26. '          |  \_________/  |
  27.  
  28.  
  29. _ECHO "Hello"
  30. TOGGLE = -1 'Change TRUE/FALSE value to see the different return values for codes.
  31.  
  32.     'See the INP Scan Codes at https://www.qb64.org/wiki/Keyboard_scancodes
  33.     IF TOGGLE THEN
  34.         a = ConsoleKeyhit(0) 'To retrieve the INP Scancodes as QB64 lists them
  35.     ELSE
  36.         a = ConsoleKeyhit(1) 'To retrieve positive/negative codes for down/up codes
  37.     END IF
  38.     'PRINT a 'We **DON'T** require _DEST _CONSOLE if we use the _ECHO below, instead of this line.  _DUH!!
  39.     _ECHO STR$(a)
  40.     IF a = 57 THEN TOGGLE = NOT TOGGLE 'Spacebar to Swap toggle values
  41. LOOP UNTIL a = 1 'ESC key to quit

I feels like an idiot now.  You guys would NEVER believe how much time I spent trying to sort out what I was doing wrong with the routine.  I checked into why the handle might not be working.  Into whether I could use func__console() inside the routine itself.  Into all sorts of junk...

... only to eventually smack myself upside the head and say, "It's not the routine that's failing to work -- it's that you can't print to the console with setting it as the destination!"

/CRY!!



Semi-related question:  If we set $CONSOLE:ONLY, shouldn't _DEST _CONSOLE be in effect automatically?  What else are we going to use for the destination -- the non-existent GL window we never created??
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline doppler

  • Forum Regular
  • Posts: 241
Re: Windows Console INP Scancodes
« Reply #2 on: July 26, 2019, 06:04:32 pm »
Sorry I didn't realize I would cause a little grief.
Flip-side in the end I got a better working console:only.

Making a dumb console window smarter is always a win.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: Windows Console INP Scancodes
« Reply #3 on: July 26, 2019, 08:42:41 pm »
Sorry I didn't realize I would cause a little grief.
Flip-side in the end I got a better working console:only.

Making a dumb console window smarter is always a win.

It wasn’t you which caused me any grief; it was just me overlooking the obvious.  I kept debugging an issue with my code that really wasn’t an issue with the code...
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!