Drag and detach tabpages

2019-08-06 13:44发布

I have several tabpages on a single tab control and I was wondering if anyone out there knows how I can program a way to drag tabpages off the tab control and into their own "form"....pulling the tabcontrol apart?

I'm using vb.net and did find many ways to move the order of tabpages on the tabcontrol but non om how to actually detach the tabpage and place \ drag it elsewhere on the screen?

2条回答
ら.Afraid
2楼-- · 2019-08-06 13:49

Assuming WinForms, essentially you have to create a new Form and a new TabControl to house the TabPage you plan on moving.

In its simplest form:

Private Sub TabControl1_MouseMove(sender As Object, e As MouseEventArgs) Handles TabControl1.MouseMove
  If (e.Button = MouseButtons.Left) Then
    TabControl1.DoDragDrop(TabControl1.SelectedTab, DragDropEffects.Move)
  End If
End Sub

Private Sub TabControl1_GiveFeedback(sender As Object, e As GiveFeedbackEventArgs) Handles TabControl1.GiveFeedback
  e.UseDefaultCursors = False
End Sub

Private Sub TabControl1_QueryContinueDrag(sender As Object, e As QueryContinueDragEventArgs) Handles TabControl1.QueryContinueDrag
  If Control.MouseButtons <> MouseButtons.Left Then
    e.Action = DragAction.Cancel
    Dim f As New Form
    f.Size = New Size(400, 300)
    f.StartPosition = FormStartPosition.Manual
    f.Location = MousePosition
    Dim tc As New TabControl
    tc.Dock = DockStyle.Fill
    tc.TabPages.Add(TabControl1.SelectedTab)
    f.Controls.Add(tc)
    f.Show()
    Me.Cursor = Cursors.Default
  Else
    e.Action = DragAction.Continue
    Me.Cursor = Cursors.Help
  End If
End Sub
查看更多
走好不送
3楼-- · 2019-08-06 14:14

Here I'd like to submit my personal improvement based on LarsTech's code. This version allows the tab to go back to its original parent when the form closes and requires the user to drag the tab away by a defined offset of pixel before the drag event is triggered.

Dim pTabControlClickStartPosition As Point
Dim iTabControlFlyOffPixelOffset As Integer = 20

Private Sub TabControlMain_MouseDown(sender As Object, e As MouseEventArgs) Handles TabControlMain.MouseDown
    If (e.Button = MouseButtons.Left) Then
        pTabControlClickStartPosition = e.Location
    End If
End Sub

Private Sub TabControlMain_MouseMove(sender As Object, e As MouseEventArgs) Handles TabControlMain.MouseMove
    If (e.Button = MouseButtons.Left) Then
        Dim iMouseOffset_X = pTabControlClickStartPosition.X - e.X
        Dim iMouseOffset_Y = pTabControlClickStartPosition.Y - e.Y

        If iMouseOffset_X > iTabControlFlyOffPixelOffset Or iMouseOffset_Y > iTabControlFlyOffPixelOffset Then
            TabControlMain.DoDragDrop(TabControlMain.SelectedTab, DragDropEffects.Move)
            pTabControlClickStartPosition = New Point
        End If
    Else
        pTabControlClickStartPosition = New Point
    End If
End Sub

Private Sub TabControlMain_GiveFeedback(sender As Object, e As GiveFeedbackEventArgs) Handles TabControlMain.GiveFeedback
    e.UseDefaultCursors = False
End Sub

Private Sub TabControlMain_QueryContinueDrag(sender As Object, e As QueryContinueDragEventArgs) Handles TabControlMain.QueryContinueDrag
    If Control.MouseButtons <> MouseButtons.Left Then
        e.Action = DragAction.Cancel
        Dim f As New Form
        f.Size = New Size(800, 400)
        f.StartPosition = FormStartPosition.Manual
        f.Location = MousePosition
        Dim tc As New TabControl
        tc.Dock = DockStyle.Fill
        tc.TabPages.Add(TabControlMain.SelectedTab)
        f.Controls.Add(tc)
        AddHandler f.FormClosing, Sub(sender1 As Object, e1 As EventArgs)
                                      TabControlMain.TabPages.Add(tc.SelectedTab)
                                  End Sub
        f.Show()
        Me.Cursor = Cursors.Default
    Else
        e.Action = DragAction.Continue
        Me.Cursor = Cursors.SizeAll
    End If
End Sub

UPDATE: As pointed out in the comments, when the child form is closed, the TabPage is put back in the original TabControl but not in the previous order.

To avoid this behaviour we can assign a priority to the TabPages using the Tag property.

Let's assume we have three TabPages in our TabControl in the order: "Tab C", "Tab A", Tab B". Now we have to set TabA.Tag = 2, TabB.Tag = 3, TabC.Tag = 1.

Then change f.FormClosing code into this:

'Get the first TabPage with a greater Tag value than the one being inserted.
Dim followingTab = TabControlMain.TabPages.Cast(Of TabPage)().FirstOrDefault(Function(tp) CInt(tp.Tag) > CInt(tc.SelectedTab.Tag))

If followingTab Is Nothing Then
    'There is no following tab so add this one to the end.
    TabControlMain.TabPages.Add(tc.SelectedTab)
Else
    'Insert this tab before the following one.
TabControlMain.TabPages.Insert(TabControlMain.TabPages.IndexOf(followingTab), tc.SelectedTab)
    End If

Source: http://www.vbforums.com/showthread.php?766367-Tabpage-Add-or-insert-tabpage-with-order-determined&s=1b895ca4d79ab29e7c00c4b07a4ce142&p=4692139&viewfull=1#post4692139

查看更多
登录 后发表回答