让鼠标倾斜水平滚动总是重复鼠标、水平

2023-09-06 17:31:29 作者:忆

我设计与停靠在底部的水平滚动条的形式。我想补充使用鼠标倾斜按键侧面滚动的支持,并发现这个解决方案这,一些调整后,似乎这样的伎俩,那就是 - 在窗体只有绘制在其表面GDI图形。

I'm designing a form with a horizontal scroll bar docked at the bottom. I wanted to add support for side-scrolling using mouse tilt buttons and found this solution which, after a bit of tinkering, seemed to do the trick – that is, while the form only had GDI graphics drawn on its surface.

不过,从那时起,我已经添加了一些控件到窗体,并发现,当鼠标移动到任何的这些的倾斜操作只能触发一次而不是-AT-A-时间多次被评为确实,当鼠标移动到表格的其他部分。

However, since then I've added some controls to the form and found that when the mouse is over any of them the tilt operation only fires once-at-a-time instead of repeatedly as it does when the mouse is over any other part of the form.

要明白我的意思(如果你有一个鼠标倾斜按钮),停靠水平滚动条到窗体底部,添加一些其他控件并粘贴此code:

To see what I mean (if you have a mouse with tilt buttons) dock a horizontal scrollbar onto the bottom of a form, add a few other controls and paste in this code:

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

您会看到一个侧面滚动重复,当鼠标移动到表格的空白部分,但只有一杆时,它在一个控制。

You'll see that side-scrolling repeats when the mouse is over a blank part of the form, but only "one-shots" when it's over a control.

我猜的解决之道在于某处的消息的。结果的价值,但我茫然,什么是应该的。事实上,我甚至不知道我返回正确的值,反正因为code在原有解决方案抛出异常的DirectCast函数,所以我换,对于CTYPE,这似乎工作好。使用间谍我试着努力吧+ +,但我看不到任何明显。

I'm guessing the solution lies somewhere in the message's .Result value, but I'm at a loss as to what that should be. In fact I'm not even sure I'm returning a correct value anyway because the code in the original solution threw an exception to the DirectCast function so I swapped that for CType, which seemed to work okay. I've tried working it out using Spy++ but I can't see anything obvious.

任何想法吗?

更新

我注意到,当我有'儿童'窗口间谍++有两个(0x020E)消息和两个返回值,1然后按0。我presume的消息被传递到由窗体控件。所以我想现在的问题是:可以将邮件从传递到控制pvented $ P $?或者可以控制的返回值被拦截并转换为1?

I've noticed when I include 'Child' windows in Spy++ there are two (0x020E) messages and two return values, 1 then 0. I presume the message is being passed onto the control by the form. So I guess the question now is: can the message be prevented from being passed to the control? Or can the control's return value be intercepted and converted to 1?

推荐答案

我已经成功地图谋一种解决方法,但我觉得肯定必须有一个比这更好的方法。我所做的就是添加一个类为每种类型的控制在我的形式,从控制继承使用。然后,我添加了一个WndProc的程序,每个班让 1 总是返回 WM_MOUSEHWHEEL 通过这些控制处理的邮件。例如,这是Button类:

I've managed to contrive a workaround but I feel sure there must be a better method than this. What I've done is add a class for each type of control used on my form and inheriting from the control. Then I've added a WndProc procedure to each class so that 1 is always returned for WM_MOUSEHWHEEL messages processed by these controls. For example, this is the button class:

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

然后,它是不断变化的,在窗体的设计code引用的只是一个问题。

Then it was just a matter of changing the references in the form's designer code.

正如我说的,我敢肯定,一定有比这更好的方法。这将是痛苦的,如果你不得不这样做对大量不同的控件类的,但对我来说我只需要它的几个基本控制。

As I say, I'm sure there must be a better method than this. It would be painful if you had to do it for a large number of different control classes, but in my case I just needed it for a few basic controls.

我离开这个开放的,希望有人会提出一个更好的解决方案,但没有几天曾经做过,所以我要接受我自己的答案。

I left this open for a few days in the hope that someone would suggest a better solution but nothing has been forthcoming so I'm going to accept my own answer.