我正在设计一个底部停靠水平滚动条的表单。我想添加对使用鼠标倾斜按钮进行横向滚动的支持,并找到了这个解决方案,经过一番修补,它似乎可以解决问题——也就是说,虽然表单的表面只绘制了 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?
我已经设法设计了一个解决方法,但我觉得一定有比这更好的方法。我所做的是为窗体上使用的每种类型的控件添加一个类,并从控件继承。然后,我向每个类添加一个 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
然后,只需更改窗体设计器代码中的引用即可。
正如我所说,我相信一定有比这更好的方法。如果您必须为大量不同的控件类执行此操作,那将是痛苦的,但就我而言,我只需要它用于一些基本控件。
我把它开放了几天,希望有人能提出更好的解决方案,但没有任何结果,所以我将接受我自己的答案。