?
Solved

Movable Tabs on Tabcontrol

Posted on 2014-11-03
4
Medium Priority
?
138 Views
Last Modified: 2014-12-19
Visual Studio 2013 VB.NET

I have a tab control on a windows form (vb.net) that i would like to allow users to change the order by dragging. Is this possible?
0
Comment
Question by:mickeyshelley1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 40
ID: 40420829
The TabPage the necessary method (DoDragDrop) and events (DragDrop), so it is possible.

Unfortunately, I do not have any code to show you. I never did it, and it can involve quite a few lines.

Look at the documentation for the DoDragDrop method, that shows the whole thing on both sides (start the drag and control the drop) between 2 ListBoxes. You would need something similar to insert a TabPage between 2 other TabPages.
0
 
LVL 34

Accepted Solution

by:
Mike Eghtebas earned 2000 total points
ID: 40420846
tabs
I made this tab control, with two tabs. Then with mouse down, I dragged left or right. and then I let it go:

 mouse down used to capture the initial x value using:
Public Class Form1

    Dim Xinitial As Int32
    Dim Xfinal As Int32

    Private Sub TabPage2_MouseClick(sender As Object, e As MouseEventArgs) Handles TabPage2.MouseClick
        Xinitial = e.X
    End Sub

let it go helped to find final value of x:
    Private Sub TabPage2_MouseUp(sender As Object, e As MouseEventArgs) Handles TabPage2.MouseUp
        Xfinal = e.X

       'determined the user dragged to left or right:
        If Xfinal > Xfinal Then
            changeTabIndex("TabPage2", 1) ' to the right
        Else
            changeTabIndex("TabPage2", -1) ' to the left
        End If

    End Sub

This function could be further developed to re-index the refresh the form to rearrange the tabs:
    Private Sub changeTabIndex(TabName As String, intVal As Int32)
        Dim intNewIndex As Int32

       ' intNewIndex = TabControl1.SelectedIndex + intVal

        'TabControl1.SelectedIndex = intNewIndex

    End Sub

End Class

This is what I have done so far. I stopped to search if there is easier way of doing this so I don't have to re-invent the wheel.

Please the mouse-down and up on the tab area will respond to these events. They will not respond to if you work on tab on the top row.
0
 
LVL 28

Expert Comment

by:Ark
ID: 40420974
Public Class DraggableTabControl
    Inherits TabControl

    Private _srcPage As TabPage

    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
        If (e.Button = MouseButtons.Left) AndAlso (SelectedTab IsNot Nothing) AndAlso (Not GetTabRect(SelectedIndex).IsEmpty) Then
            _srcPage = SelectedTab
        End If
        MyBase.OnMouseDown(e)
    End Sub

    Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
        If (e.Button = MouseButtons.Left) AndAlso (_srcPage IsNot Nothing) Then
            Me.Cursor = If(TabPageFromPoint(e.Location) Is Nothing, Cursors.No, Cursors.VSplit)
        Else
            Me.Cursor = Cursors.Default
        End If
        MyBase.OnMouseMove(e)
    End Sub

    Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
        SwapPages(_srcPage, TabPageFromPoint(e.Location))
        Me.SelectedTab = _srcPage
        _srcPage = Nothing
        MyBase.Cursor = Cursors.Default
        MyBase.OnMouseUp(e)
    End Sub

    Private Function TabPageFromPoint(ByVal pt As Point) As TabPage
        For i As Integer = 0 To TabPages.Count - 1
            If GetTabRect(i).Contains(pt) Then Return TabPages(i)
        Next
        Return Nothing
    End Function

    Private Sub SwapPages(ByVal a As TabPage, ByVal b As TabPage)
        If a Is Nothing OrElse b Is Nothing OrElse a.Equals(b) Then Return
        Dim i = TabPages.IndexOf(a), j = TabPages.IndexOf(b)
        TabPages(i) = b : TabPages(j) = a
    End Sub
End Class

Open in new window

0
 
LVL 28

Expert Comment

by:Ark
ID: 40421019
PS. Another approach - using drag'n'drop:
Public Class DraggableTabControl
    Inherits TabControl

    Public Sub New()
        MyBase.New()
        MyBase.AllowDrop = True
    End Sub
    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
        If (e.Button = MouseButtons.Left) AndAlso (SelectedTab IsNot Nothing) AndAlso (Not GetTabRect(SelectedIndex).IsEmpty) Then
            DoDragDrop(SelectedTab, DragDropEffects.All)
        End If
        MyBase.OnMouseDown(e)
    End Sub

    Private Sub DraggableTabControl_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragDrop
        If e.Data.GetDataPresent(GetType(TabPage)) Then
            Dim target = TabPageFromPoint(Me.PointToClient(New Point(e.X, e.Y)))
            Dim srcPage = e.Data.GetData(GetType(TabPage))
            SwapPages(srcPage, target)
            Me.SelectedTab = srcPage
        End If
    End Sub

    Private Sub DraggableTabControl_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Me.DragOver
        If e.Data.GetDataPresent(GetType(TabPage)) Then
            Dim target = TabPageFromPoint(Me.PointToClient(New Point(e.X, e.Y)))
            Dim srcPage = e.Data.GetData(GetType(TabPage))
            If target Is Nothing OrElse target.Equals(srcPage) Then
                e.Effect = DragDropEffects.None
            Else
                e.Effect = DragDropEffects.Move
            End If
        End If
    End Sub

    Private Function TabPageFromPoint(ByVal pt As Point) As TabPage
        For i As Integer = 0 To MyBase.TabPages.Count - 1
            If GetTabRect(i).Contains(pt) Then Return TabPages(i)
        Next
        Return Nothing
    End Function

    Private Sub SwapPages(ByVal a As TabPage, ByVal b As TabPage)
        If a Is Nothing OrElse b Is Nothing OrElse a.Equals(b) Then Return
        Dim i = TabPages.IndexOf(a), j = TabPages.IndexOf(b)
        TabPages(i) = b : TabPages(j) = a
    End Sub

End Class

Open in new window

0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses
Course of the Month14 days, 20 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question