Code archives/User Input/Windows-style Keyboard Interface

This code has been declared by its author to be Public Domain code.

Download source code

Windows-style Keyboard Interface by octothorpe2002
If you want to see an example, copy the program below, then uncomment the short "example" program at the very bottom.

To use this in your program, Include() this library, and call at least one of the "register" routines, then call KEY_GetKey() just like you'd use Blitz's builtin GetKey().

Warning: if you don't call any of the "register" routines, KEY_GetKey() will never return a keystroke!

Differences from how Windows handles the keyboard:

1. If the user presses an unrecognized key while holding down a recognized one, the repeating effect will not be stopped. To fix this, register each unused key on the keyboard with an ASCII value of 0.

2. Windows allows you to release shift and continue repeating, but pressing shift will stop repeating. This function differs from Windows's behaviour in that it does not stop repeating if shift is pressed (or released, for that matter). Emulating this quirk would be easy, but I think it's stupid so I didn't.
Type KEY_Global
	Field scancode_to_ascii.KEY_info[255]
	Field repeat_initial_delay
	Field repeat_subsequent_delay
	Field repeat_timer
	Field depressed_key.KEY_info
End Type
Global KEY_Global.KEY_Global = New KEY_Global
KEY_Global\repeat_initial_delay     = 750
KEY_Global\repeat_subsequent_delay  = 75

Type KEY_info
	Field scancode
	Field ascii_plain     ; lowercase
	Field ascii_shift     ; uppercase
End Type

;--------------------------------------------------------
Function KEY_register_keyinfo(scancode, ascii_plain=0, ascii_shift=0)
;--------------------------------------------------------
	KEY_Global\scancode_to_ascii[scancode] = New KEY_info
	KEY_Global\scancode_to_ascii[scancode]\scancode    = scancode
	KEY_Global\scancode_to_ascii[scancode]\ascii_plain = ascii_plain
	KEY_Global\scancode_to_ascii[scancode]\ascii_shift = ascii_shift
End Function

