Сделать так, чтобы горизонтальная прокрутка с наклоном мыши всегда повторялась

Я разрабатываю форму с горизонтальной полосой прокрутки, закрепленной внизу. Я хотел добавить поддержку боковой прокрутки с помощью кнопок наклона мыши и нашел это решение, которое , после небольшой переделки, похоже, справился с задачей — то есть форма имела только графику 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?


person Antagony    schedule 12.06.2012    source источник
comment
обычно при таком поведении элемент управления перехватывает событие мыши и никогда не достигает формы, которая удерживает полосу прокрутки и управляет ею. На самом деле, я удивлен, что даже одно событие попало в форму. Возможно, вам придется подключиться к системным DLL, чтобы выполнить это....   -  person SASS_Shooter    schedule 12.06.2012
comment
@SASS_Shooter Я думал, что WndProc получил все сообщения, предназначенные для формы и ее элементов управления. Я немного поиграл со Spy++, и если я включу «дочерние» окна, станет ясно, что сообщение передается элементу управления, который возвращает 0. Итак, вопрос в том, можно ли предотвратить передачу сообщения в управление или возвращаемое значение управления перехвачено и преобразовано в 1?   -  person Antagony    schedule 13.06.2012


Ответы (1)


Мне удалось придумать обходной путь, но я уверен, что должен быть лучший метод, чем этот. Что я сделал, так это добавил класс для каждого типа элемента управления, используемого в моей форме и наследующего элемент управления. Затем я добавил процедуру WndProc в каждый класс, чтобы 1 всегда возвращалось для WM_MOUSEHWHEEL сообщений, обработанных этими элементами управления. Например, это класс кнопки:

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

Тогда это был просто вопрос изменения ссылок в коде дизайнера формы.

Как я уже сказал, я уверен, что должен быть лучший метод, чем этот. Было бы болезненно, если бы вам пришлось делать это для большого количества различных классов элементов управления, но в моем случае мне это нужно было только для нескольких основных элементов управления.


Я оставил это открытым на несколько дней в надежде, что кто-то предложит лучшее решение, но ничего не последовало, поэтому я собираюсь принять свой собственный ответ.

person Antagony    schedule 15.06.2012