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

C# 透過 Windows Hook 監控滑鼠移動完整實作

     編輯:關於C語言

核心程式碼


using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace HookDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Win32Hook hook = new Win32Hook();
            hook.OnMouseChange += Hook_OnMouseChange;
            hook.SetHook();
        }

        private void Hook_OnMouseChange(object sender, EventArgs e)
        {
            this.Text = Cursor.Position.ToString(); // 即時顯示滑鼠座標於標題列
        }
    }

    public class Win32Hook
    {
        // 匯入 Windows API
        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(
            HookType idHook,
            HookProc lpfn,
            int hMod,
            int dwThreadId);

        public enum HookType
        {
            WH_GETMESSAGE = 3,
            WH_MOUSE = 7,           // 滑鼠訊息
            WH_KEYBOARD = 2,        // 鍵盤訊息
            WH_MOUSE_LL = 14,       // 底層滑鼠攔截 (全域)
            WH_KEYBOARD_LL = 13     // 底層鍵盤攔截 (全域)
        }

        public delegate int HookProc(int nCode, int wParam, int lParam);

        public event EventHandler OnMouseChange;

        public void SetHook()
        {
            // 安裝鉤子:WH_GETMESSAGE + 目前執行緒
            SetWindowsHookEx(
                HookType.WH_GETMESSAGE,
                new HookProc(MyHookProc),
                0,
                GetCurrentThreadId());
        }

        private int MyHookProc(int nCode, int wParam, int lParam)
        {
            if (OnMouseChange != null)
            {
                OnMouseChange(null, EventArgs.Empty);
            }
            return CallNextHookEx(0, nCode, wParam, lParam); // 傳遞給下一個鉤子
        }

        [DllImport("user32.dll")]
        private static extern int CallNextHookEx(int hhk, int nCode, int wParam, int lParam);
    }
}

關鍵技術解析

技術點說明
SetWindowsHookEx安裝鉤子程序到鉤子鏈,參數:鉤子類型、回呼函式、模組控制代碼、執行緒 ID
WH_GETMESSAGE (3)攔截 GetMessage/PeekMessage 訊息,含滑鼠/鍵盤/視窗訊息
WH_MOUSE_LL (14)低階滑鼠鉤子,**全域攔截** (不限本程序),需在非 UI 執行緒或註入 DLL
HookProc 委派鉤子回呼函式簽名:nCode (處理代碼)、wParam (訊息 ID)、lParam (訊息參數指標)
CallNextHookEx**必須呼叫**將訊息傳遞給鏈中下一個鉤子,否則系統訊息循環阻塞
GetCurrentThreadId取得目前執行緒 ID,限定鉤子範圍為當前執行緒 (區域鉤子)

鉤子類型選擇指南

需求推薦鉤子類型注意事項
僅監控自程序視窗訊息WH_GETMESSAGE / WH_MOUSE執行緒範圍,簡單安全
全域監控滑鼠/鍵盤 (含其他程式)WH_MOUSE_LL / WH_KEYBOARD_LL需註入 DLL 或獨立執行緒,UAC 高權限可能受限
攔截並修改/阻擋訊息WH_MOUSE_LL + 回傳非 0謹慎使用,可能導致系統無回應

現代替代方案

  • Raw Input API (RegisterRawInputDevices):取得原始輸入裝置資料,無鉤子效能問題
  • Windows UI Automation:跨程式 UI 元素監控與操作
  • GlobalMouseKeyHook (NuGet):封裝良好的全域鉤子庫,支援 .NET Core/5+

安全性與效能警示

  • 鉤子回呼在**系統訊息泵執行緒**執行,**嚴禁執行耗時操作** (檔案 I/O、資料庫、MessageBox)
  • 全域鉤子 (LL) 影響全系統效能,盡量縮小範圍改用區域鉤子
  • 應用程式結束時**必須卸載鉤子** (UnhookWindowsHookEx),否則導致系統資源洩漏
  • 64 位元系統需確保簽名正確 (IntPtr 而非 int 處理控制代碼)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved