Скэн-коды клавиатуры и работа с ними




Чтение скэн-кодов клавиш — это самый низкий уровень программного опроса клавиатуры. Каждая нажатая клавиша выдает свой {505} уникальный скэн-код, который зависит только от ее местоположения на клавиатуре и никак не зависит от того, что под ней понимается. Так, арифметические знаки на алфавитной и цифровой клавиатурах имеют различные скэн-коды. Скэн-коды полностью совместимой с IBM PC ПЭВМ приведены в табл. 21. 2.

Таблица 21. 2

Клавиша Скэн-код Клавиша Скэн-код
(16) (10) (16) (10)
Esc $01   Z $2C  
!1 $02   X $2D  
@2 $03   C $2E  
#3 $04   V $2F  
$4 $05   B $30  
%5 $06   N $31  
^6 $07   M $32  
&7 $08   <, $33  
*8 $09   >. $34  
(9 $0A   ?/    
)0 $0B   Shift(правый) $36  
_- $0C   PrintScreen $37  
+= $0D   Alt $38  
BackSpace $0E   Пробел $39  
TAB $0F   CapsLock $3A  
Q $10   F1 $3B  
W $11   F2 $3C  
E $12   F3 $3D  
R $13   F4 $3E  
T $14   F5 $3F  
Y $15   F6 $40  
U $16   F7 $41  
I $17   F8 $42  
O $18   F9 $43  
P $19   F10 $44  
{[ $1A   NumLock $45  
}] $1B   ScrollLock $46  
Enter $1C   7 Home $47  
Ctrl $1D   8 Вверх $48 72 {506}
A $1E   9 PgUp $49  
S $1F   Серый - $4A  
D $20   4 Влево $4B  
F $21     $4C  
G $22   6 Вправо $4D  
H $23   Серый + $4E  
J $24   1 End $4F  
K $25   2 Вниз $50  
L $26   3 PgDn $51  
:; $27   0 Ins $52  
“ ‘ $28   . Del $53  
~` $29   F11 $D9  
Shift (левый) $2A   F12 $DA  
|\ $2B        

Проверить правильность этой таблицы на любой другой ПЭВМ (с MS-DOS и Турбо Паскалем, конечно) можно при помощи программы опроса скэн-кода нажатой клавиши (рис. 21. 10).

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 {507}

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 рассматривается каркас Паскаль-программы, позволяющей «отлавливать» одновременное нажатие нескольких регистровых клавиш вместе с алфавитной клавишей или без нее.

Аналогичным методом можно определять факты нажатия практически всех распознаваемых ПЭВМ комбинаций клавиш. Надо {508}

{КАРКАС ПРОГРАММЫ, РЕАГИРУЮЩЕЙ НА СПЕЦИАЛЬНЫЕ КОМБИНАЦИИ} { НАЖАТИЙ НА КЛАВИАТУРЕ } 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]; { чтение скэн-кода } {Устанавливаем флаг нажатия, анализируя скэн-код и состояние байта нажатия клавиш регистров: } CtrlRShiftD:=(C=HotKey) and ((M and KlavReg)=KlavReg); if CtrlRShiftD then begin { Специальная обработка } L:=Port[$61]; H:=L; { портов, если нажата } L:=L or $80; { требуемая комбинация } Port[$61]:=L; Port[$61]:=H; Port[$20]:=$20 end else { Иначе пусть выполняется } inline($FF/$1E/>OldInt09H); { настоящее прерывание } END; {$F-} VAR 1: Word; {=== ОСНОВНАЯ ЧАСТЬ ПРИМЕРА ==== } LABEL Stop; BEGIN CtrlRShiftD:=False; {обязательное стартовое значение! } ClrScr: Write(‘Нажатие Ctrl+Пр.Shift+D приостановит цикл. '); GetIntVec($09, OldInt09H); { сохраняем старый вектор } SetIntVec($09, @IntProc); { подставляем новый вектор } {...}

Рис. 21.11 {509}

for i:=1 to 30000 do begin { рабочий цикл } GotoXY(5,5); Write(1:6, ' из 30000.'); { Программа должна периодически проверять, было ли } { одновременное нажатие Ctrl+Правая Shift + D? } if CtrlRShiftD then { Да. Обработка нажатия горячего ключа } begin Write('Комбинация нажата...Закончить(Y/N)? '); if UpCase(ReadKey)='Y' then Goto Stop; ClrScr; {... } end else { Нет. Дальнейшие действия программы } begin {...} end; {if} end; {for i} { конец рабочего цикла } {... } Stop: { метка выхода из цикла } SetIntVec{ $09, OldInt09H); { вернем исходный вектор } ClrScr END.

Рис. 21.11 (окончание)

только устанавливать соответствующие значения скэн-кодов «горячих» клавиш в HotKey и числа для побитового сравнения с байтами $417/$418 в KlavReg.

Недостатком примера является задержка между нажатием комбинации клавиш и началом анализа. Избежать ее можно, если вставить вызовы процедур реакции на «горячие» комбинации прямо в Interrupt-процедуру. Однако не советуем спешить это сделать. При такой организации программы необходимо принимать специальные меры по предохранению содержимого регистров процессора, блокированию прочих прерываний, их согласованию и т.п., о чем можно всегда прочитать в любой толстой книге по системному программированию на языке ассемблера. В большинстве же программ может пригодиться и предложенный способ.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-11-01 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: