есть ли способ прочитать клавиши-модификаторы клавиатуры, такие как ALT или CTRL, в программах на базе DOS? - PullRequest
2 голосов
/ 01 августа 2020

Я знаю, что вы можете опросить буфер клавиатуры, чтобы получить клавиши-модификаторы, такие как ALT или CTRL. Но даже в старых программах DOS было действие, когда я просто нажимал эти клавиши (например, чтобы изменить цвет кнопок MENU, нажав ALT). Есть ли в DOS способ получить эти ключи? Как это сделать? Я думаю, что в BASI C не было бы решения, хотя BASI C имеет доступный обработчик событий ON. Любые рекомендации или советы по этому вопросу приветствуются.

Ответы [ 2 ]

3 голосов
/ 10 августа 2020

Вы можете посмотреть на KeyboardStatusFlags по линейному адресу 1047 в области данных B IOS. Для клавиши Alt вы исследуете бит 3, а для клавиши Ctrl вы исследуете бит 2. Следующая программа QBASI C делает именно это:

DEF SEG = 0
DO
  IF PEEK(1047) AND 8 THEN
    PRINT "ALT is pressed"
    EXIT DO
  ELSEIF PEEK(1047) AND 4 THEN
    PRINT "CTRL is pressed"
    EXIT DO
  END IF
LOOP

Ответ на комментарий

Есть ли способ получить КЛЮЧ (ЗНАЧЕНИЕ ASCII), посмотрев адрес?

Опять же, вы можете найти эту информацию в буфере клавиатуры (круговой буфер). B IOS поддерживает указатель размером в слово на место, где хранится следующий доступный ключ (HEAD), и указатель размером в слово на место за местом, где хранится последний буферизованный ключ (TAIL). Если HEAD равен TAIL, буфер клавиатуры пуст. INKEY$ в этом случае вернет пустую строку.

Head% = PEEK(1050) + 256 * PEEK(1051)
Tail% = PEEK(1052) + 256 * PEEK(1053)
IF Head% <> Tail% THEN
  Ascii% = PEEK(1024 + Head%)
  Scan% = PEEK(1024 + Head% + 1)
ELSE
  Ascii% = 0
  Scan% = 0
END IF

«Преимущество» приведенного выше кода состоит в том, что вы можете предварительно просмотреть , какой ключ (если есть) доступен следующим в буфер клавиатуры. Ключ не снимается. INKEY$ может дать ту же информацию , но также удалит ключ .

1 голос
/ 11 августа 2020

Другим решением является Ответ Майкла Петча: Stackoverflow-get ASCII VALUE

; Assemble with nasm -f bin getkeyh.asm -o getkeyh.com

GetKeyH:
    push bp
    mov  bp, sp
    les  bx, [bp+6]            ; ES:BX = address of variable to return value in
                               ; [bp+0] is where BP was pushed
                               ; [bp+2] is where the 32-bit far return address is
                               ; [bp+6] is where last parameter is
                               ; Parameters are pushed on stack left to right
                               ; like pascal calling convention.

    in   al,60h                ; Get scancode from keyboard
    xchg dx,ax
    xor  ax,ax                 ; assume no key (AX=0)
    test dl,10000000b          ; is it key up event?
    jnz  short getkeyhD        ;     if it is return 0 (in AX)
    mov  al, dl                ; Otherwise keydown, AX = scan code
getkeyhD:
    mov  [es:bx], ax           ; Update variable with scancode so BASIC can read it.
    pop bp
    

Версия, которая может использоваться с MASM / JWASM / Turbo Assembler:

; Assemble and link with Turbo Assembler to getkeyh.com file with: 
; tasm getkeyh.asm
; tlink /t getkeyh
;
; You can use JWASM a MASM clone available on MacOS/Linux/Windows to
; build getkeyh.com . You can use:
; jwasm -bin -Fo=getkeyh.com -0 getkeyh.asm
;
; -0 generates code that can run on 8088/8086 processors
; -1 for 186+ processors
; -2 for 286+ processors
;
; MASM 6.0+ and Segmented Linker LINK.EXE (5.60) can generate getkeyh.com:
; masm getkeyh.asm;
; link /t getkeyh,getkeyh.com;
;
; MASM5.x doesn't support ".model tiny" you have to use ".model small"
; and use LINK.EXE 5.60:
; masm getkeyh.asm;
; link /t getkeyh,getkeyh.com;
 
.model tiny                    ; We will generate a COM file
 
.code
org 100h                       ; COM Programs have an ORG 100h
 
GetKeyH PROC
    push bp
    mov  bp, sp
    les  bx, [bp+6]            ; ES:BX = address of variable to return value in
                               ; [bp+0] is where BP was pushed
                               ; [bp+2] is where the 32-bit far return address is
                               ; [bp+6] is where last parameter is
                               ; Parameters are pushed on stack left to right
                               ; like pascal calling convention.
 
    in   al,60h                ; Get scancode from keyboard
    xchg dx,ax
    xor  ax,ax                 ; assume no key (AX=0)
    test dl,10000000b          ; is it key up event?
    jnz  short getkeyhD        ;     if it is return 0 (in AX)
    mov  al, dl                ; Otherwise keydown, AX = scan code
getkeyhD:
    mov  es:[bx], ax           ; Update var with scancode so Turbo Basic can read it
    pop bp                     ; Do not use `RET`, Turbo Basic will return for us
GetKeyH ENDP
 
END GetKeyH                    ; Entrypoint is GetKeyH

с Turbo Basi c Программная часть:

SUB GetKeyH INLINE
    $INLINE "getkeyh.com"
END SUB

CLS
DO
    LOCATE 10, 10
    Call GetKeyH (scancode%)
    PRINT "Key = "; HEX$(scancode%); "    "
LOOP UNTIL INKEY$ = CHR$(27)

END
...