You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取特定时刻按住的按键?怎样检查单个按键按压状态?

嘿,我完全懂你的需求——要实时掌握所有正在按住的按键状态,还得能单独查某个键是按下去还是抬起来,关键是程序不能卡在等待输入的循环里,得一直跑对吧?之前用int 16hin al, 60h踩了多键识别的坑,那咱们来聊聊靠谱的解决办法。

一、DOS汇编环境下的解决方案

如果你是在纯DOS环境写汇编,int 16h确实没法处理多键同时按住的情况,因为它只能读取键盘缓冲区里的单个按键。但in al, 60h这个端口读取方法其实是能搞定多键的,只是你需要自己维护一个按键状态数组来跟踪每个键的通码/断码:

核心思路

键盘控制器会通过端口60h发送两种扫描码:

  • 通码:值小于80h,表示某个按键被按下
  • 断码:值等于对应通码加80h,表示某个按键被松开

你可以创建一个大小为256的数组key_state,每个元素对应一个扫描码的状态(1表示按住,0表示抬起)。然后在程序的主循环里,定期检查键盘控制器状态端口64h(第0位为1时表示60h端口有数据),读取扫描码并更新数组。

示例代码

; 定义按键状态数组,初始全为0
key_state db 256 dup(0)

main_loop:
    ; 检查键盘控制器是否有数据待读取
    in al, 64h
    test al, 01h
    jz skip_key_process  ; 没数据就跳过处理,继续执行程序其他逻辑

    ; 读取扫描码
    in al, 60h
    mov bl, al

    ; 判断是按下还是松开
    test bl, 80h
    jnz key_released

    ; 按键按下:标记状态为1
    mov byte ptr [key_state + bx], 1
    jmp skip_key_process

key_released:
    ; 按键松开:去掉断码的80h标记,标记状态为0
    and bl, 7Fh
    mov byte ptr [key_state + bx], 0

skip_key_process:
    ; 这里写你程序的核心逻辑,比如绘图、计算等
    ; ...

    jmp main_loop  ; 循环执行,保持程序持续运行

检查特定按键状态

比如要查A键,它的扫描码是1Eh,直接读取数组对应位置即可:

; 检查A键是否按住
mov al, [key_state + 1Eh]
test al, 1
jz a_key_up
; 这里写A键按住时的逻辑
jmp check_done
a_key_up:
; 这里写A键抬起时的逻辑
check_done:
二、Windows平台下的解决方案

如果是在Windows环境开发,不管是用C/C++还是汇编,直接调用系统API会更简单,不用自己处理端口和扫描码。GetAsyncKeyState函数就是专门干这个的:

核心用法

GetAsyncKeyState接收一个虚拟键码参数(比如VK_A代表A键,'A'也可以),返回值的**最高位(第15位)**为1时,表示该按键当前正被按住;为0则表示已抬起。而且这个函数不会阻塞程序,完全符合你“持续运行”的需求。

C语言示例代码

#include <windows.h>
#include <stdio.h>

int main() {
    while (1) {
        // 检查A键的状态
        if (GetAsyncKeyState('A') & 0x8000) {
            printf("A键正在按住\n");
        } else {
            printf("A键已抬起\n");
        }

        // 检查Shift键的状态(虚拟键码VK_SHIFT)
        if (GetAsyncKeyState(VK_SHIFT) & 0x8000) {
            printf("Shift键正在按住\n");
        }

        Sleep(100);  // 加个小延迟,避免占用过多CPU
    }
    return 0;
}

批量获取所有按键状态

如果要一次性获取所有按键的状态,可以循环遍历所有虚拟键码(0到255),逐个调用GetAsyncKeyState检查,把状态存在数组里就行,逻辑和DOS下的状态数组类似,但不用处理底层端口了。


内容的提问来源于stack exchange,提问作者yaya1711

火山引擎 最新活动