鍵盤 Hook 雖然強大,但易觸發 UAC 提權、系統開銷大、訊息泵處理繁瑣。經實測 RegisterHotKey 在 WinForms 環境穩定可靠,只要封裝得當即可滿足大多數熱鍵需求。
Dictionary<int, Hotkey> 追蹤每個熱鍵 ID 的視窗控制代碼與註冊狀態。RegisterHotKey(hWnd, id, modifiers, vk):若 ID 已存在先自動 UnregisterHotKey,再重新註冊,實現「同 ID 覆蓋」語意。IDisposable,Dispose() 遍歷字典逐一註銷,表單關閉時一行程式碼搞定清理。public bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk)
{
if (dicHotkeys.ContainsKey(id) && dicHotkeys[id].IsRegistered)
UnregisterHotKey(dicHotkeys[id].HWnd, id);
dicHotkeys[id] = new Hotkey(hWnd, true);
return dicHotkeys[id].IsRegistered = WinApi.RegisterHotKey(hWnd, id, fsModifiers, vk);
}
public void Dispose() {
foreach (var kv in dicHotkeys)
if (kv.Value.IsRegistered) UnregisterHotKey(kv.Value.HWnd, kv.Key);
}
KeyDown 即時組合顯示「Ctrl+Alt+A」格式,支援字母、數字鍵、小鍵盤、F1-F12。KeyPress 設 Handled=true 避免字元輸入干擾。LostFocus / KeyUp 觸發 CheckHotkey(),若以「+」結尾或為空則顯示「無」。modifiers 與 vk 呼叫 HotkeyHelper.RegisterHotKey。protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == HotkeyHelper.WM_HOTKEY) // 0x312
{
// 這裡處理熱鍵觸發邏輯,例如還原視窗、顯示表單等
if (mainForm.WindowState == FormWindowState.Minimized)
mainForm.WindowState = FormWindowState.Normal;
mainForm.Activate();
}
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
這套封裝:零依賴、自動覆蓋同 ID、表單關閉自動清理、輸入體驗友善,直接複製到專案即用。若需支援組合鍵更多變體(如 Win 鍵),只需擴充 MOD_WIN = 0x8 常數即可。