鼠标滚轮事件重定向器

在许多应用程序中,用户在使用鼠标滚轮时,需要先点击控件才能触发滚动或其他操作。这种默认行为有时会导致用户体验不佳,如果应用程序能够实现鼠标指针在控件上时自动响应滚轮事件,将大大提高用户体验。这种功能通常被称为鼠标悬停滚动或鼠标悬停缩放。一个典型的例子是在Windows资源管理器中组合使用TreeViewListView

为了在不同的应用程序中实现这种功能,不得不一次又一次地编写相同的代码,使用MouseEnter、MouseLeave、IMessageFilter等。因此,创建了一个类,它允许通过一行代码实现这个功能。这个类可以简单地将任何控件附加到重定向器上,并且当鼠标指针在其边界内时,它将立即开始接收鼠标滚轮事件。

使用代码

将MouseWheelRedirector.vb添加到Windows Forms应用程序项目中。

要开始为控件接收鼠标滚轮事件,请使用以下代码:

Dim myControl As New Control() MouseWheelRedirector.Attach(myControl)

要停止为该控件接收鼠标滚轮事件(除非它有焦点),请使用以下代码:

MouseWheelRedirector.Detach(myControl)

要暂停所有附加控件的重定向(不分离它们),请使用以下代码:

MouseWheelRedirector.Active = False

要恢复所有附加控件的重定向,请使用以下代码:

MouseWheelRedirector.Active = True

以下是使用该类与TreeViewListView的示例代码。要使用它,只需创建一个新的Windows应用程序,并将以下代码放入Form1的代码窗口:

Option Explicit On Option Strict On Option Infer On Imports System.Windows.Forms Public Class Form1 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim tools As New ToolStrip() tools.Items.Add(New ToolStripButton("Suspend MouseWheelRedirector", Nothing, AddressOf SuspendRedirector)) tools.Items.Add(New ToolStripButton("Resume MouseWheelRedirector", Nothing, AddressOf ResumeRedirector)) Dim split As New SplitContainer() split.Dock = DockStyle.Fill Dim tree As New TreeView() tree.Dock = DockStyle.Fill Dim list As New ListView() list.Dock = DockStyle.Fill list.View = View.List Me.Height = 300 Me.Width = 800 split.Panel1.Controls.Add(tree) split.Panel2.Controls.Add(list) Me.Controls.Add(split) Me.Controls.Add(tools) For i = 0 To 199 tree.Nodes.Add("Tree View Node " & i) list.Items.Add("List View Item " & i) Next tree.ExpandAll() MouseWheelRedirector.Attach(tree) MouseWheelRedirector.Attach(list) End Sub Private Sub SuspendRedirector(ByVal sender As Object, ByVal e As System.EventArgs) MouseWheelRedirector.Active = False End Sub Private Sub ResumeRedirector(ByVal sender As Object, ByVal e As System.EventArgs) MouseWheelRedirector.Active = True End Sub End Class

技术要点

这个类使用了以下技术来完成给定的任务:

  • 监听控件的MouseEnter和MouseLeave事件,以确定鼠标指针是否在控件上。
  • 实现IMessageFilter以捕获应用程序中的WM_MOUSEWHEEL消息。
  • 使用PInvoke调用Windows API函数SendMessage,将WM_MOUSEWHEEL消息重定向到控件的句柄。

IMessageFilter对象作为MouseWheelRedirector类的单例实现,并通过共享成员Attach、Detach和Active进行访问。

限制

正如在评论和讨论部分所指出的,如果附加的控件有子控件,当鼠标指针在子控件上时,重定向器将无法工作:每当鼠标指针击中子控件时,父控件的鼠标离开事件将触发,父控件将停止接收重定向的鼠标滚轮事件,直到下一个鼠标进入事件。

If instance.currentControl Is control Then instance.currentControl = Nothing End If
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485