Key trap?
Key trap?
Hi! :-)
Is there any way in FB, to trap a specific keyboard key (or key combination), that way so pressing this key, to trigger a specific action?
Eg. pressing ^c breaks the program and exits. Exactly this way is it possible pressing a key (or a combination) to do a specific action (exiting, or going to a subroutine, or beeping, or presenting a menu etc.)?
I think the good old days, it was possible with ONKEY (I think) or setting an interrupt.
TIA! :-)
A.
Is there any way in FB, to trap a specific keyboard key (or key combination), that way so pressing this key, to trigger a specific action?
Eg. pressing ^c breaks the program and exits. Exactly this way is it possible pressing a key (or a combination) to do a specific action (exiting, or going to a subroutine, or beeping, or presenting a menu etc.)?
I think the good old days, it was possible with ONKEY (I think) or setting an interrupt.
TIA! :-)
A.
-
- Posts: 556
- Joined: Mar 10, 2007 15:44
- Location: Ohio, USA
- Contact:
Re: Key trap?
Look at Multikey
Re: Key trap?
Achaean wrote: Is there any way in FB, to trap a specific keyboard key (or key combination), that way so pressing this key, to trigger a specific action?
Code: Select all
#include "fbgfx.bi"
using fb
do
? "What a good question! ";
if multikey(SC_ALT) and multikey(SC_F4) then end
loop until multikey(SC_ESCAPE) ' until esc pressed
Re: Key trap?
For the required multikey combination:
And for Lizard's requirment:
Code: Select all
Print "<Esc> to exit othewise test the keyboard"
Print
function ret(n as long) as string
dim as string s
select case n
case &h01: s= "SC_ESCAPE "' = ' &h01
case &h02: s= "SC_1 "' = ' &h02
case &h03: s= "SC_2 "' = ' &h03
case &h04: s= "SC_3 "' = ' &h04
case &h05: s= "SC_4 "' = ' &h05
case &h06: s= "SC_5 "' = ' &h06
case &h07: s= "SC_6 "' = ' &h07
case &h08: s= "SC_7 "' = ' &h08
case &h09: s= "SC_8 "' = ' &h09
case &h0A: s= "SC_9 "' = ' &h0A
case &h0B: s= "SC_0 "' = ' &h0B
case &h0C: s= "SC_MINUS "' = ' &h0C
case &h0D: s= "SC_EQUALS "' = ' &h0D
case &h0E: s= "SC_BACKSPACE "' = ' &h0E
case &h0F: s= "SC_TAB "' = ' &h0F
case &h10: s= "SC_Q "' = ' &h10
case &h11: s= "SC_W "' = ' &h11
case &h12: s= "SC_E "' = ' &h12
case &h13: s= "SC_R "' = ' &h13
case &h14: s= "SC_T "' = ' &h14
case &h15: s= "SC_Y "' = ' &h15
case &h16: s= "SC_U "' = ' &h16
case &h17: s= "SC_I "' = ' &h17
case &h18: s= "SC_O "' = ' &h18
case &h19: s= "SC_P "' = ' &h19
case &h1A: s= "SC_LEFTBRACKET "' = ' &h1A
case &h1B: s= "SC_RIGHTBRACKET "' = ' &h1B
case &h1C: s= "SC_ENTER "' = ' &h1C
case &h1D: s= "SC_CONTROL "' = ' &h1D
case &h1E: s= "SC_A "' = ' &h1E
case &h1F: s= "SC_S "' = ' &h1F
case &h20: s= "SC_D "' = ' &h20
case &h21: s= "SC_F "' = ' &h21
case &h22: s= "SC_G "' = ' &h22
case &h23: s= "SC_H "' = ' &h23
case &h24: s= "SC_J "' = ' &h24
case &h25: s= "SC_K "' = ' &h25
case &h26: s= "SC_L "' = ' &h26
case &h27: s= "SC_SEMICOLON "' = ' &h27
case &h28: s= "SC_QUOTE "' = ' &h28
case &h29: s= "SC_TILDE "' = ' &h29
case &h2A: s= "SC_LSHIFT "' = ' &h2A
case &h2B: s= "SC_BACKSLASH "' = ' &h2B
case &h2C: s= "SC_Z "' = ' &h2C
case &h2D: s= "SC_X "' = ' &h2D
case &h2E: s= "SC_C "' = ' &h2E
case &h2F: s= "SC_V "' = ' &h2F
case &h30: s= "SC_B "' = ' &h30
case &h31: s= "SC_N "' = ' &h31
case &h32: s= "SC_M "' = ' &h32
case &h33: s= "SC_COMMA "' = ' &h33
case &h34: s= "SC_PERIOD "' = ' &h34
case &h35: s= "SC_SLASH "' = ' &h35
case &h36: s= "SC_RSHIFT "' = ' &h36
case &h37: s= "SC_MULTIPLY "' = ' &h37
case &h38: s= "SC_ALT "' = ' &h38
case &h39: s= "SC_SPACE "' = ' &h39
case &h3A: s= "SC_CAPSLOCK "' = ' &h3A
case &h3B: s= "SC_F1 "' = ' &h3B
case &h3C: s= "SC_F2 "' = ' &h3C
case &h3D: s= "SC_F3 "' = ' &h3D
case &h3E: s= "SC_F4 "' = ' &h3E
case &h3F: s= "SC_F5 "' = ' &h3F
case &h40: s= "SC_F6 "' = ' &h40
case &h41: s= "SC_F7 "' = ' &h41
case &h42: s= "SC_F8 "' = ' &h42
case &h43: s= "SC_F9 "' = ' &h43
case &h44: s= "SC_F10 "' = ' &h44
case &h45: s= "SC_NUMLOCK "' = ' &h45
case &h46: s= "SC_SCROLLLOCK "' = ' &h46
case &h47: s= "SC_HOME "' = ' &h47
case &h48: s= "SC_UP "' = ' &h48
case &h49: s= "SC_PAGEUP "' = ' &h49
case &h4B: s= "SC_LEFT "' = ' &h4B
case &h4D: s= "SC_RIGHT "' = ' &h4D
case &h4E: s= "SC_PLUS "' = ' &h4E
case &h4F: s= "SC_END "' = ' &h4F
case &h50: s= "SC_DOWN "' = ' &h50
case &h51: s= "SC_PAGEDOWN "' = ' &h51
case &h52: s= "SC_INSERT "' = ' &h52
case &h53: s= "SC_DELETE "' = ' &h53
case &h57: s= "SC_F11 "' = ' &h57
case &h58: s= "SC_F12 "' = ' &h58
'' Extra case &h: s= "SCancodes not compatible with DOS case &h: s= "SCancodes
case &h: s= "SC_LWIN "' = ' &h7D
case &h: s= "SC_RWIN "' = ' &h7E
case &h: s= "SC_MENU "' = ' &h7F
end select
return s
end function
'This bit by fxm (I think)
Do
Dim K As Integer
For I As Integer = 0 To 127
If Multikey(I) Then
If K = 0 Then
K = 1
Else
Print " And ";
End If
Print ret(i);
If I = 1 Then
Exit Do
End If
End If
Next I
If K = 1 Then
Print
K = 0
End If
Sleep 25
Loop
While Inkey <> ""
Wend
Print
Print
Print "Any key to exit."
Sleep
Code: Select all
#include "fbgfx.bi"
using fb
do
if MultiKey( SC_LSHIFT ) and MultiKey( SC_RSHIFT) and MultiKey( SC_F4) then end
' is the requirment for
'if (up arrow) and (F4) then end
? "What a good question! ";
loop until multikey(SC_ESCAPE) ' until esc pressed
Re: Key trap?
THANKS A LOT guys!!! :-)
That's what I thought, looking at the Wiki.
Seems that Multikey is the closer command to achieve the key mapping.
1) However, the main downside (at my personal opinion), is that Multikey doesn't seems to do a "global" key press check, since it can be implemented inside a flow control statement (If-Then, Do-Loop, Case).
It would be nice to have a command for "global" key trap routine, so that the mapped key can behave similar to ^C (not depending at flow control routines).
Seems like a feature request to me! :-)
2) To the point now.
I wrote a small timer. Just an infinite loop that displays the time passed. I used Locate and Print Using for formatting the output, although it could be simpler avoiding these and using a CLS instead.
I wrote it at Linux, but it doesn't use any OS specific code, so I suppose that it runs as is, at Windows too.
Anyway, this is the code:
If you want to test it, just replace SLEEP 1000,1 to something like SLEEP 10 (for fast forwarding the time).
Obviously, the way to exit, is pressing ^C.
Nothing wrong with that, but for testing the Multikey command, I tried editing it, that way so pressing the ESC key, will exit the program (instead of using ^C).
So, that what I thought it could be done:
Actually, I just added an If Multikey command, to the seconds counter.
Well...mixed results! :-)
Sometimes, pressing ESC -> the program exits to bash. Success! :-)
At least partially. Some other times, the counter stops but the program doesn't exit, just hangs and I have to press 4-5 ^C, in order to exit to bash.
Another minor downside, is that Multikey doesn't seems to clear the keyboard buffer and if you accidentally press ESC twice or more, the program exits and passes the keyb buffer to bash.
Opinions?
What I'm doing wrong? :-)
That's what I thought, looking at the Wiki.
Seems that Multikey is the closer command to achieve the key mapping.
1) However, the main downside (at my personal opinion), is that Multikey doesn't seems to do a "global" key press check, since it can be implemented inside a flow control statement (If-Then, Do-Loop, Case).
It would be nice to have a command for "global" key trap routine, so that the mapped key can behave similar to ^C (not depending at flow control routines).
Seems like a feature request to me! :-)
2) To the point now.
I wrote a small timer. Just an infinite loop that displays the time passed. I used Locate and Print Using for formatting the output, although it could be simpler avoiding these and using a CLS instead.
I wrote it at Linux, but it doesn't use any OS specific code, so I suppose that it runs as is, at Windows too.
Anyway, this is the code:
Code: Select all
DIM AS UBYTE SEC,MIN,HOU
DIM AS INTEGER X
PRINT
X=CSRLIN
DO
DO
DO
LOCATE X
PRINT USING "Hrs: ##";HOU;SPC(1);
PRINT USING "Min: ##";MIN;SPC(1);
PRINT USING "Sec: ##";SEC
SLEEP 1000,1
SEC=SEC+1
LOOP WHILE SEC<60
MIN=MIN+1
SEC=0
LOOP WHILE MIN<60
HOU=HOU+1
MIN=0
SEC=0
LOOP
Obviously, the way to exit, is pressing ^C.
Nothing wrong with that, but for testing the Multikey command, I tried editing it, that way so pressing the ESC key, will exit the program (instead of using ^C).
So, that what I thought it could be done:
Code: Select all
#include "fbgfx.bi"
#if __FB_LANG__ = "fb"
Using FB
#endif
DIM AS UBYTE SEC,MIN,HOU
DIM AS INTEGER X
PRINT
X=CSRLIN
DO
DO
DO
LOCATE X
PRINT USING "Hrs: ##";HOU;SPC(1);
PRINT USING "Min: ##";MIN;SPC(1);
PRINT USING "Sec: ##";SEC
SLEEP 1000,1
SEC=SEC+1
IF MULTIKEY(SC_ESCAPE)=-1 THEN END
LOOP WHILE SEC<60
MIN=MIN+1
SEC=0
LOOP WHILE MIN<60
HOU=HOU+1
MIN=0
SEC=0
LOOP
Well...mixed results! :-)
Sometimes, pressing ESC -> the program exits to bash. Success! :-)
At least partially. Some other times, the counter stops but the program doesn't exit, just hangs and I have to press 4-5 ^C, in order to exit to bash.
Another minor downside, is that Multikey doesn't seems to clear the keyboard buffer and if you accidentally press ESC twice or more, the program exits and passes the keyb buffer to bash.
Opinions?
What I'm doing wrong? :-)
Re: Key trap?
Instead of sleep 1000 you could try
Or you could have a dedicated key sub to call your time (in a sub) via threadcall
Code: Select all
#include "fbgfx.bi"
using fb
locate ,0
dim as double t
DIM AS UBYTE SEC,MIN,HOU
DIM AS INTEGER X
PRINT
X=CSRLIN
DO
DO
DO
LOCATE X,0,0
PRINT USING "Hrs: ##";HOU;SPC(1);
PRINT USING "Min: ##";MIN;SPC(1);
PRINT USING "Sec: ##";SEC
SLEEP 1,1
if timer-t>1 then t=timer :SEC=SEC+1
'SEC=SEC+1
'exit and clear the keyboard
IF MULTIKEY(SC_ESCAPE)=-1 THEN while inkey<>"":wend: print len(inkey):Print "Press a key to end":sleep: END
LOOP WHILE SEC<60
MIN=MIN+1
SEC=0
LOOP WHILE MIN<60
HOU=HOU+1
MIN=0
SEC=0
LOOP
Code: Select all
#include "fbgfx.bi"
#if __FB_LANG__ = "fb"
Using FB
#endif
sub showtime()
DIM AS UBYTE SEC,MIN,HOU
DIM AS INTEGER X
PRINT
X=CSRLIN
DO
DO
DO
LOCATE X
PRINT USING "Hrs: ##";HOU;SPC(1);
PRINT USING "Min: ##";MIN;SPC(1);
PRINT USING "Sec: ##";SEC
SLEEP 1000,1
SEC=SEC+1
'IF MULTIKEY(SC_ESCAPE)=-1 THEN END
LOOP WHILE SEC<60
MIN=MIN+1
SEC=0
LOOP WHILE MIN<60
HOU=HOU+1
MIN=0
SEC=0
LOOP
end sub
Sub keysub
threadcall showtime()
dim as string e
Do
e=inkey
if e=chr(27) then exit sub
sleep 1
Loop
End Sub
keysub
print inkey,len(inkey)
print "Press a key to end"
sleep
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Key trap?
D.J.Peters GETKEY may also help. It helped me many times.
https://freebasic.net/forum/viewtopic.p ... %2A#p16566
https://freebasic.net/forum/viewtopic.p ... %2A#p16566
Code: Select all
enum KEYCODES
K_NONE = 0
CTRL_A = 1
CTRL_B = 2
CTRL_C = 3
CTRL_D = 4
CTRL_E = 5
CTRL_F = 6
K_BELL = 7
K_BACKSPACE = 8
K_TAB = 9
CTRL_J = 10
CTRL_K = 11
CTRL_L = 12
K_ENTER = 13
CTRL_N = 14
CTRL_O = 15
CTRL_P = 16
CTRL_Q = 17
CTRL_R = 18
CTRL_S = 19
CTRL_T = 20
CTRL_U = 21
CTRL_V = 22
CTRL_W = 23
CTRL_X = 24
CTRL_Y = 25
CTRL_Z = 26
K_ESCAPE = 27
CTRL_5 = 29
CTRL_6 = 30
CTRL_7 = 31
K_SPACE = 32
K_EXCLATIONMARK = 33 ' !
K_QUOTE = 34 ' "
K_HASH = 35 ' #
K_DOLLAR = 36 ' $
K_PERCENT = 37 ' %
K_AMPERSAND = 38 ' &
K_SINGLEQUOTE = 39 ' '
K_LEFTBRACKET = 40 ' (
K_RIGHTBRACKET = 41 ' )
K_MULTIPLY = 42 ' *
K_PLUS = 43 ' +
K_COMMA = 44 ' ,
K_MINUS = 45 ' -
K_PERIOD = 46 ' .
K_SLASH = 47 ' /
K_0 = 48
K_1 = 49
K_2 = 50
K_3 = 51
K_4 = 52
K_5 = 53
K_6 = 54
K_7 = 55
K_8 = 56
K_9 = 57
K_COLON = 58 ' :
K_SEMICOLON = 59 ' ;
K_LESS = 60 ' <
K_EQUALS = 61 ' =
K_GREATER = 62 ' >
SHIFT_QUESTIONMARK = 63 ' ?
AltGr_Q = 64 ' @
SHIFT_A = 65
SHIFT_B = 66
SHIFT_C = 67
SHIFT_D = 68
SHIFT_E = 69
SHIFT_F = 70
SHIFT_G = 71
SHIFT_H = 72
SHIFT_I = 73
SHIFT_J = 74
SHIFT_K = 75
SHIFT_L = 76
SHIFT_M = 77
SHIFT_N = 78
SHIFT_O = 79
SHIFT_P = 80
SHIFT_Q = 81
SHIFT_R = 82
SHIFT_S = 83
SHIFT_T = 84
SHIFT_U = 85
SHIFT_V = 86
SHIFT_W = 87
SHIFT_X = 88
SHIFT_Y = 89
SHIFT_Z = 90
K_L_SQUAREBRACKET = 91 ' [
K_Backslash = 92 ' \
K_R_SQUAREBRACKET = 93 ' ]
K_CARET = 94 ' ^
K_UNDERSCORE = 95 ' _
K_A = 97
K_B = 98
K_C = 99
K_D = 100
K_E = 101
K_F = 102
K_G = 103
K_H = 104
K_I = 105
K_J = 106
K_K = 107
K_L = 108
K_M = 109
K_N = 110
K_O = 111
K_P = 112
K_Q = 113
K_R = 114
K_S = 115
K_T = 116
K_U = 117
K_V = 118
K_W = 119
K_X = 120
K_Y = 121
K_Z = 122
K_L_CURLYBRACKET = 123 ' {
K_R_CURLYBRACKET = 125 ' }
K_TILDE = 126 ' ~
ALTGR_C = 162 ' ¢
ALTGR_E = 164 ' (€)
ALTGR_Y = 171 ' «
ALTGR_6 = 172
ALTGR_2 = 178 ' ²
ALTGR_3 = 179 ' ³
ALTGR_M = 181 ' µ
ALTGR_R = 182
ALTGR_DOT = 183 ' ·
ALTGR_1 = 185 ' ¹
ALTGR_X = 187 ' »
SHIFT_AE = 196 ' Ä
SHIFT_OE = 214 ' Ö
SHIFT_UE = 220 ' Ü
K_SS = 223 ' ß
K_AE = 228 ' ä
ALTGR_A = 230 ' æ
ALTGR_D = 240 ' ð
K_OE = 246 ' ö
ALTGR_O = 248 ' ø
K_UE = 252 ' ü
ALTGR_P = 254 ' þ
K_F1 = 315
K_F2 = 316
K_F3 = 317
K_F4 = 318
K_F5 = 319
K_F6 = 320
K_F7 = 321
K_F8 = 322
K_F9 = 323
K_F10 = 324
K_HOME = 327
K_UP = 328
K_PAGEUP = 329
K_LEFT = 331
K_RIGHT = 333
K_END = 335
K_DOWN = 336
K_PAGEDOWN = 337
K_INSERT = 338
K_DELETE = 339
K_CLOSEWINDOW = 363
end enum
#if __FB_LANG__ = "fb"
' I like VAR :-)
function GetKeyCode() as KEYCODES
var code = K_NONE, key = inkey(), chars = len(key)
if chars then chars-=1 : code = key[chars] or (chars shl 8)
return code
end function
#else
function GetKeyCode() as KEYCODES
dim as KEYCODES code = K_NONE
dim as string key = inkey()
dim as integer chars = len(key)
if chars then
code = asc(right(key,1)) : if chars>1 then code += 256
end if
return code
end function
#endif
'
' main
'
screenres 640,480
dim as KEYCODES key
while key<>K_ESCAPE andalso key<>K_CLOSEWINDOW
key =GetKeyCode()
if key<>K_NONE then locate 1,1 : print "last keycode: " & key & " "
sleep 10
wend
Re: Key trap?
This behavior is well commented in the documentation.Achaean wrote:Another minor downside, is that Multikey doesn't seems to clear the keyboard buffer and if you accidentally press ESC twice or more, the program exits and passes the keyb buffer to bash.
Re: Key trap?
MANY THANKS guys!!! :-)
I'll look at them.
I'll look at them.