Imports System.Windows.Forms
Imports Mercury.Mobile.Forms.Win32

''' <summary>
''' An extended version of the <see cref="System.Windows.Forms.VScrollBar"/> control.
''' </summary>
''' <remarks></remarks>
Public Class VScrollBarEx
    Inherits VScrollBar

    ''' <summary>
    ''' Initializes a default instance of the <see cref="Mercury.Mobile.Forms.VScrollBarEx"/> class.
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        Me.New(Nothing)
    End Sub

    ''' <summary>
    ''' Initializes a new instance of the <see cref="Mercury.Mobile.Forms.VScrollBarEx"/> 
    ''' class from the specified VScrollBar.
    ''' </summary>
    ''' <param name="fromScroll">The scrollbar from which to derive.</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal fromScroll As VScrollBar)
        If fromScroll IsNot Nothing Then
            Me.Anchor = fromScroll.Anchor
            Me.BindingContext = fromScroll.BindingContext
            Me.Bounds = fromScroll.Bounds
            Me.ClientSize = fromScroll.ClientSize
            Me.Dock = fromScroll.Dock
            Me.LargeChange = fromScroll.LargeChange
            Me.SmallChange = fromScroll.SmallChange
            Me.Location = fromScroll.Location
            Me.Maximum = fromScroll.Maximum
            Me.Minimum = fromScroll.Minimum
            Me.Parent = fromScroll.Parent
            Me.Size = fromScroll.Size
            For Each bnd In fromScroll.DataBindings
                Me.DataBindings.Add(bnd)
            Next
        End If
        WindowHook.Hook(Me, AddressOf InternalWndProc)
    End Sub

    Private _scrolling As Boolean
    Private _deferredScrolling As Boolean

    ''' <summary>
    ''' Notifies the user that a scroll event has ended.
    ''' </summary>
    Public Event ScrollCompleted(ByVal sender As Object, ByVal e As EventArgs)

    ''' <summary>
    ''' Determines whether to enable deferred scrolling in this data grid.
    ''' </summary>
    ''' <returns>True if deferred scrolling is enabled; otherwise, false.</returns>
    ''' <remarks></remarks>
    Public Property DeferredScrolling() As Boolean
        Get
            Return Me._deferredScrolling
        End Get
        Set(ByVal value As Boolean)
            Me._deferredScrolling = value
        End Set
    End Property

    Private Function InternalWndProc(ByVal hWnd As IntPtr, ByVal msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer, ByRef handled As Boolean) As Integer
        handled = False
        Dim message = CType(msg, WM)
        If message = WM.LBUTTONDOWN Then
            Me._scrolling = True
        ElseIf message = WM.LBUTTONUP Then
            Me._scrolling = False
            If Me.DeferredScrolling Then _
                Me.CompleteScrollInternal()
        End If
    End Function

    Private Sub CompleteScrollInternal()
        Me.OnValueChanged(EventArgs.Empty)
        Me.OnScrollCompleted(EventArgs.Empty)
    End Sub

    Protected Overridable Sub OnScrollCompleted(ByVal e As EventArgs)
        RaiseEvent ScrollCompleted(Me, e)
    End Sub

    Protected Overrides Sub OnValueChanged(ByVal e As System.EventArgs)
        If Me.DeferredScrolling AndAlso Me._scrolling Then _
            Return
        MyBase.OnValueChanged(e)
    End Sub

    Private disposedValue As Boolean

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        ' Dispose
        If Not (Me.disposedValue) Then
            Try
                WindowHook.Unhook(Me)
            Catch
            End Try
        End If
        Me.disposedValue = True
        MyBase.Dispose(disposing)
    End Sub

End Class