.net 使鼠标倾斜水平滚动始终重复

.net 使鼠标倾斜水平滚动始终重复,.net,vb.net,winforms,mouseevent,mousewheel,.net,Vb.net,Winforms,Mouseevent,Mousewheel,我正在设计一个底部有水平滚动条的表单。我想添加对使用鼠标倾斜按钮进行侧滚的支持,并发现经过一点修补后,它似乎达到了目的——也就是说,表单的表面只绘制了GDI图形 但是,从那时起,我在表单中添加了一些控件,发现当鼠标位于其中任何一个控件上时,倾斜操作只会一次触发一次,而不是像鼠标位于表单的任何其他部分时那样重复触发 要了解我的意思,如果您有一个带有倾斜按钮的鼠标将水平滚动条停靠在窗体底部,请添加一些其他控件并粘贴到以下代码中: Public Class Form1 Const WM_MOU

我正在设计一个底部有水平滚动条的表单。我想添加对使用鼠标倾斜按钮进行侧滚的支持,并发现经过一点修补后,它似乎达到了目的——也就是说,表单的表面只绘制了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++中包含“Child”窗口时,有两条0x020E消息和两个返回值,分别为1和0。我假定消息是通过表单传递到控件上的。所以我想现在的问题是:是否可以阻止消息传递给控件?或者可以截取控件的返回值并将其转换为1吗?

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

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
然后,只需更改表单设计器代码中的引用即可

正如我所说,我相信一定有比这更好的方法。如果您必须为大量不同的控件类执行此操作,这将是一件痛苦的事情,但在我的例子中,我只需要为一些基本控件使用它


我将此项保留了几天,希望有人能提出更好的解决方案,但目前还没有结果,因此我将接受自己的答案。

通常情况下,控件会截取鼠标事件,而不会到达保存和控制滚动条的窗体。事实上,我很惊讶哪怕只有一个项目能进入状态。您可能需要连接到系统DLL以完成此任务。…@SASS_Shooter我以为WndProc收到了所有用于表单及其控件的消息。我在Spy++上玩得更多了,如果我包含“Child”窗口,很明显消息正在传递到返回0的控件上。所以问题是,是否可以阻止消息传递给控件,或者阻止控件返回值被截获并转换为1?