2010-12-04 45 views

Répondre

9

Bien sûr, c'est possible! Vous essayez probablement de trop compliquer la solution. Essentiellement, tout ce que vous avez à faire est de sous-classer le standard TabControl et d'ajouter de la logique aux gestionnaires d'événements de la souris. Vous devrez juste vérifier le formulaire que l'utilisateur est en train de faire glisser et le réorganiser dans la collection TabPages.

Il y a quelques solutions complètes disponibles en ligne:

1

TabPages de remise en ordre par glisser-déposer-par Ludwig B.
inspiré par http://dotnetrix.co.uk/tabcontrol.htm#tip7

 private void tc_MouseDown(object sender, MouseEventArgs e) 
     { 
      // store clicked tab 
      TabControl tc = (TabControl)sender; 
      int hover_index = this.getHoverTabIndex(tc); 
      if (hover_index >= 0) { tc.Tag = tc.TabPages[hover_index]; } 
     } 
     private void tc_MouseUp(object sender, MouseEventArgs e) 
     { 
      // clear stored tab 
      TabControl tc = (TabControl)sender; 
      tc.Tag = null; 
     } 
     private void tc_MouseMove(object sender, MouseEventArgs e) 
     {   
      // mouse button down? tab was clicked? 
      TabControl tc = (TabControl)sender; 
      if ((e.Button != MouseButtons.Left) || (tc.Tag == null)) return; 
      TabPage clickedTab = (TabPage)tc.Tag; 
      int clicked_index = tc.TabPages.IndexOf(clickedTab); 

      // start drag n drop 
      tc.DoDragDrop(clickedTab, DragDropEffects.All); 
     } 
     private void tc_DragOver(object sender, DragEventArgs e) 
     { 
      TabControl tc = (TabControl)sender; 

      // a tab is draged? 
      if (e.Data.GetData(typeof(TabPage)) == null) return; 
      TabPage dragTab = (TabPage)e.Data.GetData(typeof(TabPage)); 
      int dragTab_index = tc.TabPages.IndexOf(dragTab); 

      // hover over a tab? 
      int hoverTab_index = this.getHoverTabIndex(tc); 
      if (hoverTab_index < 0) { e.Effect = DragDropEffects.None; return; } 
      TabPage hoverTab = tc.TabPages[hoverTab_index]; 
      e.Effect = DragDropEffects.Move; 

      // start of drag? 
      if (dragTab == hoverTab) return; 

      // swap dragTab & hoverTab - avoids toggeling 
      Rectangle dragTabRect = tc.GetTabRect(dragTab_index); 
      Rectangle hoverTabRect = tc.GetTabRect(hoverTab_index); 

      if (dragTabRect.Width < hoverTabRect.Width) 
      { 
       Point tcLocation = tc.PointToScreen(tc.Location); 

       if (dragTab_index < hoverTab_index) 
       { 
        if ((e.X - tcLocation.X) > ((hoverTabRect.X + hoverTabRect.Width) - dragTabRect.Width)) 
         this.swapTabPages(tc, dragTab, hoverTab); 
       } 
       else if (dragTab_index > hoverTab_index) 
       { 
        if ((e.X - tcLocation.X) < (hoverTabRect.X + dragTabRect.Width)) 
         this.swapTabPages(tc, dragTab, hoverTab); 
       } 
      } 
      else this.swapTabPages(tc, dragTab, hoverTab); 

      // select new pos of dragTab 
      tc.SelectedIndex = tc.TabPages.IndexOf(dragTab); 
     } 

     private int getHoverTabIndex(TabControl tc) 
     { 
      for (int i = 0; i < tc.TabPages.Count; i++) 
      { 
       if (tc.GetTabRect(i).Contains(tc.PointToClient(Cursor.Position))) 
        return i; 
      } 

      return -1; 
     } 

     private void swapTabPages(TabControl tc, TabPage src, TabPage dst) 
     { 
      int index_src = tc.TabPages.IndexOf(src); 
      int index_dst = tc.TabPages.IndexOf(dst); 
      tc.TabPages[index_dst] = src; 
      tc.TabPages[index_src] = dst; 
      tc.Refresh(); 
     } 
+1

Oui, j'ai déjà lié à ce même échantillon dans ma réponse. Il y a plusieurs mois. –

6

J'ai trouvé le solution Posté par @Cody gris pour être la plupart du temps ce que je voulais, mais je ne vois pas la nécessité pour qu'il soit si compliqué.

C'est ma simplification, mis en œuvre en dérivant de TabControl:

public class DraggableTabControl : TabControl 
{ 
    private TabPage m_DraggedTab; 

