Posts: 60
Threads: 11
Joined: Apr 2022
Reputation:
7
Is the _KeyDown command (in regards to the SHIFT key) only recognizing a change in state rather than reading the position of the key? Run the following program:
Code: (Select All)
Common Shared true%, false%
true% = (1 = 1): false% = (1 = 0)
start:
Locate 10, 10
If Shiftpressed% Then Print "YES" Else Print "NO "
If InKey$ = Chr$(27) Then System
GoTo start
Function Shiftpressed%
'returns true% if either SHIFT key is pressed
If _KeyDown(100303) + _KeyDown(100304) = 0 Then
Shiftpressed% = false%
Else
Shiftpressed% = true%
End If
End Function
Press and release shift - everything works great.
Click on another window other than the running QB64 program.
Press and hold the shift key.
Click on the running QB64 program
The state never changes to YES until you cycle the shift key. I am guessing that the state of the key is not actually being read, but rather a change in state while the QB64 program is the active window is required?
I am unsure how to get around this, but if anyone has any ideas how I can accurately register the state of a key when reentering a QB64 program it would be greatly appreciated.
Posts: 195
Threads: 5
Joined: Apr 2022
Reputation:
21
09-16-2024, 09:28 AM
(This post was last modified: 09-16-2024, 11:25 AM by JRace.)
I'm not sure how to scan the current keyboard state in PE.
I'm sure it can be done, probably in Microsoft's overly-complicated PITA manner, using the Windows API or maybe the GetKeyboardState function in winuser.h.
Key and mouse state changes in Windows are usually sent to the program whose window currently has the focus.
Posts: 1,277
Threads: 120
Joined: Apr 2022
Reputation:
100
Here is some code using _DEVICES that works.
Click off the program window, press either shift key (or both), then click the program window to bring it back into focus.
The program includes a handy set of constants and key names you can use as well.
Code: (Select All) ' __________________________________________________________________________________________________________________________________________________
'/ KEYBOARD KEY _BUTTON CONSTANTS \
CONST CLKEY_ESC = 2 ' |
CONST CLKEY_F1 = 60 ' FUNCTION KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_F2 = 61 ' _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ |
CONST CLKEY_F3 = 62 ' ||ESC|| ||F1 |||F2 |||F3 |||F4 || ||F5 |||F6 |||F7 |||F8 || ||F9 |||N/A|||F11|||F12|| |
CONST CLKEY_F4 = 63 ' ||___|| ||___|||___|||___|||___|| ||___|||___|||___|||___|| ||___|||___|||___|||___|| |
CONST CLKEY_F5 = 64 ' |/___\| |/___\|/___\|/___\|/___\| |/___\|/___\|/___\|/___\| |/___\|/___\|/___\|/___\| |
CONST CLKEY_F6 = 65 ' |
CONST CLKEY_F7 = 66 ' NOTE: F10 does not register as a _BUTTON. I know, strange but true. |
CONST CLKEY_F8 = 67 ' These _BUTTON contants were provided by gx.bi in dbox's Game Engine: https://github.com/boxgaming/gx |
CONST CLKEY_F9 = 68 ' |
CONST CLKEY_F11 = 88 ' |
CONST CLKEY_F12 = 89 ' |
CONST CLKEY_BACKQUOTE = 42 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_1 = 3 ' FIRST KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_2 = 4 ' |
CONST CLKEY_3 = 5 ' _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _________ |
CONST CLKEY_4 = 6 ' ||`~ |||1! |||2@ |||3# |||4$ |||5% |||6^ |||7& |||8* |||9( |||0) |||-_ |||=+ |||BACKSP || |
CONST CLKEY_5 = 7 ' ||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||_______|| |
CONST CLKEY_6 = 8 ' |/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/_______\| |
CONST CLKEY_7 = 9 ' |
CONST CLKEY_8 = 10 ' |
CONST CLKEY_9 = 11 ' |
CONST CLKEY_0 = 12 ' |
CONST CLKEY_MINUS = 13 ' |
CONST CLKEY_EQUALS = 14 ' |
CONST CLKEY_BACKSPACE = 15 ' |
CONST CLKEY_TAB = 16 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_Q = 17 ' SECOND KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_W = 18 ' |
CONST CLKEY_E = 19 ' _______ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _______ |
CONST CLKEY_R = 20 ' ||TAB |||Q |||W |||E |||R |||T |||Y |||U |||I |||O |||P |||[{ |||]} |||\| || |
CONST CLKEY_T = 21 ' ||_____|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||_____|| |
CONST CLKEY_Y = 22 ' |/_____\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/_____\| |
CONST CLKEY_U = 23 ' |
CONST CLKEY_I = 24 ' |
CONST CLKEY_O = 25 ' |
CONST CLKEY_P = 26 ' |
CONST CLKEY_LBRACKET = 27 ' |
CONST CLKEY_RBRACKET = 28 ' |
CONST CLKEY_BACKSLASH = 44 ' |
CONST CLKEY_CAPSLOCK = 59 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_A = 31 ' THIRD KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_S = 32 ' |
CONST CLKEY_D = 33 ' ________ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ ____________ |
CONST CLKEY_F = 34 ' ||CAPS |||A |||S |||D |||F |||G |||H |||J |||K |||L |||;: |||'" |||ENTER || |
CONST CLKEY_G = 35 ' ||______|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||__________|| |
CONST CLKEY_H = 36 ' |/______\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/__________\| |
CONST CLKEY_J = 37 ' |
CONST CLKEY_K = 38 ' |
CONST CLKEY_L = 39 ' |
CONST CLKEY_SEMICOLON = 40 ' |
CONST CLKEY_QUOTE = 41 ' |
CONST CLKEY_ENTER = 29 ' |
CONST CLKEY_LSHIFT = 43 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_Z = 45 ' FOURTH KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_X = 46 ' |
CONST CLKEY_C = 47 ' _____________ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____________ |
CONST CLKEY_V = 48 ' ||LEFT SHIFT |||Z |||X |||C |||V |||B |||N |||M |||,< |||.> |||/? |||RIGHT SHIFT|| |
CONST CLKEY_B = 49 ' ||___________|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___|||___________|| |
CONST CLKEY_N = 50 ' |/___________\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___\|/___________\| |
CONST CLKEY_M = 51 ' |
CONST CLKEY_COMMA = 52 ' |
CONST CLKEY_PERIOD = 53 ' |
CONST CLKEY_SLASH = 54 ' |
CONST CLKEY_RSHIFT = 55 ' |
CONST CLKEY_LCTRL = 30 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_LWIN = 348 ' FIFTH KEY ROW _BUTTON CONSTANTS |
CONST CLKEY_SPACEBAR = 58 ' |
CONST CLKEY_RWIN = 349 ' ______ ______ ______ _____________________________________________ ______ ______ ______ |
CONST CLKEY_RCTRL = 286 ' ||LCTL|||LWIN|||MENU|||SPACEBAR |||N/A |||RWIN|||RCTL|| |
CONST CLKEY_MENU = 350 ' ||____|||____|||____|||___________________________________________|||____|||____|||____|| |
' |/____\|/____\|/____\|/___________________________________________\|/____\|/____\|/____\| |
' |
CONST CLKEY_NUMLOCK = 326 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_NUMPAD_DIVIDE = 310 ' NUMBER PAD _BUTTON CONSTANTS |
CONST CLKEY_NUMPAD_MULTIPLY = 56 ' |
CONST CLKEY_NUMPAD_MINUS = 75 ' _____ _____ _____ _____ |
CONST CLKEY_NUMPAD_7 = 72 ' ||NUM|||/ |||* |||- || |
CONST CLKEY_NUMPAD_8 = 73 ' ||___|||___|||___|||___|| |
CONST CLKEY_NUMPAD_9 = 74 ' |/___\|/___\|/___\|/___\| |
CONST CLKEY_NUMPAD_PLUS = 79 ' _____ _____ _____ _____ |
CONST CLKEY_NUMPAD_4 = 76 ' ||7 |||8 |||9 |||+ || |
CONST CLKEY_NUMPAD_5 = 77 ' ||___|||___|||___||| || |
CONST CLKEY_NUMPAD_6 = 78 ' |/___\|/___\|/___\|| || |
CONST CLKEY_NUMPAD_1 = 80 ' _____ _____ _____|| || |
CONST CLKEY_NUMPAD_2 = 81 ' ||4 |||5 |||6 ||| || |
CONST CLKEY_NUMPAD_3 = 82 ' ||___|||___|||___|||___|| |
CONST CLKEY_NUMPAD_ENTER = 285 ' |/___\|/___\|/___\|/___\| |
CONST CLKEY_NUMPAD_0 = 83 ' _____ _____ _____ _____ |
CONST CLKEY_NUMPAD_PERIOD = 84 ' ||1 |||2 |||3 |||E || |
' ||___|||___|||___|||N || |
' |/___\|/___\|/___\||T || |
' ___________ _____||E || |
' ||0 |||. |||R || |
' ||_________|||___|||___|| |
' |/_________\|/___\|/___\| |
' |
CONST CLKEY_UP = 329 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_LEFT = 332 ' ARROW KEY _BUTTON CONSTANTS |
CONST CLKEY_DOWN = 337 ' |
CONST CLKEY_RIGHT = 334 ' _____ |
' || || |
' ||___|| |
' |/___\| |
' _____ _____ _____ |
' || ||| ||| || |
' ||___|||___|||___|| |
' |/___\|/___\|/___\| |
' |
CONST CLKEY_SCRLK = 71 ' ----------------------------------------------------------------------------------------- |
CONST CLKEY_PAUSE = 70 ' POSITION KEY _BUTTON CONSTANTS |
CONST CLKEY_INSERT = 339 ' |
CONST CLKEY_HOME = 328 ' _____ _____ _____ |
CONST CLKEY_PAGEUP = 330 ' ||N/A|||SCR|||PAU|| |
CONST CLKEY_DELETE = 340 ' ||___|||___|||___|| NOTE: Pause not working on my system? |
CONST CLKEY_END = 336 ' |/___\|/___\|/___\| |
CONST CLKEY_PAGEDOWN = 338 ' _____ _____ _____| |
' ||INS|||HOM|||PUP|| |
' ||___|||___|||___|| |
' |/___\|/___\|/___\| |
' _____ _____ _____ |
' ||DEL|||END|||PDN|| |
' ||___|||___|||___|| |
' |/___\|/___\|/___\| |
' |
'\__________________________________________________________________________________________________________________________________________________/
DIM Devices AS INTEGER ' used to activate _DEVICES
DIM Kbd AS LONG ' keyboard device number
DIM b AS INTEGER ' button (key) counter
DIM KeyName(350) AS STRING ' name of each key
Devices = _DEVICES
' --------------------
'| Load the key names |
' --------------------
FOR K = 1 TO 350 ' read in names of keyboard controller keys
KeyName(K) = "" ' clear key name
IF K < 90 THEN READ KeyName(K) ' first 89 names are in data statements
IF K = 285 THEN READ KeyName(K) ' 285, 90 through 284 are skipped
IF K = 286 THEN READ KeyName(K) ' 286
IF K = 310 THEN READ KeyName(K) ' 310, 287 through 309 are skipped
IF K > 325 THEN READ KeyName(K) ' 326 through 350 are in data statements
NEXT K
'Keyboard _BUTTON 1 - 20
DATA "","Escape","1","2","3","4","5","6","7","8","9","0","Minus","Equals","Backspace","Tab","Q","W","E","R"
'Keyboard _BUTTON 21 - 40
DATA "T","Y","U","I","O","P","Left Bracket","Right Bracket","Enter","Left CTRL","A","S","D","F","G","H","J","K","L","Semicolon"
'Keyboard _BUTTON 41 - 50
DATA "Quote","","Left Shift","Back Slash","Z","X","C","V","B","N"
'Keyboard _BUTTON 51 - 60
DATA "M","Comma","Period","Fore Slash","Right Shift","Numpad Multiply","","Space Bar","Caps Lock","F1"
'Keyboard _BUTTON 61 - 70
DATA "F2","F3","F4","F5","F6","F7","F8","F9","","Pause"
'Keyboard _BUTTON 71 - 80
DATA "Scroll Lock","Numpad 7","Numpad 8","Numpad 9","Numpad Minus","Numpad 4","Numpad 5","Numpad 6","Numpad Plus","Numpad 1"
'Keyboard _BUTTON 81 - 89
DATA "Numpad 2","Numpad 3","Numpad 0","Numpad Period","","","","F11","F12"
'Keyboard _BUTTON 285 - 286
DATA "Numpad Enter","Right CTRL"
'Keyboard _BUTTON 310
DATA "Numpad Divide"
'Keyboard _BUTTON 326 - 340
DATA "Number Lock","","Home","UP Arrow","Page UP","","LEFT Arrow","","RIGHT Arrow","","End","DOWN Arrow","Page Down","Insert","Delete"
'Keyboard _BUTTON 341 - 350
DATA "","","","","","","","Left Win","Right Win","Menu"
DO
Kbd = _DEVICEINPUT ' check for device input
IF Kbd = 1 THEN ' was the device the keyboard?
FOR b = 1 TO 350 ' yes, scan through the buttons (keyboard keys)
IF _BUTTON(b) <> 0 THEN ' is this button pressed?
PRINT _BUTTON(b); KeyName(b) ' yes, print the button name
END IF
NEXT b
END IF
_LIMIT 60 ' don't hog the CPU
LOOP UNTIL _KEYDOWN(27) ' leave when ESC pressed
SYSTEM ' return to the OS
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 60
Threads: 11
Joined: Apr 2022
Reputation:
7
Terry to the rescue !!! Thank you Terry. This definitely works and I will try to integrate this into my program.
Posts: 1,277
Threads: 120
Joined: Apr 2022
Reputation:
100
(09-16-2024, 04:36 PM)dano Wrote: Terry to the rescue !!! Thank you Terry. This definitely works and I will try to integrate this into my program. You are most welcome. It seems _DEVICES is one of those overlooked commands that can poll the keyboard as well as game controllers. I was actually quite surprised that this worked without having to use the _WINDOWHASFOCUS statement in some way.
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 2,128
Threads: 218
Joined: Apr 2022
Reputation:
100
Change
Code: (Select All) IF _BUTTON(b) <> 0 THEN
to...
Code: (Select All) IF LEN(_BUTTON(b)) THEN
Why? Cuz I sez so, varmint!
I don't know, I've never played around with _BUTTON before, so I'm assuming it would work, just like LEN(INKEY$).
Other than that, I just wanted to +1 Terry for the code post. Very nice! Also, interesting topic about windows focus.
Pete
Fake News + Phony Politicians = Real Problems
Posts: 2,128
Threads: 218
Joined: Apr 2022
Reputation:
100
Well holy horny toads! What waz I thinkin'?
INKEY$ gets strings, _BUTTON gets values. Sending Dav my shipping address so he can send me my award!
Pete
Fake News + Phony Politicians = Real Problems
Posts: 1,277
Threads: 120
Joined: Apr 2022
Reputation:
100
I was playing around with seeing which keys are seen when focus is lost and regained. _KEYDOWN does see some of them, but the SHIFT keys are not.
Here's a quick hack of some code I made to investigate.
Code: (Select All) 'Quick hack
LOCATE 8, 2
PRINT "NOTE: _KEYDOWN only registers SHIFT keys and some of the other keyboard keys"
PRINT " _KEYDOWN will register multiple keys"
PRINT " A negative _KEYHIT value means the key was released"
DO
LOCATE 2, 2
IF _WINDOWHASFOCUS THEN
'IF focus = 0 THEN _KEYCLEAR
focus = -1
PRINT "WINDOW HAS FOCUS "
ELSE
focus = 0
PRINT "WINDOW DOES NOT HAVE FOCUS"
END IF
a$ = INKEY$
LOCATE 4, 2
PRINT "INKEY$ = "; a$
LOCATE 5, 2
PRINT "_KEYHIT = ";
k = _KEYHIT
IF k <> 0 THEN PRINT k; " "
LOCATE 6, 2
PRINT "_KEYDOWN = ";
IF _KEYDOWN(100304) AND _KEYDOWN(100303) THEN
PRINT "LEFT & RIGHT SHIFT"
ELSEIF _KEYDOWN(100304) THEN
PRINT "LEFT SHIFT "
ELSEIF _KEYDOWN(100303) THEN
PRINT "RIGHT SHIFT "
ELSE
FOR k = 33 TO 122
IF _KEYDOWN(k) THEN
PRINT CHR$(k); " "; ' print multiple keys
END IF
NEXT k
PRINT " "
END IF
_LIMIT 60
LOOP UNTIL _KEYDOWN(27)
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Posts: 723
Threads: 118
Joined: Apr 2022
Reputation:
106
Tried it with INP(&H60) too, seems to respond the same like _KEYKIT. Doesn't see SHIFT hold when the program is maximized, but sees the release.
- Dav
Posts: 2,128
Threads: 218
Joined: Apr 2022
Reputation:
100
A quick hack is better than a quack hick... Hey where is Steve, anyway?
PEEK / POKE won't help, either.
Def Seg = 0
i% = Peek(1047) Mod 16
If InStr(Chr$(1) + Chr$(2) + Chr$(5) + Chr$(6) + Chr$(9) + Chr$(10), Chr$(i%)) Then tx.shift = -1 Else tx.shift = 0
If tx.shift Then Print "Different Shift same results."
Def Seg
So it looks like unless someone can come up with a way for QB64 to poll the keyboard when the QB64 window is not active then anyone wanting this ability will need to write a Windows only routine using Win32 API keyboard functions. I had to do that for mouse routines when the program window was out of focus. It worked perfectly, but Linux and Mac users were not be able to use it.
Pete
Fake News + Phony Politicians = Real Problems
|