| USES CRT, DOS;
| VAR
| Ch, ExtCh : Char; {символы с клавиатуры }
| Scan, LastScan : Byte; {скэн-коды клавиш }
| OldInt09H : Pointer; {адрес старого вектора }
| {$F+}
| PROCEDURE IntProc; INTERRUPT; {перехват прерывания }
| BEGIN
| Scan:=Port[$60]; {чтение скэн-кода }
| Inline($FF/$1E/>OldInt09H); {возврат прерывания }
| END;
| {$F-}
| BEGIN
| GetIntVec($09, OldInt09H); {взятие адреса прерывания }
| SetIntVec($09, @IntProc); {подстановка перехватчика }
Рис. 21.10
- 508 -
| Scan := 128;
| { стартовое значение Scan }
| WriteLn('Нажимайте что угодно.', 'Esc - выход из программы.');
| repeat { Основной цикл опроса: }
| Ch := #0;
| ExtCh := #0;
| { сброс значений до опроса }
| repeat
| until Scan<128; { ожидание любого нажатия }
| Write( ' Скэн-код=', Scan:3 );
| if KeyPressed { Клавиша - не регистровая? }
| then Ch:=ReadKey; { да, ее код запоминается }
| if KeyPressed and (Ch=#0) {Клавиша - функциональная? }
| then ExtCh := ReadKey; { да, запоминается расш. код }
| { вывод итогов опроса: }
| Write ( 'Символ', Ch + ExtCh );
| GotoXY( 30, WhereY ); { нейтрализация кода 13 }
| WriteLn(('” Код=', Ord( Ch ):3, ' Расш. код=', Ord( ExtCh ) );
| LastScan := Scan; { нужен последний скэн-код }
| Scan := 128; { снова стартовое значение }
| until LastScan=1; { условие конца — нажата Esc }
| SetIntVec($09, OldInt09H);
| { восстановление прерывания }
| ReadLn { пауза до нажатия ввода }
| END.
Рис. 21.10 (окончание)
Программа перехватывает низкоуровневое прерывание номер 9 и запоминает содержимое порта, через который передаются коды нажатых клавиш, в глобальной переменной Scan. После этого анализируется, внесло ли нажатие что-либо в буфер ввода. Если да, то выводится информация о нажатой клавише. Используя перехват прерывания, кaк это сделано в примере, можно проводить и более сложный анализ (рис. 21.11). После каждого нажатия любой клавиши перехватчик записывает в Scan скэн-код. Но здесь есть особенность: при нажатии клавиши вырабатывается истинный скэн-код, а при отпускании — увеличенный на 128. Поэтому в примере ожидание нажатия возложено на цикл
repeat until Scan < 128;
который размыкается только при нажатии клавиши (Scan содержит число, меньшее 128) и не реагирует на отпускание их.
На рис. 21.11 рассматривается каркас Паскаль-программы, позволяющей «отлавливать» одновременное нажатие нескольких регистровых клавиш вместе с алфавитной клавишей или без нее.
Аналогичным методом можно определять факты нажатия практически всех распознаваемых ПЭВМ комбинаций клавиш. Надо
- 509 -
| { КАРКАС ПРОГРАММЫ, РЕАГИРУЮЩЕЙ НА СПЕЦИАЛЬНЫЕ КОМБИНАЦИИ}
| { НАЖАТИЙ НА КЛАВИАТУРЕ }
| USES CRT, DOS;
| {Необходим модуль DOS. CRT нужен для примера. }
| VAR { глобальные переменные программы : }
| OldInt09H : Pointer; { адрес прерывания 09 }
| CtrlRShiftD : Boolean; { флаг нажатия комбинации }
| CONST { Константы специальной комбинации клавиш: }
| HotKey = $20; { скэн-код клавиши [D]; }
| KlavReg = 1+4; { значение в байте $0:$0417 при нажатии }
| { левого регистра Shift вместе с Ctrl : }
| { 1 - нажата правая клавиша Shift (бит 0); }
| { 4 - Нажато Ctrl+Shift (бит номер 2). }
| {$F+}
| PROCEDURE IntProc; INTERRUPT; {перехват прерывания 09Н }
| VAR
| M: Byte absolute $000:$417; { байт состояния регистров }
| C,L,H : Byte; { значение скэн-кода и др. }
| BEGIN
| С := Port[$60]; { чтение скэн-кода }