Windows Forms 透過引發鍵盤事件來處理鍵盤輸入。大多數應用程式僅需處理 KeyDown、KeyPress、KeyUp 事件即可,但若要實作更高級的鍵盤處理(如全域熱鍵、攔截特定按鍵、自訂導航邏輯),則必須深入理解鍵盤訊息的底層運作流程。
Keys 列舉表示,對應 WM_KEYDOWN/WM_SYSKEYDOWN 訊息。可組合多個按鍵 (如 Ctrl+S)。WM_CHAR/WM_SYSCHAR 訊息。組合鍵產生字符時可透過 KeyPress 事件偵測。以按下「a」鍵為例:
訊息在到達 WndProc 前,會經過 PreProcessMessage 調用一系列可覆寫的方法:
| 操作 | 調用方法 | 說明 |
|---|---|---|
| 檢查命令鍵 (快捷鍵/選單熱鍵) | ProcessCmdKey | 優先級最高。回傳 true 則不調度訊息、不引發事件。 |
| 檢查特殊輸入鍵 | IsInputKey | 回傳 true 視為一般字符,引發 KeyDown;false 則呼叫 ProcessDialogKey。 |
| 檢查導航鍵 (Esc/Tab/Enter/方向鍵) | ProcessDialogKey | 處理控制項內部導航。向上傳遞至父控制項。回傳 true 結束預處理。 |
| 操作 | 調用方法 | 說明 |
|---|---|---|
| 檢查一般字符 | IsInputChar | 回傳 true 引發 KeyPress;false 呼叫 ProcessDialogChar。 |
| 檢查助記符 (如按鈕的 &O) | ProcessDialogChar | 類似 ProcessDialogKey,向上傳遞。容器控制項會檢查子控制項助記鍵。 |
訊息到達 WndProc 後,由以下方法處理 (可覆寫):
| 方法 | 說明 |
|---|---|
ProcessKeyMessage | 處理所有鍵盤訊息的總入口。 |
ProcessKeyPreview | 將訊息傳給父控制項。回傳 true 則不產生鍵盤事件。 |
ProcessKeyEventArgs | 根據需要引發 KeyDown、KeyPress、KeyUp 事件。 |
| 覆寫方法 | 適用情境 |
|---|---|
IsInputKey | 攔截導航鍵並引發 KeyDown (如 TextBox 處理 Tab/Enter)。 |
ProcessDialogKey | 控制項特殊輸入/導航處理 (如 ListBox 用方向鍵切換選項)。 |
IsInputChar | 攔截導航鍵引發 KeyPress (如數值輸入框加速鍵)。 |
ProcessDialogChar | KeyPress 階段特殊處理 (如 ListBox 按字母快速跳轉)。 |
若需在預處理階段強制將某鍵視為輸入鍵,可處理 PreviewKeyDown 事件並設定 e.IsInputKey = true:
private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Tab || e.KeyCode == Keys.Enter)
e.IsInputKey = true; // 強制引發 KeyDown,不被 ProcessDialogKey 攔截
}
掌握鍵盤訊息的預處理與處理管線,能讓你精確控制 WinForms 應用程式的鍵盤行為。建議原則:優先使用高層事件,只有在事件無法滿足需求時,才考慮覆寫底層預處理方法。