首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Windows 控制台程式鍵盤事件處理完全指南:ReadConsoleInput 實戰

     編輯:關於C語言

核心 API:ReadConsoleInput

BOOL ReadConsoleInput(
    HANDLE hConsoleInput,      // 標準輸入控制代碼
    PINPUT_RECORD lpBuffer,    // 輸入事件緩衝區
    DWORD nLength,             // 讀取記錄數
    LPDWORD lpNumberOfEventsRead // 實際讀取數
);

從標準輸入讀取鍵盤、滑鼠、視窗縮放等事件。鍵盤事件包含字符事件(產生字符)與按鍵事件(按下/釋放),統一通過 `INPUT_RECORD` 結構體傳遞。

關鍵結構體定義

INPUT_RECORD - 統一事件容器

typedef struct _INPUT_RECORD {
    WORD EventType;  // 事件類型
    union {
        KEY_EVENT_RECORD KeyEvent;
        MOUSE_EVENT_RECORD MouseEvent;
        WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
        MENU_EVENT_RECORD MenuEvent;
        FOCUS_EVENT_RECORD FocusEvent;
    } Event;
} INPUT_RECORD;

鍵盤事件對應 `EventType == KEY_EVENT`,具體資訊在 `Event.KeyEvent`。

KEY_EVENT_RECORD - 鍵盤事件詳情

typedef struct _KEY_EVENT_RECORD {
    BOOL bKeyDown;           // TRUE=按下, FALSE=釋放
    WORD wRepeatCount;       // 重複次數
    WORD wVirtualKeyCode;    // 虛擬鍵碼
    WORD wVirtualScanCode;   // 掃描碼
    union {
        WCHAR UnicodeChar;   // Unicode 字符
        CHAR AsciiChar;      // ASCII 字符
    } uChar;
    DWORD dwControlKeyState; // 控制鍵狀態位掩碼
} KEY_EVENT_RECORD;

常用虛擬鍵碼表(節選)

常數值按鍵
VK_ESCAPE0x1BEsc
VK_RETURN0x0DEnter
VK_SHIFT0x10Shift
VK_CONTROL0x11Ctrl
VK_MENU0x12Alt
VK_LEFT0x25←
VK_UP0x26↑
VK_RIGHT0x27→
VK_DOWN0x28↓
'A'~'Z'0x41~0x5A字母鍵
'0'~'9'0x30~0x39數字鍵(主鍵盤)
VK_F1~VK_F120x70~0x7B功能鍵

控制鍵狀態位掩碼

ENHANCED_KEY      // 擴展鍵
LEFT_ALT_PRESSED  // 左 Alt
RIGHT_CTRL_PRESSED // 右 Ctrl
SHIFT_PRESSED     // Shift
CAPSLOCK_ON       // Caps Lock 開啟
NUMLOCK_ON        // Num Lock 開啟
SCROLLLOCK_ON     // Scroll Lock 開啟

實戰範例 1:偵測 Esc 鍵退出

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

int main() {
    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD rec; DWORD cnt;
    
    for (;;) {
        ReadConsoleInput(hIn, &rec, 1, &cnt);
        if (rec.EventType == KEY_EVENT && rec.Event.KeyEvent.bKeyDown) {
            if (rec.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) {
                printf("Esc pressed, exit.\n");
                break;
            }
        }
    }
    return 0;
}

關鍵:必須檢查 `bKeyDown`,否則按下與釋放各觸發一次,導致雙重處理。

實戰範例 2:大小寫鎖定與 Shift 組合判斷

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

int main() {
    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD rec; DWORD cnt;
    
    for (;;) {
        ReadConsoleInput(hIn, &rec, 1, &cnt);
        if (rec.EventType == KEY_EVENT && rec.Event.KeyEvent.bKeyDown) {
            if (rec.Event.KeyEvent.wVirtualKeyCode == 'A') {
                DWORD state = rec.Event.KeyEvent.dwControlKeyState;
                if (state & SHIFT_PRESSED) printf("Shift+");
                if (state & CAPSLOCK_ON) printf("A "); else printf("a ");
            }
        }
    }
    return 0;
}

技巧:控制鍵狀態使用位元 AND (`&`)而非相等比較,因多個控制鍵可能同時按下(如 Shift + CapsLock)。

進階應用方向

  • 組合鍵處理:`Ctrl+C`、`Alt+F4` 等熱鍵
  • 遊戲輸入迴圈:非阻塞輪詢 `PeekConsoleInput` + `ReadConsoleInput`
  • Unicode 支援:使用 `uChar.UnicodeChar` 處理中文輸入法組合字符
  • 滑鼠事件整合:同一迴圈處理 `MOUSE_EVENT` 實現文字選擇、選單點擊

常見坑點提醒

  1. 未檢查 `bKeyDown` 導致按下/釋放雙重觸發
  2. 控制鍵狀態用 `==` 而非 `&` 判斷,漏檢同時按下情況
  3. 未處理 `wRepeatCount` > 1 的長按重複事件
  4. 混用 `scanf`/`getchar` 與 `ReadConsoleInput` 造成輸入緩衝區混亂

總結

Windows 控制台鍵盤事件處理的核心是 `ReadConsoleInput` + `KEY_EVENT_RECORD`。掌握虛擬鍵碼、掃描碼、字符碼三者關係,善用位元運算檢查控制鍵狀態,即可構建健壯的互動式控制台應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved