首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# WinForm 讓外部進程 (CBox) 響應本程序鍵盤事件的全局鍵盤鉤子方案

     編輯:程式設計綜合問答

問題本質

外部進程擁有獨立輸入隊列,前台焦點在外部進程時,本程序 Form 的 KeyUp/KeyPress 不會觸發。需在系統級攔截鍵盤消息。

解決方案:全局鍵盤鉤子

方案一:現成組件

  • GlobalHotKey (GitHub/NuGet):封裝 SetWindowsHookEx(WH_KEYBOARD_LL),提供事件訂閱。
  • KeyboardHook (CodeProject 經典項目)。

方案二:自行實現核心步驟


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 更輕量。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved