Public Class OrderedTabControl
Inherits TabControl
'//fields
Private draggingTab As TabPage = Nothing
'//methods
Protected Overrides Sub OnDragOver(ByVal drgevent As _
DragEventArgs)
MyBase.OnDragOver(drgevent)
drgevent.Effect = DragDropEffects.Move
End Sub
Protected Overrides Sub OnQueryContinueDrag(ByVal e As _
QueryContinueDragEventArgs)
MyBase.OnQueryContinueDrag(e)
If Me.draggingTab IsNot Nothing Then
Dim raiseMouse = False
Dim pt = Me.PointToClient(Control.MousePosition)
Dim startTab = Me.GetTabRect(Me.TabPages.IndexOf(Me.draggingTab)) _
.Contains(pt)
Dim otherTab = Me.GetRectangles().Any(Function(r) r.Contains(pt))
Dim leftButton = Control.MouseButtons.Equals(MouseButtons.Left)
Dim mouseArgs = New MouseEventArgs(Windows.Forms.MouseButtons.Left, _
1, pt.X, pt.Y, 0)
If Not leftButton AndAlso Not otherTab Then
'//mouse let go outside of draggable area
e.Action = DragAction.Cancel
raiseMouse = True
ElseIf Not leftButton AndAlso otherTab AndAlso Not startTab Then
'//mouse let go in allowable area
e.Action = DragAction.Drop
raiseMouse = True
ElseIf Not leftButton AndAlso startTab Then
'//mouse let go in rectangle that it started from, cancel drag
e.Action = DragAction.Cancel
raiseMouse = True
Else
'//anything else can continue
e.Action = DragAction.Continue
End If
If raiseMouse Then
Me.OnMouseClick(mouseArgs)
Me.OnMouseUp(mouseArgs)
End If
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As _
MouseEventArgs)
MyBase.OnMouseDown(e)
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim pt = New Point(e.X, e.Y)
Dim tp = Me.GetTabFromPoint(pt)
If tp IsNot Nothing Then
Me.draggingTab = tp
Me.DoDragDrop(tp, DragDropEffects.Move)
End If
End If
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As _
MouseEventArgs)
MyBase.OnMouseUp(e)
End Sub
Protected Overrides Sub OnMouseClick(ByVal e As _
MouseEventArgs)
MyBase.OnMouseClick(e)
End Sub
'//methods
Private Function GetRectangles() As IEnumerable(Of Rectangle)
Return Me.TabPages.Cast(Of TabPage)() _
.Select(Function(t, i) Me.GetTabRect(i))
End Function
Private Function GetTabFromPoint(ByVal pt As Point) As TabPage
Return Me.GetTabFromPoint(pt.X, pt.Y)
End Function
Private Function GetTabFromPoint(ByVal x As Integer, _
ByVal y As Integer) As TabPage
For i = 0 To Me.TabCount - 1
If Me.GetTabRect(i).Contains(x, y) Then
Return Me.TabPages(i)
End If
Next
Return Nothing
End Function
End Class