Справочник программиста на персональном компьютере фирмы IBM. Клавиатура
Страница 9. Написание процедуры  ввода  с клавиатуры общего назначения


     3.1.8 Написание процедуры  ввода  с клавиатуры общего назначения.


   Система  кодов, используемых клавиатурой, не поддается простой
интрепретации. Коды могут иметь длину 1 или 2 байта и нет просто-
го соответствия между длиной кода и тем, служит ли он для обозна-
чения символа или для управления оборудованием. Не все комбинации
клавиш даже выдают уникальный код, поэтому необходимы  добавочные
усилия, чтобы различить их. Ни коды ASCII, ни расширенные коды не
упорядочены таким образом, который бы позволил их простую группи-
ровку и проверку ошибок. Другими  словами, процедура ввода с кла-
виатуры общего назначения требует хлопотливого программирования.
   Здесь приведены примеры на Бейсике и с использованием прерыва-
ния 16H. В них показано как свести вместе большинство информации,
приведенной в данной главе. Общий алгоритм показан на рис. 3-3.

   Высокий уровень.


   Процедура обработки ввода с клавиатуры, написанная на Бейсике,
может делать все  что  делает  ассемблерная  процедура,  за одним
исключением.  Функция INKEY$ не предоставляет доступа к  скан-ко-
дам. Это означает, что  Вы  не  можете  сказать  получены ли коды
ASCII 8, 9, 13 и 27 от нажатия клавиш <BackSpace>, <Tab>, <Enter>
и <Escape> или через Ctrl-H,  -I,  -M  и -[.  Различие может быть
установлено  проверкой  бита  статуса  клавиши  Ctrl,  по  адресу
0040:0017, в момент нажатия клавиши. Но этот метод не будет рабо-
тать,  если  введенный символ был запасен в буфере  клавиатуры  в
течение некоторого времени.

100 C$=INKEY$:IF C$="" THEN 100   'получение символа
110 IF LEN(C$)=2 THEN 700         'если расширенный, то на 700
120 C=ASC(C$)                     'иначе берем номер кода ASCII
130 IF C<32 THEN 300              'если управляющий, то на 300
140 IF C<65 OR C>123 THEN 100     'принимаем только символы
150 '''пишущей машинки и делаем с ними, что хотим, например:
160 S$=S$+C$                      'добавляем символ к строке
170 PRINT C$;                     'выводим его на экран
180 '''... и т.д.
190 GOTO 100                      'на ввод следующего символа
 .
 .
300 '''процедура обработки управляющих кодов ASCII
310 DEF SEG = 0                   'указываем на начало памяти
320 REGISTER=PEEK(&H417)          'берем регистр статуса
330 X=REGISTER AND 4              'X=4, когда нажат Ctrl
340 IF X=0 THEN 500               'если не нажат, то на 500
350 '''если это комбинация Ctrl-буква, то делаем что хотим
360 IF C=8 THEN GOSUB 12000       'например, переходим на проце-
370 '''дуру вывода экрана помощи и т.д.
380 GOTO 100                      'на ввод следующего символа
 .
 .

500 '''процедура обработки 4-х клавиш: декодирует коды ASCII 8,
510 '''9, 13 и 27, когда клавиша Ctrl не нажата
520 IF C=8 THEN GOSUB 5000        'обработка <BackSpace>
530 IF C=9 THEN GOSUB 6000        'обработка <Tab>
540 IF C=13 THEN GOSUB 7000       'обработка <CR>
550 IF C=27 THEN GOSUB 8000       'обработка <Esc>
560 GOTO 100                      'на ввод следующего символа
 .
 .
700 '''процедура обработки расширенных кодов
710 C$=RIGHT$(C$,1)               'берем только 2-й байт C$
720 C=ASC(C$)                     'переводим в числовую форму
730 '''в C - расширенный код - делаем с ним, что хотим, например
740 IF C<71 OR C>81 THEN 100   'берем только управление курсором
750 IF C=72 THEN GOSUB 3500    'обработка "курсор-вверх"
760 '''... и т.д.
770 GOTO 100                      'на ввод следующего символа

   Средний уровень.


   Этот  пример  отличается от предыдущего методом  распознавания
четырех частных случаев Ctrl-H, -I,  -M и -[. Здесь, когда встает
вопрос о том, возник ли указанный код при нажатии одной  клавиши,
или в комбинации с  клавишей  Ctrl,  проверяется  скан-код.  Этот
метод более правилен, чем проверка бита статуса, так как скан-код
запоминается в буфере  клавиатуры, а установка бита статуса может
быть изменена.

;---получение кода нажатой клавиши и определение его типа
NEXT:  MOV  AH,0           ;функция ввода с клавиатуры BIOS
       INT  16H            ;получаем введенный код
       CMP  AL,0           ;проверка на расширенный код
       JE   EXTENDED_CODE  ;если да, то на спец. процедуру
       CMP  AL,32          ;проверка на управляющий символ
       JL   CONTROL_CODE   ;если да, то на спец. процедуру
       CMP  AL,65          ;если символ не входит в набор пишу-
       JL   NEXT           ;щей машинки, то берем следующий
       CMP  AL,123         ;
       JL   NEXT           ;
;---теперь обрабатываем символ в AL
       STOSB               ;запоминаем символ по адресу ES:DI
       MOV  AH,2           ;функция вывода символа на экран
       MOV  DL,AL          ;помещаем символ в DL перед выводом
       INT  21H            ;выводим его на экран
        .
        .
       JMP  NEXT           ;переходим к следующему символу

;---анализируем управляющие коды
CONTROL_CODE:  CMP  AL,13       ;код ASCII 13?
               JNE  TAB         ;если нет, то след. проверка
               CMP  AH,28       ;иначе проверяем скан-код <CR>
               JNE  C_M         ;если нет, то было Ctrl-M
               CALL CARRIAGE_RET;обработка возврата каретки
               JMP  NEXT        ;переход к следующему символу
C_M:           CALL CTRL_M      ;обработка Ctrl-M
               JMP  NEXT        ;переход к следующему символу
TAB:           CMP  AL,9        ;проверка на табуляцию...
                .
                .
               CMP  AL,10       ;затем проверка других
                .
                .
REJECT:        JMP  NEXT        ;переход к следующему символу
;---анализ расширенных кодов (2-й байт кода в AH):
EXTENDED_CODE: CMP  AH,71       ;проверка нижней границы
               JL   REJECT      ;если меньше, то след. символ
               CMP  AH,81       ;проверка верхней границы
               JL   REJECT      ;если больше, то след. символ
;---AH содержит символ управления курсором, анализируем его:
               CMP  AH,72       ;"курсор-вверх"?
               JE   C_U         ;если да, то на процедуру
               CMP  AH,80       ;"курсор-вниз"?
               JE   C_D         ;если да, то на процедуру
                .
                .
C_U:           CALL CURSOR_UP   ;вызов соответствующей процедуры
               JMP  NEXT        ;переход к следующему символу
C_D:           CALL CURSOR_DOWN ;вызов соответствующей процедуры
               JMP  NEXT        ;переход к следующему символу

 
« Предыдущая статья   Следующая статья »