Handling Scroll Events of a Panel Control and Other Scrollable Controls

The panel control supports scrolling of its content if the AutoScroll property is set to True. Nevertheless, an event for handling the scroll events is missing. This event can be added to the panel easily by deriving from the System.Windows.Forms.Panel class (or any other scrollable control) and listening for scroll messages in the WndProc method. The code below can be used as a replacement for the .NET Framework’s panel control:

Imports System
Imports System.Windows.Forms

''' <summary>
'''   Extends the panel control by a <c>Scroll</c> event.
''' </summary>
Public Class ScrollPanel
    Inherits Panel

    ''' <summary>
    '''   Occurs when the panel is scrolled.
    ''' </summary>
    ''' <param name="sender">The source of the event.</param>
    ''' <param name="e">
    '''   A <c>ScrollEventArgs</c> that contains the event data.
    ''' </param>
    Public Event Scroll(ByVal sender As Object, ByVal e As ScrollEventArgs)

    Private Const WM_VSCROLL As Int32 = &H115
    Private Const WM_HSCROLL As Int32 = &H114

    ''' <summary>
    '''   Raises the <c>Scroll</c> event.
    ''' </summary>
    ''' <param name="e">
    '''   A <c>ScrollEventArgs</c> that contains the event data.
    ''' </param>
    Protected Sub OnScroll(ByVal e As ScrollEventArgs)
        RaiseEvent Scroll(Me, e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        If m.Msg = WM_HSCROLL Then
            OnScroll(New ScrollEventArgs(ScrollDirection.Horizontal))
        ElseIf m.Msg = WM_VSCROLL Then
            OnScroll(New ScrollEventArgs(ScrollDirection.Vertical))
        End If
        MyBase.WndProc(m)
    End Sub
End Class

''' <summary>
'''   Provides data for the <c>Scroll</c> event.
''' </summary>
Public Class ScrollEventArgs
    Private m_Direction As ScrollDirection

    ''' <summary>
    '''   Creates a new instance of <c>ScrollEventArgs</c>.
    ''' </summary>
    ''' <param name="Direction">
    '''   The initial value of the <c>Direction</c> property.
    ''' </param>
    Public Sub New(ByVal Direction As ScrollDirection)
        Me.Direction = Direction
    End Sub

    ''' <summary>
    '''   Gets or sets the direction the panel has been scrolled to.
    ''' </summary>
    ''' <value>The direction the panel has been scrolled to.</value>
    Public Property Direction() As ScrollDirection
        Get
            Return m_Direction
        End Get
        Set(ByVal Value As ScrollDirection)
            m_Direction = Value
        End Set
    End Property
End Class

''' <summary>
'''   Provides possible scrolling directions.
''' </summary>
Public Enum ScrollDirection

    ''' <summary>
    '''   Horizontal scrolling.
    ''' </summary>
    Horizontal

    ''' <summary>
    '''   Vertical scrolling.
    ''' </summary>
    Vertical
End Enum

ScrollPanel provides a Scroll event that is raised when the panel is scrolled. The event handler receives a ScrollEventArgs object that gives information about the scrolling direction.