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

文章翻译 文章翻译
文章编号: 318804 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

本文以鼠标挂钩为例,介绍如何设置特定于某个线程的挂钩和特定于某个挂钩过程的挂钩。您可以使用挂钩监视特定类型的事件。您可以将这些事件作为一个调用线程与一个特定的线程或同一桌面中的所有的线程关联起来。



设置鼠标挂钩

若要设置挂钩,请从 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 框架不支持这一点。托管代码没有让函数指针具有统一的值这一概念,因为这些函数是动态构建的代理。

参考

有关窗口挂钩的更多信息,请参见下面的 MSDN 文档:
About Hooks
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/hooks_9rg3.asp

属性

文章编号: 318804 - 最后修改: 2004年3月10日 - 修订: 3.0
这篇文章中的信息适用于:
  • Microsoft .NET Framework Software Development Kit 1.0 Service Pack 2
  • Microsoft Visual C# .NET 2002 标准版
关键字:?
kbhowtomaster KB318804
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com