Key trap?

General FreeBASIC programming questions.
Post Reply
Achaean
Posts: 51
Joined: Aug 02, 2017 12:54

Key trap?

Post by Achaean »

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.
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: Key trap?

Post by bcohio2001 »

Look at Multikey
lizard
Posts: 440
Joined: Oct 17, 2017 11:35
Location: Germany

Re: Key trap?

Post by lizard »

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
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Key trap?

Post by dodicat »

For the required multikey combination:

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 
And for Lizard's requirment:

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 
Achaean
Posts: 51
Joined: Aug 02, 2017 12:54

Re: Key trap?

Post by Achaean »

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:

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
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:

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
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? :-)
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Key trap?

Post by dodicat »

Instead of sleep 1000 you could try

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
Or you could have a dedicated key sub to call your time (in a sub) via threadcall

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 
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Key trap?

Post by Tourist Trap »

D.J.Peters GETKEY may also help. It helped me many times.
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
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Key trap?

Post by fxm »

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.
This behavior is well commented in the documentation.
Achaean
Posts: 51
Joined: Aug 02, 2017 12:54

Re: Key trap?

Post by Achaean »

MANY THANKS guys!!! :-)
I'll look at them.
Post Reply