在 Visual C# .NET 中设置窗口挂钩

本文介绍如何使用.NET框架设置鼠标挂钩来监视鼠标事件。通过安装挂钩,可以捕获并处理特定线程上的鼠标输入,适用于创建定制的应用行为或进行输入监控。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要
本文以鼠标挂钩为例,介绍如何设置特定于某个线程的挂钩和特定于某个挂钩过程的挂钩。您可以使用挂钩监视特定类型的事件。您可以将这些事件作为一个调用线程与一个特定的线程或同一桌面中的所有的线程关联起来。
设置鼠标挂钩
若要设置挂钩,请从 User32.dll 文件中调用 SetWindowsHookEx 函数。此函数可将一个应用程序定义的挂钩过程安装到与此挂钩关联的挂钩链中。

若要设置一个鼠标挂钩并监视鼠标事件,请按照以下步骤操作:
1.启动 Microsoft Visual Studio .NET。
2.在文件菜单上,指向新建,然后单击项目。
3.在新建项目对话框中,单击项目类型下的 Visual C# 项目,然后单击模板下的 Windows 应用程序。在名称框中键入 ThreadSpecificMouseHook。默认情况下将 Form1 添加到项目中。
4.    将下面的代码行添加到 Form1.cs 文件中的其他 using 语句后面。
using System.Runtime.InteropServices;
5.    在 Form1 类中添加以下代码:
//定义委托(钩子函数,用于回调)
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
//Declare hook handle as int.
static int hHook = 0;
//Declare mouse hook constant.
//For other hook types, you can obtain these values from Winuser.h in Microsoft SDK.
public const int WH_MOUSE = 7;
private System.Windows.Forms.Button button1;
//Declare MouseHookProcedure as HookProc type.
HookProc MouseHookProcedure;              
 
//Declare wrapper managed POINT class.
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
       public int x;
       public int y;
}
 
//Declare wrapper managed MouseHookStruct class.
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
       public POINT pt;
       public int hwnd;
       public int wHitTestCode;
       public int dwExtraInfo;
}
 
//Import for SetWindowsHookEx function.
//Use this function to install thread-specific hook.
//安装钩子的函数
[DllImport("user32.dll",CharSet=CharSet.Auto,
 CallingConvention=CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
IntPtr hInstance, int threadId);
 
//Import for UnhookWindowsHookEx.
//Call this function to uninstall the hook.
//卸载钩子
[DllImport("user32.dll",CharSet=CharSet.Auto,
 CallingConvention=CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
             
//Import for CallNextHookEx.
//Use this function to pass the hook information to next hook procedure in chain.
[DllImport("user32.dll",CharSet=CharSet.Auto,
 CallingConvention=CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam); 
6.    向窗体添加 Button 控件,然后将下面的代码添加到 Button1_click 过程:
private void button1_Click(object sender, System.EventArgs e)
{
       if(hHook == 0)
       {
               // Create an instance of HookProc.
              MouseHookProcedure = new HookProc(Form1.MouseHookProc);
                           
              hHook = SetWindowsHookEx(WH_MOUSE,
                                   MouseHookProcedure,
                                   (IntPtr)0,
                                   AppDomain.GetCurrentThreadId());
              //If SetWindowsHookEx fails.
              if(hHook == 0 )
              {
                     MessageBox.Show("SetWindowsHookEx Failed");
                     return;
              }
              button1.Text = "UnHook Windows Hook";
       }
       else
       {
              bool ret = UnhookWindowsHookEx(hHook);
              //If UnhookWindowsHookEx fails.
              if(ret == false )
              {
                     MessageBox.Show("UnhookWindowsHookEx Failed");
                     return;
              }
              hHook = 0;
              button1.Text = "Set Windows Hook";
              this.Text = "Mouse Hook";
       }
}
7.    在 Form1 类中为 MouseHookProc 函数添加下面的代码:
public static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
 //Marshall the data from callback.
 MouseHookStruct MyMouseHookStruct = (MouseHookStruct) Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
 
 if (nCode < 0)
 {
    return CallNextHookEx(hHook, nCode, wParam, lParam);
 }
 else
 {
    //Create a string variable with shows current mouse. coordinates
    String strCaption = "x = " +
           MyMouseHookStruct.pt.x.ToString("d") +
              " y = " +
    MyMouseHookStruct.pt.y.ToString("d");
    //Need to get the active form because it is a static function.
    Form tempForm = Form.ActiveForm;
       
    //Set the caption of the form.
    tempForm.Text = strCaption;
    return CallNextHookEx(hHook, nCode, wParam, lParam);
 }
}
8.按 F5 键运行此项目,然后单击窗体上的按钮以设置此挂钩。当指针在窗体上移动时,鼠标坐标将出现在窗体标题栏上。再次单击此按钮可删除此挂钩。
在 .NET 框架中不支持全局挂钩
您无法在 Microsoft .NET 框架中实现全局挂钩。若要安装全局挂钩,挂钩必须有一个本机动态链接库 (DLL) 导出以便将其本身插入到另一个需要调入一个有效而且一致的函数的进程中。这需要一个 DLL 导出,而 .NET 框架不支持这一点。托管代码没有让函数指针具有统一的值这一概念,因为这些函数是动态构建的代理。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值