    public DraggableTabControl() 
    { 
     MouseDown += OnMouseDown; 
     MouseMove += OnMouseMove; 
    } 

    private void OnMouseDown(object sender, MouseEventArgs e) 
    { 
     m_DraggedTab = TabAt(e.Location); 
    } 

    private void OnMouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.Button != MouseButtons.Left || m_DraggedTab == null) 
     { 
      return; 
     } 

     TabPage tab = TabAt(e.Location); 

     if (tab == null || tab == m_DraggedTab) 
     { 
      return; 
     } 

     Swap(m_DraggedTab, tab); 
     SelectedTab = m_DraggedTab; 
    } 

    private TabPage TabAt(Point position) 
    { 
     int count = TabCount; 

     for (int i = 0; i < count; i++) 
     { 
      if (GetTabRect(i).Contains(position)) 
      { 
       return TabPages[i]; 
      } 
     } 

     return null; 
    } 

    private void Swap(TabPage a, TabPage b) 
    { 
     int i = TabPages.IndexOf(a); 
     int j = TabPages.IndexOf(b); 
     TabPages[i] = b; 
     TabPages[j] = a; 
    } 
} 

Les API de glisser-déposer sont vraiment destinés à traîner des choses entre des applications distinctes, ou à tout le moins, des contrôles séparés. Les utiliser dans ce cas est exagéré.

Assurez-vous que la réponse de Cody a été également mise en doute si vous faites la mienne, car elle est basée sur la sienne.

+0

Beau travail! C'est une solution vraiment simple. –

1

J'ai étendu un peu la réponse de Jacob Stanley. De cette façon, l'échange ne se produira pas trop souvent. Ceci est particulièrement utile pour les onglets de différentes tailles, auquel cas la solution précédente changerait très souvent en faisant glisser. La différence dans l'expérience utilisateur est que vous devez faire glisser un peu plus loin pour déplacer réellement la languette. Mais ceci est similaire au réordonnancement des onglets dans les navigateurs.

J'ai également ajouté un curseur de la main tout en faisant glisser et activé le double-tampon.

using System; 
using System.Drawing; 
using System.Windows.Forms; 

namespace Controls 
{ 
    public class DraggableTabControl : TabControl 
    { 
     private TabPage draggedTab; 

     public DraggableTabControl() 
     { 
      this.MouseDown += OnMouseDown; 
      this.MouseMove += OnMouseMove; 
      this.Leave += new System.EventHandler(this.DraggableTabControl_Leave); 

      this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 
     } 

     private void OnMouseDown(object sender, MouseEventArgs e) 
     { 
      draggedTab = TabAt(e.Location); 
     } 

     private void OnMouseMove(object sender, MouseEventArgs e) 
     { 
      if (e.Button != MouseButtons.Left || draggedTab == null) 
      { 
       this.Cursor = this.DefaultCursor; 
       draggedTab = null; 
       return; 
      } 

      int index = TabPages.IndexOf(draggedTab);   
      int nextIndex = index + 1; 
      int prevIndex = index - 1; 

      int minXForNext = int.MaxValue; 
      int maxXForPrev = int.MinValue; 

      var tabRect = GetTabRect(index); 

      if (nextIndex < TabPages.Count) 
      { 
       var nextTabRect = GetTabRect(nextIndex); 
       minXForNext = tabRect.Left + nextTabRect.Width; 
      } 

      if (prevIndex >= 0) 
      { 
       var prevTabRect = GetTabRect(prevIndex); 
       maxXForPrev = prevTabRect.Left + tabRect.Width; 
      } 

      this.Cursor = Cursors.Hand; 

      if (e.Location.X > maxXForPrev && e.Location.X < minXForNext) 
      { 
       return; 
      } 

      TabPage tab = TabAt(e.Location); 

      if (tab == null || tab == draggedTab) 
      { 
       return; 
      } 

      Swap(draggedTab, tab); 
      SelectedTab = draggedTab; 
     } 

     private TabPage TabAt(Point position) 
     { 
      int count = TabCount; 

      for (int i = 0; i < count; i++) 
      { 
       if (GetTabRect(i).Contains(position)) 
       { 
        return TabPages[i]; 
       } 
      } 

      return null; 
     } 

     private void Swap(TabPage a, TabPage b) 
     { 
      int i = TabPages.IndexOf(a); 
      int j = TabPages.IndexOf(b); 

      TabPages[i] = b; 
      TabPages[j] = a; 
     } 

     private void DraggableTabControl_Leave(object sender, EventArgs e) 
     { 
      this.Cursor = this.DefaultCursor; 
      draggedTab = null; 
     } 
    } 
}