如何用VB.NET注册全局鼠标事件(移动、点击)?

How to register to global mouse events (move, click) with VB.NET?

对于我自己实现的轻量级远程服务应用程序(如 RDP、TeamViewer),我需要监听系统(或全局)的鼠标事件,如鼠标移动或 left/right/middle/etc 单击。

我发现,有一个托管的 interface/API 用于查询系统的鼠标位置:

Dim pos As System.Drawing.Point = Windows.Forms.Cursor.Position
Label1.Text = String.Format("Current Position: {0} - {1}", pos.X, pos.Y)

不过classWindows.Forms.Cursor好像没有活动,我可以register/listen来。 Private WithEvents MyCurser As Windows.Forms.Cursor 没有任何包含 Handles 的列表。

为了更清楚:我确实想在我的应用程序外部跟踪鼠标事件(所以我自己的表单的点击事件监听器不适用),因为我的应用程序是远程服务应用程序,如 RDP 或 TeamViewer,仅将鼠标事件(和显示)转发到远程计算机。

是否有 managed (.NET) 方法将鼠标位置更改为事件(并且不需要计时器来查询位置),以及是否用户点击了(正在点击)鼠标上的按钮(这是什么按钮)?

奖励问题:当鼠标 move/click "event" 由另一个软件触发而不是由实际操作鼠标的人触发时,您的解决方案是否有效。

您可以使用我的库 InputHelper。它旨在帮助 .NET 开发人员以简单、正确的方式捕获和模拟鼠标和键盘输入。

在看到并回答了太多 Stack Overflow 问题后,用户要么使用了已弃用的 API,要么他们的 P/Invoke 签名偏离了方向,我决定将其创建为更 .NET - 管理输入的友好方式,以及尝试与用户从互联网上许多不同地方收集的唯一部分正确的代码作斗争。

InputHelper 是围绕本机 Windows API (WinAPI) 构建的,并利用 SendInput(), SendMessage()/PostMessage() and SetWindowsHookEx() 等功能来完成其工作。

它的 Wiki 遗憾的是还远未完成,因为我只记录了鼠标和键盘挂钩,但是该库包含 XML 文档文件,其中包含解释其中每个函数的注释,它们是在您键入代码时由 IntelliSense 自动显示。因此,对于库的小型文档和概述,您始终可以打开 Visual Studio 的对象浏览器(在任何类型或名称空间上按 F12,或转到 View > Object Browser) 并在那里找到它。

InputHelper目前包含四个caregories:

  • InputHelper.Hooks: 类 用于捕获系统范围的鼠标和键盘输入。例如,这可以用来制作热键。

  • InputHelper.Keyboard:模拟物理("real")键盘input/key笔画的方法。

  • InputHelper.Mouse:模拟物理鼠标输入的方法

  • InputHelper.WindowMessages:在更虚拟的层面上模拟鼠标和键盘输入的方法。这利用 window 消息 (Send-/PostMessage) 并可用于针对特定 windows.

您要查找的是 InputHelper.Hooks,具体来说,InputHelper.Hooks.MouseHook.

首先,在 Releases page 上下载库的编译版本并将其添加为项目的引用。为方便起见,在您将要使用的文件中导入 InputHelperLib 命名空间:

Imports InputHelperLib

现在,创建鼠标挂钩的最简单方法是在 class 级别实例化 MouseHook class 的实例:

Dim MouseHook As New InputHelper.Hooks.MouseHook

这将侦听鼠标事件,直到变量超出范围或直到您对其调用 Dispose()

如果您不想立即启动挂钩,只需声明变量并在需要时对其进行初始化。

Dim MouseHook As InputHelper.Hooks.MouseHook

'Start the hook at the click of a button.
Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
    If MouseHook Is Nothing Then
        MouseHook = New InputHelper.Hooks.MouseHook
    End If
End Sub

钩子包括四个事件:

  • MouseDown - 按下或按住鼠标按钮时发生。

  • MouseMove - 鼠标移动时发生。

  • MouseUp - 释放鼠标按钮时发生。

  • MouseWheel - 滚动鼠标滚轮时发生。

您可以使用 AddHandler statement.

订阅活动
Dim MouseHook As InputHelper.Hooks.MouseHook

'Start the hook at the click of a button.
Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
    If MouseHook Is Nothing Then
        MouseHook = New InputHelper.Hooks.MouseHook

        AddHandler MouseHook.MouseDown, AddressOf MouseHook_MouseDown
        AddHandler MouseHook.MouseMove, AddressOf MouseHook_MouseMove
        AddHandler MouseHook.MouseWheel, AddressOf MouseHook_MouseWheel
    End If
End Sub

示例 MouseDown 事件处理程序:

Private Sub MouseHook_MouseDown(sender As Object, e As InputHelperLib.InputHelper.Hooks.MouseHookEventArgs)
    If e.Button = System.Windows.Forms.MouseButtons.Left AndAlso e.DoubleClick = True Then
        MessageBox.Show("Left mouse button was double-clicked.")
    End If
End Sub

示例 MouseMove 事件处理程序:

Private Sub MouseHook_MouseMove(sender As Object, e As InputHelperLib.InputHelper.Hooks.MouseHookEventArgs)
    LogTextBox.AppendText("Mouse moved to (X: " & e.Location.X & ", Y: " & e.Location.Y & ")")
End Sub

示例 MouseWheel 事件处理程序:

Private Sub MouseHook_MouseWheel(sender As Object, e As InputHelperLib.InputHelper.Hooks.MouseHookEventArgs)
    If e.Delta > 0 AndAlso e.ScrollDirection = InputHelper.Hooks.ScrollDirection.Vertical Then
        MessageBox.Show("Mouse scrolled up")
    End If
End Sub

现在您有了一个可以正常工作的全局鼠标挂钩!

有关挂钩及其事件参数的更多详细信息,请查看项目的 wiki

Bonus question: Does your solution work when the mouse move/click "event" has been triggered by another software and not by the human who is actually operating the mouse.

是也不是。这取决于其他软件如何触发事件。如果它使用 SendInput 或类似的东西来模拟实际的物理输入,那么是的。如果它使用 window 消息来定位特定的 windows 则不会。