有没有办法在基于 DOS 的程序中读取键盘修饰键,例如 ALT 或 CTRL?

问题描述 投票:0回答:2

我确实知道您可能会轮询键盘缓冲区以获取修饰键,例如 ALTCTRL。但即使在旧的 DOS 程序中,每当我按下这些键时就会执行一个操作(例如,通过按 ALT 更改菜单按钮的颜色)。在DOS下有没有办法获得这些密钥?这要怎么做呢?我认为在 BASIC 中没有解决方案,尽管 BASIC 有一些可用的

ON KEY()
事件处理程序。欢迎对此问题提出任何建议或建议。

keyboard dos x86-16 basic turbo-basic
2个回答
3
投票

您可以在BIOS数据区的线性地址1047处查看KeyboardStatusFlags。对于 Alt 键,您检查位 3,对于 Ctrl 键,您检查位 2。下一个 QBASIC 程序正是这样做的:

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 值)?

您可以再次在键盘缓冲区(循环缓冲区)中找到此信息。 BIOS 维护一个字大小的指针,指向存储下一个可用密钥的位置 (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
投票

另一个解决方案是 Michael Petch 的回答: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 Basic 程序部分:

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
© www.soinside.com 2019 - 2024. All rights reserved.