//Except where stated all code and programs in this project are the copyright of Jim Blackler, 2008. //jimblackler@gmail.com // //This is free software. Libraries and programs are distributed under the terms of the GNU Lesser //General Public License. Please see the files COPYING and COPYING.LESSER. using System; using System.Drawing; using System.Windows.Forms; namespace MiscControls { /// /// A tab control in which the user can re-order the tabs by dragging the mouse /// public partial class ReorderableTabControl : TabControl { /// /// Make a reorderable tab control /// public ReorderableTabControl() { InitializeComponent(); } bool dragging = false; TabPage lastDraggedTabPage; private void ReorderableTabControl_MouseDown(object sender, MouseEventArgs e) { if ((e.Button & MouseButtons.Left) != 0) { dragging = true; lastDraggedTabPage = null; } } private void ReorderableTabControl_MouseMove(object sender, MouseEventArgs e) { if (!dragging) return; // user does not have button held down TabPage overTabPage = null; int overTabPageIdx = -1; int selectedIndex = TabPages.IndexOf(SelectedTab); Rectangle selectedRect = GetTabRect(selectedIndex); // Find the tab page that the mouse is over int index = 0; foreach (TabPage scanTabPage in TabPages) { Rectangle rect = GetTabRect(index); if (selectedRect.Width < rect.Width) { // Lessen the strange 'over shifting' effect of moving a small tab over // a larger one int newWidth = (selectedRect.Width + rect.Width) / 2; // Real hot spot width is average of two tab sizes if (rect.X > selectedRect.X) // moving right on the tab display { rect.X += rect.Width - newWidth; } rect.Width = newWidth; } if (rect.Contains(PointToClient(MousePosition))) { overTabPage = scanTabPage; overTabPageIdx = index; break; } index++; } if (overTabPage == lastDraggedTabPage) return; if (overTabPage == null) return; // not over a tab page if (SelectedTab == overTabPage) return; // still over original tab page .. nothing to do SuspendLayout(); // Revised method from section commented out below TabPages[overTabPageIdx] = SelectedTab; TabPages[selectedIndex] = overTabPage; SelectedIndex = overTabPageIdx; // Simply swap the tab pages (this works because they are adjacent) //TabPages.Remove(overTabPage); //TabPages.Insert(selectedIndex, overTabPage); ResumeLayout(); } /// /// The user has lifted the button - stop dragging /// private void ReorderableTabControl_MouseUp(object sender, MouseEventArgs e) { dragging = false; } } }