本文最初发表于2004年,并在2006年和2008年进行了更新。在此期间,作者收到了大量的积极反馈和建议。同时,许多有用的贡献以代码片段的形式在论坛上发布。作者决定不再单独发布新版本,而是邀请大家积极参与项目开发。
项目地址:。可以通过以下方式参与:
此类允许监听键盘和鼠标活动,甚至可以在应用程序在后台运行或完全没有用户界面时检测它们的活动。此类引发常见的.NET事件,如KeyEventArgs和MouseEventArgs,因此可以轻松检索所需的任何信息。
有许多应用程序在后台运行并检测用户不活动以更改其模式。例如,MSN Messenger(或其他任何消息传递程序)。作者打算编写这样的应用程序,因此在MSDN上找到了所需的内容: 。这篇文章描述了如何监听鼠标移动,但仅当应用程序处于活动状态时才有效。在文章的末尾,作者找到了这样的解释:“.NET Framework不支持全局钩子。不能在Microsoft .NET Framework中实现全局钩子...”。尽管如此,作者继续研究并发现有一些例外。可以全局安装WH_KEYBOARD_LL和WH_MOUSE_LL钩子。因此,作者基本上用WH_MOUSE_LL替换了MSDN示例中的WH_MOUSE,它起作用了。
第二步是将收到的信息提取到.NET EventArgs中并引发相应的事件。
作者在CodeProject上找到了一篇类似的文章:,但作者不喜欢的是,有一个主要部分是C++编写的非托管DLL。这个非托管DLL是用C++编写的,许多类使它变得复杂,难以集成到作者自己的小型应用程序中。
本文最初发表于2004年,并在2006年进行了更新。在此期间,作者收到了大量的积极反馈和建议。在此期间,技术也有所改进,例如.NET Framework 3.5或Visual Studio 2008。因此,作者决定再次更新它。
作者重构并改进了解决方案,使其更加灵活、稳定和高效。但这种重构也有一些缺点:
简单方式:如果正在开发Windows Forms应用程序并且喜欢拖放编程,有一个名为GlobalEventProvider的组件在Gma.UserActivityMonitor.dll程序集中。只需将其拖放到表单上,并使用属性编辑器事件选项卡创建事件。
替代方式:使用静态类HookManager提供的事件。注意,在事件中sender对象始终为null。
有关更多使用提示,请参见附带的演示应用程序的源代码。
要在应用程序中使用此类,只需要创建一个实例并监听想要处理的事件。当对象被创建时,钩子会自动安装,但可以使用适当的public方法停止和开始监听。
C# UserActivityHook actHook;
void MainFormLoad(object sender, System.EventArgs e)
{
actHook = new UserActivityHook();
// 创建实例
// 监听事件
actHook.OnMouseActivity += new MouseEventHandler(MouseMoved);
actHook.KeyDown += new KeyEventHandler(MyKeyDown);
actHook.KeyPress += new KeyPressEventHandler(MyKeyPress);
actHook.KeyUp += new KeyEventHandler(MyKeyUp);
}
现在,一个处理事件的示例:
C# public void MouseMoved(object sender, MouseEventArgs e)
{
labelMousePosition.Text = String.Format("x={0} y={1}", e.X, e.Y);
if (e.Clicks > 0) LogWrite("MouseButton - " + e.Button.ToString());
}
作者感谢所有在讨论论坛中有用的评论。在2004年6月4日发表本文后,发布了许多错误和建议。一次又一次地出现了相同的主题,作者不得不参考以前的帖子,这就是为什么作者决定修订代码并发布FAQ。以下是最重要的变更列表:
问题:项目无法在Visual Studio .NET 2005的调试模式下运行,因为调用SetWindowsHookEx时出现异常错误。为什么?是.NET 2.0的问题吗? 答案:编译后的发布版本运行良好,因此不能是.NET 2.0的问题。要解决这个问题,只需要在项目属性中取消选中“启用Visual Studio托管进程”复选框。在菜单中:Project -> Project Properties... -> Debug -> Enable the Visual Studio hosting process。
问题:需要在处理完一些按键后抑制它们。 答案:只需在处理过的按键事件中将e.Handled属性设置为true。它防止按键被其他应用程序处理。
问题:是否可以将全局钩子转换为应用程序钩子,仅捕获应用程序内的按键和鼠标移动? 答案:可以。只需使用...
C# private const int WH_MOUSE = 7;
private const int WH_KEYBOARD = 2;
... everywhere, instead of:
C# private const int WH_MOUSE_LL = 14;
private const int WH_KEYBOARD_LL = 13;
问题:它在Win98(Windows ME,Windows 95)上工作吗? 答案:是的和不。全局钩子WH_MOUSE_LL和WH_KEYBOARD_LL只能在Windows NT/2000/XP下监控。在其他情况下,只能使用应用程序钩子(WH_MOUSE和WH_KEYBOARD),它们仅捕获应用程序内的按键和鼠标移动。
问题:在使用钩子通过点击标题栏中的x按钮关闭应用程序时有很长的延迟。如果通过另一个事件(例如按钮点击)关闭应用程序,那就可以正常工作。 这是微软的一个已知错误。它与Windows主题有关。如果禁用Windows主题,问题就会消失。另一个选择是让钩子代码在辅助线程中运行。