Энциклопедия Turbo Pascal. Главы 1-4 - Использование кодов клавиш сканирования

ОГЛАВЛЕНИЕ

Использование кодов клавиш сканирования

При работе на ПЭВМ фирмы ИБМ наиболее сложно обрабатывать программно коды функциональных клавиш и клавиш со стрелками /также клавиш INS,  DEL,  PGOP,  PGDN, END и HOME/. При нажатии такой клавиши генерируется не восьмибитовый /однобайтовый/ код, как делается при нажатии других клавиш.  При нажатии такой клавиши в действительности генерируется шестнадцатибитовый код, называемый кодом сканирования.  Код сканирования состоит из младшего байта, который при нажатии обычной клавиши будет содержать код ASCII для этой клавиши,  и старшего байта, который содержит позицию клавиши на клавиатуре.

Для большинства клавиш операционная система преобразует код сканирования в  соответствующий восьмибитовый код ASCII.  Но для функциональных клавиш и клавиш со стрелками это преобразование не делается,  поскольку код символа для специальной клавиши будет иметь нулевое значение. Это означает, что для определения нажатой клавиши необходимо воспользоваться кодом позиции.  Программу чтения символа с клавиатуры посредством обращения к функции ДОС с номером I нельзя использовать для чтения специальных клавиш. Это, очевидно,  приводит к трудностям,  когда в программе необходимо использовать специальные клавиши.  В Турбо Паскале версии 4 предусматривается функция "Readkey",  предназначенная для чтения и символов и кодов. Однако в приводимой ниже процедуре используется другой подход. Здесь делается прерывание $16 для получения полного шестнадцатибитового кода клавиши.

     ; эта процедура выдает шестнадцатибитовый код,  младший байт
     ; которого содержит либо символ ASCII,  либо нулевое значе     ; ние. В последнем случае старший байт содержит код сканиро     ; вания

     code    segment 'code'
             assume cs:code

     public  scan
     scan    proc near

     ; сохранить указатель стека
             push bp
             mov bp,sp

     ; получить первый параметр
            mov ah,0
            int 16h
            mov [bx+2],ax; возвращаемое значение
     ; восстановление и выход

            pop bp
            ret 2
     scan   endp
     code   endx
            end

После вызова код сканирования и код символа уже будут находиться в регистре АХ,  который следует использовать для передачи информации в вызывающую процедуру. После прерывания 16n с нулевым функциональным номером код позиции будет находиться в  регистре АН,  а код символа будет находиться в регистре AL.  Процедура "scan" написана с учетом того, что при нажатии специальной клавиши код символа имеет нулевое значение.

Если код символа имеет нулевое значение, то декодируется код позиции для определения,  какая клавиша была нужна. Для обработки всякого ввода с клавиатуры посредством указанной функции решения следует принимать на основе содержимого регистров АН и  AL.  Один из таких способов иллюстрируется ниже в короткой программе:

     program special_keys;

     {SL SCAN}

     var
       t: integer;

     function Scan:integer; external;

     begin
       repeat
         t: = Scan;
         if lo(t)=0 then WriteLn('scan code is', hi(t))
         else WriteLn(chr(lo(t)));
       until chr(lo(t))='q';
     end.

Для доступа к обеим половинам шестнадцатиразрядного значения, полученного процедурой "scan", можно воспользоваться предусмотренными в Турбо Паскале стандартными функциями  "Ht"  и  "Lo".
Кроме того,  для преобразования целого числа в символ потребуется функция "Chr".

Для декодирования кода сканирования вы можете воспользоваться техническим справочным руководством фирмы ИБМ.  Другой,  более интересный способ,  заключается в написании короткой программы, единственным назначением которой является лишь экспериментальная выдача кодов нажатых клавиш.  Для начала приведем коды сканирования для клавиш со стрелками:

Левая стрелка - 75,
Правая стрелка - 77,
Стрелка вверх - 72,
Стрелка вниз - 80.

Для полного совмещения специальных клавиш с обычными кла вишами необходимо написать специальные функции ввода данных и использовать их вместо обычных функций "read" и "readln". К сожалению этот путь является единственным.  Однако,  наградой будет возможность работать в  вашей программе с полным набором клавиш ПЭВМ фирмы ИБМ.