Public Class listboxEx
Inherits ListBox
Private Const WM_PAINT As Integer = &HF
Private Const WM_MOUSEMOVE = &H200
' The Item being dragged
Private _itemDnD As Object = Nothing
Private itemOver As Integer = -1
Public Sub New()
' Reduce flicker
MyBase.DoubleBuffered = True
End Sub
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
If m.Msg = WM_MOUSEMOVE And _itemDnD IsNot Nothing OrElse m.Msg = WM_PAINT Then
If itemOver >= 0 AndAlso itemOver < Items.Count Then
Dim rc As Rectangle = New Rectangle(0, MyBase.GetItemRectangle(itemOver).Top, MyBase.GetItemRectangle(itemOver).Width, MyBase.GetItemHeight(0))
DrawInsertionLine(rc.Left, rc.Right, rc.Top)
End If
End If
End Sub
''' <summary>
''' Draw a line with insertion marks at each end
''' </summary>
''' <param name="X1">Starting position (X) of the line</param>
''' <param name="X2">Ending position (X) of the line</param>
''' <param name="Y">Position (Y) of the line</param>
Private Sub DrawInsertionLine(ByVal X1 As Integer, ByVal X2 As Integer, ByVal Y As Integer)
Using g As Graphics = MyBase.CreateGraphics()
g.DrawLine(Pens.Red, X1, Y, X2 - 1, Y)
Dim leftTriangle As Point() = New Point(2) {New Point(X1, Y - 4), New Point(X1 + 7, Y), New Point(X1, Y + 4)}
Dim rightTriangle As Point() = New Point(2) {New Point(X2, Y - 4), New Point(X2 - 8, Y), New Point(X2, Y + 4)}
g.FillPolygon(Brushes.Red, leftTriangle)
g.FillPolygon(Brushes.Red, rightTriangle)
End Using
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseDown(e)
_itemDnD = MyBase.Items(MyBase.IndexFromPoint(New Point(e.X, e.Y)))
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseMove(e)
If _itemDnD Is Nothing Then
Return
End If
' Show the user that a drag operation is happening
Cursor = Cursors.Hand
' use 0 instead of e.X so that you don't have to keep inside the columns while dragging
itemOver = MyBase.IndexFromPoint(New Point(0, e.Y))
' invalidate the listbox
MyBase.Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseUp(e)
If _itemDnD Is Nothing Then
Return
End If
Try
' use 0 instead of e.X so that you don't have to keep inside the columns while dragging
itemOver = MyBase.IndexFromPoint(New Point(0, e.Y))
If itemOver = -1 Then
Return
End If
If _itemDnD IsNot MyBase.Items(itemOver) Then
MyBase.Items.Remove(_itemDnD)
MyBase.Items.Insert(itemOver, _itemDnD)
End If
MyBase.SelectedIndex = itemOver
MyBase.Invalidate()
Finally
' finish drag&drop operation
_itemDnD = Nothing
Cursor = Cursors.Default
End Try
End Sub
End Class