Hacer que el desplazamiento horizontal de la inclinación del mouse siempre se repita

Estoy diseñando un formulario con una barra de desplazamiento horizontal anclada en la parte inferior. Quería agregar soporte para el desplazamiento lateral usando los botones de inclinación del mouse y encontré esta solución que, después de un poco de retoques, pareció funcionar, es decir, mientras que el formulario solo tenía gráficos GDI dibujados en su superficie.

Sin embargo, desde entonces he agregado algunos controles al formulario y descubrí que cuando el mouse está sobre cualquiera de de ellos la operación de inclinación solo se activa una vez a la vez en lugar de repetidamente como lo hace cuando el mouse está sobre cualquier otra parte del formulario.

Para ver a lo que me refiero (si tiene un mouse con botones de inclinación), acople una barra de desplazamiento horizontal en la parte inferior de un formulario, agregue algunos otros controles y pegue este código:

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

Verá que el desplazamiento lateral se repite cuando el mouse está sobre una parte en blanco del formulario, pero solo "una vez" cuando está sobre un control.

Supongo que la solución se encuentra en algún lugar del mensaje. .Result valor, pero estoy perdido en cuanto a lo que debería ser. De hecho, ni siquiera estoy seguro de estar devolviendo un valor correcto de todos modos porque el código en la solución original generó una excepción a la función DirectCast, así que cambié eso por CType, que parecía funcionar bien. Intenté resolverlo usando Spy ++ pero no puedo ver nada obvio.

Alguna idea por favor?


ACTUALIZACIÓN

He notado que cuando incluyo ventanas 'Niño' en Spy++ hay dos mensajes (0x020E) y dos valores de retorno, 1 y luego 0. Supongo que el formulario pasa el mensaje al control. Así que supongo que la pregunta ahora es: ¿se puede evitar que el mensaje pase al control? ¿O se puede interceptar el valor de retorno del control y convertirlo en 1?

preguntado el 12 de junio de 12 a las 16:06

por lo general, en un comportamiento como ese, el control intercepta el evento del mouse y nunca llega al formulario que contiene y controla la barra de desplazamiento. De hecho, me sorprende que incluso un evento haya llegado al formulario. Es posible que deba conectarse a las DLL del sistema para lograr esto.... -

@SASS_Shooter Pensé que WndProc recibió todos las los mensajes destinados a un formulario y sus controles. He estado jugando un poco más con Spy ++ y si incluyo ventanas 'Niño', está claro que el mensaje se pasa al control que devuelve 0. Entonces, la pregunta es, ¿se puede evitar que el mensaje se pase al control o los controles devuelven el valor interceptado y convertido a 1? -

1 Respuestas

Me las arreglé para idear una solución, pero estoy seguro de que debe haber un método mejor que este. Lo que hice fue agregar una clase para cada tipo de control usado en mi formulario y heredado del control. Luego agregué un procedimiento WndProc a cada clase para que 1 siempre se devuelve por WM_MOUSEHWHEEL mensajes procesados ​​por estos controles. Por ejemplo, esta es la clase de botón:

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

Luego solo era cuestión de cambiar las referencias en el código del diseñador del formulario.

Como digo, estoy seguro de que debe haber un método mejor que este. Sería doloroso si tuviera que hacerlo para una gran cantidad de clases de control diferentes, pero en mi caso solo lo necesitaba para algunos controles básicos.


Dejé esto abierto durante unos días con la esperanza de que alguien sugiriera una solución mejor, pero no ha aparecido nada, así que aceptaré mi propia respuesta.

Respondido el 19 de junio de 12 a las 13:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.