For a long time now, I realized that there were a few keys which mapped wrongly with _KEYHIT, but they were never really much of an issue in my code, so I didn't bother to dig extensively into them. A few times, I've dug into the qb64 source in libqb.cpp to try and see if I could sort out what was wrong with a few of them (CTRL-TAB is generally the one which affects me the most, as I use it for a reverse tab process normally.), but I've never been able to decipher exactly what the heck is going on in there to correct things.
So, now I'm working on a new project (or at least trying to, though it seems I have to keep rebuilding basic development tools before I can actually go anywhere with it like I want), and once again, I need some of those "lost" or "misplaced" keys. This morning, I sorted out how to get the values of every key with GetAsyncKeyState (you can look at it here:
https://www.qb64.org/forum/index.php?topic=2030.0), but it returns values and codes which I'm not that used to using. Normally I use _KEYHIT and _KEYDOWN for my programs, and I
really don't want to have to swap everything over to the virtual key codes...
So, I sat down and started to write a patch to fix and fill in those missing codes in _KEYHIT for me. The work is definitely a work-in-progress, as I'm still finding and patching issues, but I wanted to go ahead and share what I've came up with so far.
DECLARE LIBRARY 'function is already used by QB64 so "User32" is not required
k = Keyhit(oldkeyhit&)
DIM RepeatRate
AS _FLOAT: RepeatRate
= 0.2 'necessary so we don't spam key returns with GetAsyncKeyState
'Fix for number 5 on the num pad, when numlock is active
IF GetAsyncKeyState
(12) THEN 'pause key, which has no value (and probably still won't, as QB64 uses it as a command code for pausing program execution 'and gives a false result on a keyup
IF ExtendedTimer
> Num5Delay
THEN k
= 19456: Num5Down
= -1: Num5Delay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0 IF Num5Down
THEN k
= -19456: Num5Down
= 0
'Fix for Pause Key
IF GetAsyncKeyState
(19) THEN 'pause key, which has no value (and probably still won't, as QB64 uses it as a command code for pausing program execution 'and gives a false result on a keyup
IF ExtendedTimer
> PauseDelay
THEN k
= 100019: PauseDown
= -1: PauseDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0
'Fix for the Menu Key
IF GetAsyncKeyState
(93) THEN 'menu key, which doesn't work at all on keydown 'and gives a false result on a keyup
IF ExtendedTimer
> MenuDelay
THEN k
= 100319: MenuDown
= -1: MenuDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0
'Fix for SYS Key
IF GetAsyncKeyState
(44) THEN 'SYS key, which currently thinks it's a comma 'and gives a false result on a keyup
IF ExtendedTimer
> SysDelay
THEN k
= 100316: SysDown
= -1: SysDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0 'Fix for NUM LOCK Key
IF GetAsyncKeyState
(144) THEN 'num lock key, which currently toggles itself with the down value 'changing from a up code to a down code, depending on numlock status
'and gives a false result on keyup
IF ExtendedTimer
> NumDelay
THEN k
= 100300: NumDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0
'FIX for SCROLL LOCK Key
IF GetAsyncKeyState
(145) THEN 'scroll lock key, which has no down value 'and gives a false result on keyup
IF ExtendedTimer
> ScrollDelay
THEN k
= 100302: ScrollDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0
'Fix for CTRL-Tab
IF GetAsyncKeyState
(9) THEN 'ctrl-tab; return tab, not CTRL-I IF ExtendedTimer
> TabDelay
THEN k
= 9: TabDown
= -1: TabDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0 'Fix for CTRL-Backspace
IF GetAsyncKeyState
(8) THEN 'ctrl-backspace; return backspace, not CTRL-Delete IF ExtendedTimer
> BackspaceDelay
THEN k
= 8: BackspaceDown
= -1: BackspaceDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0 'Fix for CTRL-J
IF GetAsyncKeyState
(74) THEN 'CTRL-J; return ctrl-j, not ctrl-return IF ExtendedTimer
> JDelay
THEN k
= 106: JDown
= -1: JDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0
'Fix for CTRL-Tilde, CTRL-Backquote
IF GetAsyncKeyState
(192) THEN 'ctrl-tilde, ctrl-backquote -- neither are supported IF ExtendedTimer
> TildeDelay
THEN k
= 126: TildeDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0 IF ExtendedTimer
> BackQuoteDelay
THEN k
= 96: BackQuoteDelay
= ExtendedTimer
+ RepeatRate
ELSE k
= 0 'Fix for CTRL-0 to CTRL-9
IF GetAsyncKeyState
(i
+ 48) THEN 'ctrl-0 to ctrl-9 IF ExtendedTimer
> NumDelay
(i
) THEN SELECT CASE i
'WTF are these key codes all over the damn place?? NumDelay(i) = ExtendedTimer + RepeatRate
IF ExtendedTimer
> NumDelay
(i
) THEN k
= 48 + i: NumDelay
(i
) = ExtendedTimer
+ RepeatRate
ELSE k
= 0
'Key up releases for the keys which we've been remapping
CASE 0 'We didn't read a keypress at all IF PauseDown
THEN k
= -100019: PauseDown
= 0 CASE 13: JDown
= 0 'Enter was hit, not CTRL-J CASE 93: MenuDown
= 0 '] was hit after menu CASE 105: TabDown
= 0 'CTRL-I was hit, rather than CTRL-Tab CASE 21248: BackspaceDown
= 0 'Delete was hit, rather than CTRL-Backspace CASE -13 '-13 is the release code for both ENTER and CTRL-J IF JDown
THEN k
= -106: MenuDown
= 0 CASE -16, -17, -18 'shift release, ctrl release, alt release k = 0 'no need to report these as release codes, if we don't report them as down codes.
'Instead, we report these as LEFT/RIGHT shift, ctrl, alt key releases and not just a generic "SHIFT WAS RELEASED" code.
CASE -44 '-44 is the release code for both SYS and comma IF SysDown
THEN k
= -100316: SysDown
= 0 CASE -48 TO -57 '0 to 9 shares the same release codes, regardless of if shift is pressed CASE -48: k
= -41 'it's ), not 0 CASE -49: k
= -33 '!, not 1 CASE -50: k
= -64 '@, not 2 CASE -51: k
= -35 '#, not 3 CASE -52: k
= -36 '$, not 4 CASE -53: k
= -37 '%, not 5 CASE -54: k
= -94 '^, not 6 CASE -55: k
= -38 '&, not 7 CASE -56: k
= -42 '*, not 8 CASE -57: k
= -40 '(, not 9 CASE -93 '-93 is the release code for both MENU and ] IF MenuDown
THEN k
= -100319: MenuDown
= 0 CASE -105 '-105 is the release code for both CTRL-TAB and CTRL-I IF TabDown
THEN k
= -9: TabDown
= 0 CASE -106 '-106 is the release code for both CTRL-J and ENTER IF JDown
THEN k
= -106: TabDown
= 0 CASE -144: k
= -100300 'Num lock key currently returns virtual code release values/ CASE -145: k
= -100302 'Scroll lock key currently returns virtual code release values CASE -192 'CTRL-` and CTRL-~ both map to this key, but only up a key up event k = -126
k = -96
CASE -21248 '-21248 is the release code for both CTRL-Backspace and Delete IF BackspaceDown
THEN k
= -8: BackspaceDown
= 0 Keyhit = k
'modified extendedtimer to store the old day's count, and not have to recalculate it every time the routine is called.
IF olds
= 0 THEN 'calculate the day the first time the extended timer runs SELECT CASE m
'Add the number of days for each previous month passed IF (y
MOD 4) = 2 AND m
> 2 THEN d
= d
+ 1 'add a day if this is leap year and we're past february d = (d - 1) + 365 * y 'current month days passed + 365 days per each standard year
d = d + (y + 2) \ 4 'add in days for leap years passed
s = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
old_day = s
IF TIMER < oldt
THEN 'we went from 23:59:59 (a second before midnight) to 0:0:0 (midnight) old_day = s + 83400 'add another worth of seconds to our counter
olds = old_day + oldt
ExtendedTimer## = olds
The list of issues which I've found so far boggles my mind! I thought this was just a
small issue, limited to a very few number of select keys which was affected. From what I've actually discovered, I'm now wondering why the heck _KEYHIT and _KEYDOWN are used by
anyone!! Things are broken BAD, and I had no idea...
The Menu key is completely broken.
CTRL-Tab reports itself as CTRL-I.
CTRL-Backspace reports itself as Delete.
CTRL-Tilde and CTRL-Backquote aren't supported at all.
CTRL- 0 to CTRL-9 have no keydown codes, only keyup codes.
CTRL-) to CTRL-( have no codes whatsoever. They just report themselves as CTRL-0 to CTRL-9 codes.
And that's only the glitches which I've sorted out this afternoon, while playing around with the values. Some of these return no values whatsoever, others return values which are completely unfathomable (CTRL-@ returns a value of 200000, or so.), and others return duplicate values on things...
Try the program above and test it out with some of the CTRL-key presses as mentioned in the comments in the code, and you can see the differences for yourself. Who knew the command was broken so badly?!!
If anyone finds code combinations which don't work as they should, kindly report them to me and I'll add them to this little routine for now, so it can be used as a patch until someone can actually sort out what the heck is so wrong with QB64 itself. :)
EDIT: Code assembled into Library format and attached to the bottom of this post.
Just $INCLUDE the file below, at the bottom of your desired QB64 program, and then make use of
Keyhit instead of
_KEYHIT. Only works for Windows. Linux/Mac users will need to find a different way to patch the incorrect return values, if they need to.