Windows 主控台下,功能鍵(F1-F12、方向鍵、Home/End 等)不像一般字元鍵有單一 ASCII 碼,而是發送「擴展鍵掃描碼」序列。本文詳細說明讀取原理與完整程式碼實作。
'a' = 0x61。0x00 (NUL) 或 0xE0 (224) —— 標記為擴展鍵。0x48 (Up)、0x3B (F1)。Ctrl+字元 產生控制碼(如 Ctrl+A = 0x01),非擴展序列。
import msvcrt
def get_key():
"""讀取單一按鍵,回傳 (key_type, key_code)
key_type: 'char' | 'function' | 'ctrl'
key_code: 字元碼或掃描碼
"""
if not msvcrt.kbhit():
return None, None
first = msvcrt.getch()
first_ord = ord(first)
# 擴展鍵標記:0x00 或 0xE0
if first_ord in (0x00, 0xE0):
second = msvcrt.getch()
second_ord = ord(second)
# 合成掃描碼:首位元組 * 256 + 次位元組
scan_code = first_ord * 256 + second_ord
return 'function', scan_code
# Ctrl+字元 產生 1-26 控制碼
if 1 <= first_ord <= 26:
return 'ctrl', first_ord
# 一般可列印字元
return 'char', first_ord
# 常見功能鍵掃描碼對照表 (首位元組 0x00 或 0xE0)
KEY_MAP = {
0x003B: 'F1', 0x003C: 'F2', 0x003D: 'F3', 0x003E: 'F4',
0x003F: 'F5', 0x0040: 'F6', 0x0041: 'F7', 0x0042: 'F8',
0x0043: 'F9', 0x0044: 'F10', 0x0085: 'F11', 0x0086: 'F12',
0xE048: 'Up', 0xE050: 'Down', 0xE04B: 'Left', 0xE04D: 'Right',
0xE047: 'Home', 0xE04F: 'End', 0xE049: 'PgUp', 0xE051: 'PgDn',
0xE052: 'Insert',0xE053: 'Delete',
}
def main():
print("按鍵測試模式 (ESC 退出)")
print("格式: 類型 | 碼值 | 名稱")
print("-" * 40)
while True:
ktype, kcode = get_key()
if ktype is None:
continue
if ktype == 'char':
if kcode == 27: # ESC
print("退出")
break
name = chr(kcode) if 32 <= kcode <= 126 else "Non-printable"
print("CHAR | %3d | %s" % (kcode, name))
elif ktype == 'function':
name = KEY_MAP.get(kcode, "Unknown")
print("FUNC | %5d | %s" % (kcode, name))
elif ktype == 'ctrl':
name = "Ctrl+%c" % (kcode + 64) # 1->A, 2->B...
print("CTRL | %3d | %s" % (kcode, name))
if __name__ == '__main__':
main()
msvcrt 僅限 Windows。跨平台建議使用:
msvcrt (標準庫)、pynput (第三方)curses、readchar、pynputpynput.keyboard.Listener 事件驅動模式,支援所有平台
from pynput import keyboard
def on_press(key):
try:
print('字元鍵:', key.char)
except AttributeError:
print('特殊鍵:', key)
with keyboard.Listener(on_press=on_press) as listener:
listener.join()