The KeyBoard unit implements a keyboard access layer which is system independent. It can be used to poll the keyboard state and wait for certain events. Waiting for a keyboard event can be done with the GetKeyEvent function, which will return a driver-dependent key event. This key event can be translated to a interpretable event by the TranslateKeyEvent function. The result of this function can be used in the other event examining functions.
A custom keyboard driver can be installed using the SetKeyboardDriver function. The current keyboard driver can be retrieved using the GetKeyboardDriver function. The last section of this chapter demonstrates how to make a keyboard driver.
The following constants define some error constants, which may be returned by the keyboard functions.
errKbdBase = 1010; errKbdInitError = errKbdBase + 0; errKbdNotImplemented = errKbdBase + 1;The following constants denote special keyboard keys. The first constants denote the function keys:
const kbdF1 = $FF01; kbdF2 = $FF02; kbdF3 = $FF03; kbdF4 = $FF04; kbdF5 = $FF05; kbdF6 = $FF06; kbdF7 = $FF07; kbdF8 = $FF08; kbdF9 = $FF09; kbdF10 = $FF0A; kbdF11 = $FF0B; kbdF12 = $FF0C; kbdF13 = $FF0D; kbdF14 = $FF0E; kbdF15 = $FF0F; kbdF16 = $FF10; kbdF17 = $FF11; kbdF18 = $FF12; kbdF19 = $FF13; kbdF20 = $FF14;Constants $15 till $1F are reserved for future function keys. The following constants denote the cursor movement keys:
kbdHome = $FF20; kbdUp = $FF21; kbdPgUp = $FF22; kbdLeft = $FF23; kbdMiddle = $FF24; kbdRight = $FF25; kbdEnd = $FF26; kbdDown = $FF27; kbdPgDn = $FF28; kbdInsert = $FF29; kbdDelete = $FF2A;Constants $2B till $2F are reserved for future keypad keys. The following flags are also defined:
kbASCII = $00; kbUniCode = $01; kbFnKey = $02; kbPhys = $03; kbReleased = $04;They can be used to check what kind of data a key event contains. The following shift-state flags can be used to determine the shift state of a key (i.e. which of the SHIFT, ALT and CTRL keys were pressed simultaneously with a key):
kbLeftShift = 1; kbRightShift = 2; kbShift = kbLeftShift or kbRightShift; kbCtrl = 4; kbAlt = 8;The following constant strings are used in the key name functions FunctionKeyName and KeyEventToString:
SShift : Array [1..3] of string[5] = ('SHIFT','CTRL','ALT'); LeftRight : Array [1..2] of string[5] = ('LEFT','RIGHT'); UnicodeChar : String = 'Unicode character '; SScanCode : String = 'Key with scancode '; SUnknownFunctionKey : String = 'Unknown function key : '; SAnd : String = 'AND'; SKeyPad : Array [0..($FF2F-kbdHome)] of string[6] = ('Home','Up','PgUp','Left', 'Middle','Right','End','Down', 'PgDn','Insert','Delete','', '','','','');They can be changed to localize the key names when needed.
TKeyEvent = Longint;The key stroke is encoded in the 4 bytes of the TKeyEvent type. The various fields of the key stroke encoding can be obtained by typecasting the TKeyEvent type to the TKeyRecord type:
TKeyRecord = packed record KeyCode : Word; ShiftState, Flags : Byte; end;The structure of a TKeyRecord structure is explained in table (keyevent) .
Field | Meaning |
KeyCode | Depending on flags either the physical representation of a key (under DOS scancode, ascii code pair), or the translated ASCII/unicode character. |
ShiftState | Shift-state when this key was pressed (or shortly after) |
Flags | Determine how to interpret KeyCode |
If there are two keys returning the same char-code, there's no way to find out which one was pressed (Gray+ and Simple+). If it needs to be known which was pressed, the untranslated keycodes must be used, but these are system dependent. System dependent constants may be defined to cover those, with possibily having the same name (but different value).
The TKeyboardDriver record can be used to install a custom keyboard driver with the SetKeyboardDriver function:
Type TKeyboardDriver = Record InitDriver : Procedure; DoneDriver : Procedure; GetKeyEvent : Function : TKeyEvent; PollKeyEvent : Function : TKeyEvent; GetShiftState : Function : Byte; TranslateKeyEvent : Function (KeyEvent: TKeyEvent): TKeyEvent; TranslateKeyEventUniCode: Function (KeyEvent: TKeyEvent): TKeyEvent; end;The various fields correspond to the different functions of the keyboard unit interface. For more information about this record see section kbddriver
This will cause the keyboard driver to clear up any allocated memory, or restores the console or terminal the program was running in to its initial state before the call to InitKeyBoard. This function should be called on program exit. Failing to do so may leave the terminal or console window in an unusable state. Its exact action depends on the platform on which the program is running.
For an example, see most other functions.
Program Example8; { Program to demonstrate the FunctionKeyName function. } Uses keyboard; Var K : TkeyEvent; begin InitKeyboard; Writeln('Press function keys, press "q" to end.'); Repeat K:=GetKeyEvent; K:=TranslateKeyEvent(K); If IsFunctionKey(k) then begin Write('Got function key : '); Writeln(FunctionKeyName(TkeyRecord(K).KeyCode)); end; Until (GetKeyEventChar(K)='q'); DoneKeyboard; end.
For more information on getting and setting the keyboard driver section kbddriver.
The returned key is encoded as a TKeyEvent type variable, and is normally the physical key scan code, (the scan code is driver dependent) which can be translated with one of the translation functions TranslateKeyEvent or TranslateKeyEventUniCode. See the types section for a description of how the key is described.
program example1; { This program demonstrates the GetKeyEvent function } uses keyboard; Var K : TKeyEvent; begin InitKeyBoard; Writeln('Press keys, press "q" to end.'); Repeat K:=GetKeyEvent; Write('Got key event with '); Case GetKeyEventFlags(K) of kbASCII : Writeln('ASCII key'); kbUniCode : Writeln('Unicode key'); kbFnKey : Writeln('Function key'); kbPhys : Writeln('Physical key'); kbReleased : Writeln('Released key event'); end; K:=TranslateKeyEvent(K); Writeln('Got key : ',KeyEventToString(K)); Until (GetKeyEventChar(K)='q'); DoneKeyBoard; end.
It returns the null character if the key was not a character key, but e.g. a function key.
For an example, see GetKeyEvent
If the key pressed was not a function key, the null character is returned.
Program Example2; { Program to demonstrate the GetKeyEventCode function. } Uses keyboard; Var K : TKeyEvent; begin InitKeyBoard; Writeln('Press function keys, or press "q" to end.'); Repeat K:=GetKeyEvent; K:=TranslateKeyEvent(K); If (GetKeyEventFlags(K)<>KbfnKey) then Writeln('Not a function key') else begin Write('Got key (',GetKeyEventCode(K)); Writeln(') : ',KeyEventToString(K)); end; Until (GetKeyEventChar(K)='q'); DoneKeyboard; end.
For an example, see GetKeyEvent
Note that this function does not always return expected results; In a unix X-Term, the modifier keys do not always work.
Program Example3; { Program to demonstrate the GetKeyEventShiftState function. } Uses keyboard; Var K : TKeyEvent; S : Byte; begin InitKeyBoard; Write('Press keys combined with CTRL/SHIFT/ALT'); Writeln(', or press "q" to end.'); Repeat K:=GetKeyEvent; K:=TranslateKeyEvent(K); S:=GetKeyEventShiftState(K); If (S=0) then Writeln('No special keys pressed') else begin Writeln('Detected special keys : ',ShiftStateToString(K,False)); Writeln('Got key : ',KeyEventToString(K)); end; Until (GetKeyEventChar(K)='q'); DoneKeyboard; end.
No example available yet.
This function should be called once, before using any of the keyboard functions. When it is called, the DoneKeyboard function should also be called before exiting the program or changing the keyboard driver with SetKeyboardDriver.
For an example, see most other functions.
program example1; { This program demonstrates the GetKeyEvent function } uses keyboard; Var K : TKeyEvent; begin InitKeyBoard; Writeln('Press keys, press "q" to end.'); Repeat K:=GetKeyEvent; K:=TranslateKeyEvent(K); If IsFunctionKey(K) then Writeln('Got function key : ',KeyEventToString(K)) else Writeln('not a function key.'); Until (GetKeyEventChar(K)='q'); DoneKeyBoard; end.
For an example, see most other functions.
Note that this does not remove the key from the pending keys. The key should still be retrieved from the pending key events list with the GetKeyEvent function.
program example4; { This program demonstrates the PollKeyEvent function } uses keyboard; Var K : TKeyEvent; begin InitKeyBoard; Writeln('Press keys, press "q" to end.'); Repeat K:=PollKeyEvent; If k<>0 then begin K:=GetKeyEvent; K:=TranslateKeyEvent(K); writeln; Writeln('Got key : ',KeyEventToString(K)); end else write('.'); Until (GetKeyEventChar(K)='q'); DoneKeyBoard; end.
program example6; { This program demonstrates the PollShiftStateEvent function } uses keyboard; Var K : TKeyEvent; begin InitKeyBoard; Writeln('Press keys, press "q" to end.'); Repeat K:=PollKeyEvent; If k<>0 then begin K:=PollShiftStateEvent; Writeln('Got shift state : ',ShiftStateToString(K,False)); // Consume the key. K:=GetKeyEvent; K:=TranslateKeyEvent(K); end { else write('.')}; Until (GetKeyEventChar(K)='q'); DoneKeyBoard; end.
program example5; { This program demonstrates the PutKeyEvent function } uses keyboard; Var K,k2 : TKeyEvent; begin InitKeyBoard; Writeln('Press keys, press "q" to end.'); K2:=0; Repeat K:=GetKeyEvent; If k<>0 then begin if (k2 mod 2)=0 then K2:=K+1 else K2:=0; K:=TranslateKeyEvent(K); Writeln('Got key : ',KeyEventToString(K)); if (K2<>0) then begin PutKeyEvent(k2); K2:=TranslateKeyEVent(K2); Writeln('Put key : ',KeyEventToString(K2)) end end Until (GetKeyEventChar(K)='q'); DoneKeyBoard; end.
The function returns True if the driver was set, False if not.
For more information on setting the keyboard driver, see section kbddriver.
The shift state is described using the strings in the SShift constant.
For an example, see PollShiftStateEvent.
For an example, see GetKeyEvent
No example available yet.
Code | Key | Code | Key | Code | Key |
00 | NoKey | 3D | F3 | 70 | ALT-F9 |
01 | ALT-Esc | 3E | F4 | 71 | ALT-F10 |
02 | ALT-Space | 3F | F5 | 72 | CTRL-PrtSc |
04 | CTRL-Ins | 40 | F6 | 73 | CTRL-Left |
05 | SHIFT-Ins | 41 | F7 | 74 | CTRL-Right |
06 | CTRL-Del | 42 | F8 | 75 | CTRL-end |
07 | SHIFT-Del | 43 | F9 | 76 | CTRL-PgDn |
08 | ALT-Back | 44 | F10 | 77 | CTRL-Home |
09 | ALT-SHIFT-Back | 47 | Home | 78 | ALT-1 |
0F | SHIFT-Tab | 48 | Up | 79 | ALT-2 |
10 | ALT-Q | 49 | PgUp | 7A | ALT-3 |
11 | ALT-W | 4B | Left | 7B | ALT-4 |
12 | ALT-E | 4C | Center | 7C | ALT-5 |
13 | ALT-R | 4D | Right | 7D | ALT-6 |
14 | ALT-T | 4E | ALT-GrayPlus | 7E | ALT-7 |
15 | ALT-Y | 4F | end | 7F | ALT-8 |
16 | ALT-U | 50 | Down | 80 | ALT-9 |
17 | ALT-I | 51 | PgDn | 81 | ALT-0 |
18 | ALT-O | 52 | Ins | 82 | ALT-Minus |
19 | ALT-P | 53 | Del | 83 | ALT-Equal |
1A | ALT-LftBrack | 54 | SHIFT-F1 | 84 | CTRL-PgUp |
1B | ALT-RgtBrack | 55 | SHIFT-F2 | 85 | F11 |
1E | ALT-A | 56 | SHIFT-F3 | 86 | F12 |
1F | ALT-S | 57 | SHIFT-F4 | 87 | SHIFT-F11 |
20 | ALT-D | 58 | SHIFT-F5 | 88 | SHIFT-F12 |
21 | ALT-F | 59 | SHIFT-F6 | 89 | CTRL-F11 |
22 | ALT-G | 5A | SHIFT-F7 | 8A | CTRL-F12 |
23 | ALT-H | 5B | SHIFT-F8 | 8B | ALT-F11 |
24 | ALT-J | 5C | SHIFT-F9 | 8C | ALT-F12 |
25 | ALT-K | 5D | SHIFT-F10 | 8D | CTRL-Up |
26 | ALT-L | 5E | CTRL-F1 | 8E | CTRL-Minus |
27 | ALT-SemiCol | 5F | CTRL-F2 | 8F | CTRL-Center |
28 | ALT-Quote | 60 | CTRL-F3 | 90 | CTRL-GreyPlus |
29 | ALT-OpQuote | 61 | CTRL-F4 | 91 | CTRL-Down |
2B | ALT-BkSlash | 62 | CTRL-F5 | 94 | CTRL-Tab |
2C | ALT-Z | 63 | CTRL-F6 | 97 | ALT-Home |
2D | ALT-X | 64 | CTRL-F7 | 98 | ALT-Up |
2E | ALT-C | 65 | CTRL-F8 | 99 | ALT-PgUp |
2F | ALT-V | 66 | CTRL-F9 | 9B | ALT-Left |
30 | ALT-B | 67 | CTRL-F10 | 9D | ALT-Right |
31 | ALT-N | 68 | ALT-F1 | 9F | ALT-end |
32 | ALT-M | 69 | ALT-F2 | A0 | ALT-Down |
33 | ALT-Comma | 6A | ALT-F3 | A1 | ALT-PgDn |
34 | ALT-Period | 6B | ALT-F4 | A2 | ALT-Ins |
35 | ALT-Slash | 6C | ALT-F5 | A3 | ALT-Del |
37 | ALT-GreyAst | 6D | ALT-F6 | A5 | ALT-Tab |
3B | F1 | 6E | ALT-F7 | ||
3C | F2 | 6F | ALT-F8 | ||
Key | Code | SHIFT-Key | CTRL-Key | Alt-Key |
NoKey | 00 | |||
F1 | 3B | 54 | 5E | 68 |
F2 | 3C | 55 | 5F | 69 |
F3 | 3D | 56 | 60 | 6A |
F4 | 3E | 57 | 61 | 6B |
F5 | 3F | 58 | 62 | 6C |
F6 | 40 | 59 | 63 | 6D |
F7 | 41 | 5A | 64 | 6E |
F8 | 42 | 5A | 65 | 6F |
F9 | 43 | 5B | 66 | 70 |
F10 | 44 | 5C | 67 | 71 |
F11 | 85 | 87 | 89 | 8B |
F12 | 86 | 88 | 8A | 8C |
Home | 47 | 77 | 97 | |
Up | 48 | 8D | 98 | |
PgUp | 49 | 84 | 99 | |
Left | 4B | 73 | 9B | |
Center | 4C | 8F | ||
Right | 4D | 74 | 9D | |
end | 4F | 75 | 9F | |
Down | 50 | 91 | A0 | |
PgDn | 51 | 76 | A1 | |
Ins | 52 | 05 | 04 | A2 |
Del | 53 | 07 | 06 | A3 |
Tab | 8 | 0F | 94 | A5 |
GreyPlus | 90 | 4E |
TKeyboardDriver = Record InitDriver : Procedure; DoneDriver : Procedure; GetKeyEvent : Function : TKeyEvent; PollKeyEvent : Function : TKeyEvent; GetShiftState : Function : Byte; TranslateKeyEvent : Function (KeyEvent: TKeyEvent): TKeyEvent; TranslateKeyEventUniCode: Function (KeyEvent: TKeyEvent): TKeyEvent; end;The meaning of these hooks is explained below:
The following unit demonstrates how a keyboard driver can be installed. It takes the installed driver, and hooks into the GetKeyEvent function to register and log the key events in a file. This driver can work on top of any other driver, as long as it is inserted in the uses clause after the real driver unit, and the real driver unit should set the driver record in its initialization section. The following program demonstrates the use of the unit:
program example9; { This program demonstrates the logkeys unit } uses keyboard,logkeys; Var K : TKeyEvent; begin InitKeyBoard; Writeln('Press keys, press "q" to end, "s" toggles logging.'); Repeat K:=GetKeyEvent; K:=TranslateKeyEvent(K); Writeln('Got key : ',KeyEventToString(K)); if GetKeyEventChar(K)='s' then if IsKeyLogging then StopKeyLogging else StartKeyLogging; Until (GetKeyEventChar(K)='q'); DoneKeyBoard; end.