;--------------------------------------------------------
Function KEY_register_printable_keys()
;--------------------------------------------------------
	KEY_register_keyinfo( 41,  96, 126)    ; ` and ~
	KEY_register_keyinfo(  2,  49,  33)    ; 1 and !
	KEY_register_keyinfo(  3,  50,  64)    ; 2 and @
	KEY_register_keyinfo(  4,  51,  35)    ; 3 and #
	KEY_register_keyinfo(  5,  52,  36)    ; 4 and $
	KEY_register_keyinfo(  6,  53,  37)    ; 5 and %
	KEY_register_keyinfo(  7,  54,  94)    ; 6 and ^
	KEY_register_keyinfo(  8,  55,  38)    ; 7 and &
	KEY_register_keyinfo(  9,  56,  42)    ; 8 and *
	KEY_register_keyinfo( 10,  57,  40)    ; 9 and (
	KEY_register_keyinfo( 11,  48,  41)    ; 0 and )
	KEY_register_keyinfo( 12,  45,  95)    ; - and _
	KEY_register_keyinfo( 13,  61,  43)    ; = and +
	KEY_register_keyinfo( 16, 113,  81)    ; q and Q
	KEY_register_keyinfo( 17, 119,  87)    ; w and W
	KEY_register_keyinfo( 18, 101,  69)    ; e and E
	KEY_register_keyinfo( 19, 114,  82)    ; r and R
	KEY_register_keyinfo( 20, 116,  84)    ; t and T
	KEY_register_keyinfo( 21, 121,  89)    ; y and Y
	KEY_register_keyinfo( 22, 117,  85)    ; u and U
	KEY_register_keyinfo( 23, 105,  73)    ; i and I
	KEY_register_keyinfo( 24, 111,  79)    ; o and O
	KEY_register_keyinfo( 25, 112,  80)    ; p and P
	KEY_register_keyinfo( 26,  91, 123)    ; [ and {
	KEY_register_keyinfo( 27,  93, 125)    ; ] and }
	KEY_register_keyinfo( 43,  92, 124)    ; \ and |
	KEY_register_keyinfo( 30,  97,  65)    ; a and A
	KEY_register_keyinfo( 31, 115,  83)    ; s and S
	KEY_register_keyinfo( 32, 100,  68)    ; d and D
	KEY_register_keyinfo( 33, 102,  70)    ; f and F
	KEY_register_keyinfo( 34, 103,  71)    ; g and G
	KEY_register_keyinfo( 35, 104,  72)    ; h and H
	KEY_register_keyinfo( 36, 106,  74)    ; j and J
	KEY_register_keyinfo( 37, 107,  75)    ; k and K
	KEY_register_keyinfo( 38, 108,  76)    ; l and L
	KEY_register_keyinfo( 39,  59,  58)    ; ; and :
	KEY_register_keyinfo( 40,  39,  34)    ; ' and "
	KEY_register_keyinfo( 44, 122,  90)    ; z and Z
	KEY_register_keyinfo( 45, 120,  88)    ; x and X
	KEY_register_keyinfo( 46,  99,  67)    ; c and C
	KEY_register_keyinfo( 47, 118,  86)    ; v and V
	KEY_register_keyinfo( 48,  98,  66)    ; b and B
	KEY_register_keyinfo( 49, 110,  78)    ; n and N
	KEY_register_keyinfo( 50, 109,  77)    ; m and M
	KEY_register_keyinfo( 51,  44,  60)    ; , and <
	KEY_register_keyinfo( 52,  46,  62)    ; . and >
	KEY_register_keyinfo( 53,  47,  63)    ; / and ?
	KEY_register_keyinfo( 15,   9,   9)    ; tab
	KEY_register_keyinfo( 57,  32,  32)    ; space
	KEY_register_keyinfo( 28,  13,  13)    ; enter
	KEY_register_keyinfo(181,  47,  47)    ; numpad /
	KEY_register_keyinfo( 55,  42,  42)    ; numpad *
	KEY_register_keyinfo( 74,  45,  45)    ; numpad -
	KEY_register_keyinfo( 78,  43,  43)    ; numpad +
	KEY_register_keyinfo(156,  13,  13)    ; numpad enter
	KEY_register_keyinfo( 79,  49,  49)    ; numpad 1
	KEY_register_keyinfo( 80,  50,  50)    ; numpad 2
	KEY_register_keyinfo( 81,  51,  51)    ; numpad 3
	KEY_register_keyinfo( 75,  52,  52)    ; numpad 4
	KEY_register_keyinfo( 76,  53,  53)    ; numpad 5
	KEY_register_keyinfo( 77,  54,  54)    ; numpad 6
	KEY_register_keyinfo( 71,  55,  55)    ; numpad 7
	KEY_register_keyinfo( 72,  56,  56)    ; numpad 8
	KEY_register_keyinfo( 73,  57,  57)    ; numpad 9
	KEY_register_keyinfo( 82,  48,  48)    ; numpad 0
	KEY_register_keyinfo( 83,  46,  46)    ; numpad .
End Function

;--------------------------------------------------------
Function KEY_register_manipulation_keys()
;--------------------------------------------------------
	KEY_register_keyinfo(199,  1,  1)     ; home
	KEY_register_keyinfo(207,  2,  2)     ; end
	KEY_register_keyinfo( 14,  8,  8)     ; backspace
	KEY_register_keyinfo(211,  4,  4)     ; delete
	KEY_register_keyinfo(203, 31, 31)     ; left
	KEY_register_keyinfo(205, 30, 30)     ; right
End Function

;--------------------------------------------------------
Function KEY_GetKey()
;--------------------------------------------------------

	Local trigger_keystroke = False

	; is the user still pressing the previous key?
	If KEY_Global\depressed_key <> Null Then
		If KeyDown(KEY_Global\depressed_key\scancode) Then
			; user is still pressing the key, so generate repeating keystrokes
			If KEY_Global\repeat_timer < MilliSecs() Then
				KEY_Global\repeat_timer = MilliSecs() + KEY_Global\repeat_subsequent_delay
				trigger_keystroke = True
			EndIf
		Else
			; user has stopped pressing the key
			KEY_Global\depressed_key = Null
		EndIf
	EndIf

	; has the user pressed a new key? (check the key positions for each recognized scancode)
	For key.KEY_info = Each KEY_info
		If KeyHit(key\scancode) Then Exit
	Next
	; if we found a recognized key, remember it's being pressed, and return it
	If key <> Null Then
		KEY_Global\depressed_key = key
		KEY_Global\repeat_timer = MilliSecs() + KEY_Global\repeat_initial_delay
		trigger_keystroke = True
	EndIf

	If trigger_keystroke Then
		; the ascii code we want to return often depends on if shift is being pressed
		If KeyDown(42) Or KeyDown(54) Then
			Return KEY_Global\depressed_key\ascii_shift
		Else
			Return KEY_Global\depressed_key\ascii_plain
		EndIf
	EndIf

	Return 0
End Function


;--------------------------------------------------------
; EXAMPLE
;--------------------------------------------------------
;
;SetBuffer = BackBuffer()
;
;KEY_register_printable_keys()
;
;input_string$ = ""
;While Not KeyHit(1)
;	char = KEY_GetKey()
;	If char > 0 Then input_string$ = input_string$ + Chr$(char)
;
;	Cls
;	Locate 1, 1
;	Print "Press and hold keys to see repeating effect"
;	Print input_string$ + cursor$
;	Flip
;Wend

Comments

mulawa12004
Superb piece of work - worked perfectly for me!

Busily writing an interactive character-by-character peer-to-peer chat program and this was just what I needed - able to plug it straight in!

Many thanks.


Code Archives Forum