21.3. Опрос расширенных кодов и функциональных клавиш
Обычные клавиши, даже если они нажаты одновременно с регистрами Ctrl или Shift, выдают символ с ASCII-кодом в диапазоне 1..127 (на русифицированных ПЭВМ диапазон расширяется почти до 255).
Но на клавиатуре ПЭВМ класса IBM PC имеется еще один, альтернативный, регистр (Alt) и десять функциональных клавиш (F1...F10). Алфавитно-цифровые клавиши, нажатые одновременно с клавишей Alt, и функциональные клавиши в любом регистре посылают в буфер ввода с клавиатуры сразу два символа: первый — символ с кодом 0 (нулевой символ), и второй — с цифровым кодом, характеризующим нажатую клавишу. Именно он и называется расширенным кодом.
Понятно, что подобный механизм значительно увеличивает информационную отдачу клавиатуры. Но его необходимо учитывать при программировании опроса клавиатуры, так как расширенные коды могут совпадать с нормальной кодировкой символов (так, F1 даст расширенный код 59, что будет трактоваться, как символ «;»). Рассмотренные в предыдущих разделах примеры могут давать сбои при нажатиях функциональных клавиш или обычных клавиш в регистре Alt.
Усовершенствованная программа опроса клавиатуры (универсальный вариант) показана на рис. 21.5.
| PROGRAM TestKeyBoard; { Пример опроса клавиш F1 - F10 }
| USES CRT;
| VAR
| ch : Char;
| ExtendedKey : Boolean; { флаг расширенного кода }
Рис. 21.5
- 500 -
| { $I clrkey.inc} { описание процедуры ClrKeyBuf }
| {$I wait.inc} { описание процедуры Wait }
| BEGIN
| ClrScr;
| {...} { программа без диалога }
| ClrKeyBuf; { очистка буфера }
| WriteLn( Нажмите функциональную клавишу. );
| Repeat { цикл опроса клавиш }
| ch := ReadKey; { опрос буфера клавиатуры }
| if ch=#0 { Первый байт - нулевой? }
| then { Да, код - расширенный. }
| begin { Считывается следующий }
| ch := ReadKey; { за ним расширенный код. }
| ExtendedKey := True { флаг расширенного кода }
| end
| else { Нет, код – не расширенный. }
| ExtendedKey := False; { флаг не устанавливается }
| until ( ( ch in [#59..#68] ) and ExtendedKey );
| { повторять, пока не получим расширенные коды F1..F10 }
| { ОБРАБОТКА НАЖАТОЙ ФУНКЦИОНАЛЬНОЙ КЛАВИШИ }
| WriteLn('Была нажата клавиша F',(Ord(ch) - 58):1);
| Wait; ClrScr
| END.
Рис. 21.5 (окончание)
Теперь проверяется, какой код считан первым. Если нулевой, то надо считать второй символ из буфера. Он и будет расширенным ходом. А чтобы по-прежнему реагировать только на избранные клавиши, вводится логическая переменная, которая показывает, является ли полученный от клавиши код расширенным или нет. Рассмотренный пример реагирует только на клавиши F1...F10 в «чистом» виде. Если убрать из программы оператор цикла repeat...until, то фрагмент будет возвращать значащий код любой клавиши и устанавливать значение логической переменной ExtendedKey=True в случае нажатия функциональной клавиши или Alt-комбинации.
В примере на рис. 21.5 программа будет ждать нажатия клавиш. Если это нежелательно, то надо убрать из текста вызов ClrKeyBuf и основную часть переписать так:
- 501 -
IF KeyPressed {Была ли нажата Клавиша?}
THEN BEGIN {Да, буфер – не пустой.}
ch := ReadKey; { опрос буфера клавиатуры }
if ch=#0 { Первый байт - нулевой?}
then {Да, код – расширенный.}
BEGIN { Считывается следующий }
ch := readkey; { за ним расширенный код. }
Extended := True { флаг расширенного кода }
end
else { Нет, код – не расширенный.}
Extended := False; { Флаг не устанавливавтся }
END {then}
ELSE { не было нажатия клавиш }
ch := #0; { особое значение }
Теперь программа не будет «зависать» в ожидании и сможет работать дальше, даже если ничего не было нажато. В таком случае в ch записываем символ #0 как признак пустого прохода.
Иногда можно применять особенность редактора текстов системы Турбо Паскаль — возможность непосредственного включения в тексты управляющих кодов клавиатуры. Можно получить в тексте программы «образ» любой управляющей или функциональной клавиши, нажав комбинацию клавиш Ctrl+P и следом саму эту клавишу. На экране появится символ с измененным цветом (символ может быть сдвоенным). Его можно трактовать как символ, соответствующий нажатой специальной клавише:
case ReadKey of
'@H' : реакция на нажатие стрелки курсора вверх;
'@P' : реакция на нажатие стрелки курсора вниз;
'@' : реакция на нажатие клавиши F1;
'[' : реакция на нажатие клавиши Esc;
'A' : реакция на нажатие обычной клавиши A
end; {case}