【问题标题】:Make mouse tilt horizontal scrolling always repeat使鼠标倾斜水平滚动总是重复
【发布时间】:2012-06-12 15:17:26
【问题描述】:

我正在设计一个底部有一个水平滚动条的表单。我想使用鼠标倾斜按钮添加对横向滚动的支持,并找到了this solution,经过一番修改后,它似乎可以解决问题——也就是说,虽然表单只在其表面上绘制了 GDI 图形。

然而,从那以后,我在表单中添加了一些控件,发现当鼠标悬停在其中任何一个它们上时,倾斜操作只会一次触发一次,而不是重复触发当鼠标悬停在表单的任何其他部分上时它会这样做。

要了解我的意思(如果您有一个带有倾斜按钮的鼠标)将水平滚动条停靠在表单底部,请添加一些其他控件并粘贴以下代码:

Public Class Form1
    Const WM_MOUSEHWHEEL As Integer = &H20E

    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)
        If Me.IsDisposed OrElse m.HWnd <> Me.Handle Then Return 
        Select Case m.Msg
            Case WM_MOUSEHWHEEL
                With HScrollBar1
                    If CType(m.WParam, Integer) < 0 Then '______________ Left Scroll
                        If .Value > 0 Then .Value -= 1
                    Else '______________________________________________ Right Scroll
                        If .Value < (.Maximum - .LargeChange + 1) Then .Value += 1
                    End If
                End With
                m.Result = CType(1, IntPtr) 'Indicates the message has been handled
        End Select
    End Sub

    Private Sub HScrollBar1_ValueChanged(sender As Object, e As System.EventArgs) Handles HScrollBar1.ValueChanged
        Console.WriteLine(HScrollBar1.Value)
    End Sub
End Class

当鼠标悬停在表单的空白部分上时,您会看到横向滚动重复,但当鼠标悬停在控件上时只会“单次”。

我猜解决方案位于消息的 .Result 值中,但我不知道应该是什么。事实上,我什至不确定我是否返回了正确的值,因为原始解决方案中的代码向 DirectCast 函数抛出了一个异常,所以我将它换成了 CType,这似乎可以正常工作。我已经尝试使用 Spy++ 解决它,但我看不到任何明显的东西。

有什么想法吗?


更新

我注意到当我在 Spy++ 中包含“子”窗口时,有两个 (0x020E) 消息和两个返回值,1 然后 0。我认为消息正在通过表单传递到控件。所以我想现在的问题是:可以防止消息传递给控件吗?或者可以截取控件的返回值并转换为1?

【问题讨论】:

  • 通常在这样的行为中,控件正在拦截鼠标事件并且永远不会到达持有和控制滚动条的表单。事实上,即使有一个事件进入表格,我也很惊讶。您可能需要挂钩到系统 DLL 来完成此操作....
  • @SASS_Shooter 我认为 WndProc 收到了 所有 用于表单及其控件的消息。我一直在玩 Spy++,如果我包含“子”窗口,很明显消息正在传递到返回 0 的控件上。所以问题是,是否可以阻止消息传递到控件或控件返回值被截获并转换为1?

标签: .net vb.net winforms mouseevent mousewheel


【解决方案1】:

我设法想出了一个解决方法,但我确信一定有比这更好的方法。我所做的是为表单上使用的每种类型的控件添加一个类,并从控件继承。然后我为每个类添加了一个 WndProc 过程,以便始终为这些控件处理的WM_MOUSEHWHEEL 消息返回1。例如,这是按钮类:

Public Class scButton
    Inherits Button
    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)
        If Me.IsDisposed OrElse m.HWnd <> Me.Handle Then Return
        If m.Msg = Win32Messages.WM_MOUSEHWHEEL Then m.Result = New IntPtr(1)
    End Sub
End Class

然后只需更改表单设计器代码中的引用即可。

正如我所说,我确信一定有比这更好的方法。如果你必须为大量不同的控件类做这件事会很痛苦,但在我的例子中,我只需要它来做一些基本的控件。


我把这个打开了几天,希望有人能提出更好的解决方案,但没有任何结果,所以我将接受我自己的答案。

【讨论】:

    猜你喜欢
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2014-07-20
    • 2011-12-11
    • 1970-01-01
    相关资源
    最近更新 更多