外部進程擁有獨立輸入隊列,前台焦點在外部進程時,本程序 Form 的 KeyUp/KeyPress 不會觸發。需在系統級攔截鍵盤消息。
SetWindowsHookEx(WH_KEYBOARD_LL),提供事件訂閱。
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")] static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hInstance, uint threadId);
[DllImport("user32.dll")] static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")] static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
private IntPtr _hookId = IntPtr.Zero;
private LowLevelKeyboardProc _proc = HookCallback;
private void SetHook() {
using (Process cur = Process.GetCurrentProcess())
using (ProcessModule mod = cur.MainModule)
_hookId = SetWindowsHookEx(13, _proc, GetModuleHandle(mod.ModuleName), 0); // WH_KEYBOARD_LL = 13
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && (wParam == (IntPtr)0x0100 || wParam == (IntPtr)0x0104)) { // WM_KEYDOWN, WM_SYSKEYDOWN
int vkCode = Marshal.ReadInt32(lParam);
// 這裡分發給你的邏輯處理
HandleGlobalKey(vkCode);
}
return CallNextHookEx(_hookId, nCode, wParam, lParam);
}
protected override void OnFormClosing(FormClosingEventArgs e) {
UnhookWindowsHookEx(_hookId);
base.OnFormClosing(e);
}
WH_KEYBOARD_LL) 不需 DLL 注入,回調在安裝線程上下文執行,**回調必須極快返回**,否則系統會繞過鉤子。複雜邏輯請 Task.Run 或郵箱隊列異步處理。RegisterHotKey 更輕量。