我想让用户通过拖放重新排列 TabPages 顺序。此外,让用户能够将 TabPages 从一个 TabControl 拖到另一个 TabControl 会很酷。就像在 Firefox 和 Total Commander 中一样。如何做到这一点?
问问题
10126 次
3 回答
10
通过拖放重新排序 TabPages - Ludwig B.
灵感来自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();
}
于 2011-05-19T22:59:38.247 回答
6
基于onx23的回答。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Utilities.Windows.Forms
{
public class DraggableTabControl : TabControl
{
private TabPage predraggedTab;
public DraggableTabControl() {
this.AllowDrop = true;
}
protected override void OnMouseDown(MouseEventArgs e) {
predraggedTab = getPointedTab();
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e) {
predraggedTab = null;
base.OnMouseUp(e);
}
protected override void OnMouseMove(MouseEventArgs e) {
if(e.Button == MouseButtons.Left && predraggedTab != null)
this.DoDragDrop(predraggedTab, DragDropEffects.Move);
base.OnMouseMove(e);
}
protected override void OnDragOver(DragEventArgs drgevent) {
TabPage draggedTab = (TabPage) drgevent.Data.GetData(typeof(TabPage));
TabPage pointedTab = getPointedTab();
if(draggedTab == predraggedTab && pointedTab != null) {
drgevent.Effect = DragDropEffects.Move;
if(pointedTab != draggedTab)
swapTabPages(draggedTab, pointedTab);
}
base.OnDragOver(drgevent);
}
private TabPage getPointedTab() {
for(int i=0; i<this.TabPages.Count; i++)
if(this.GetTabRect(i).Contains(this.PointToClient(Cursor.Position)))
return this.TabPages[i];
return null;
}
private void swapTabPages(TabPage src, TabPage dst) {
int srci = this.TabPages.IndexOf(src);
int dsti = this.TabPages.IndexOf(dst);
this.TabPages[dsti] = src;
this.TabPages[srci] = dst;
if(this.SelectedIndex == srci)
this.SelectedIndex = dsti;
else if(this.SelectedIndex == dsti)
this.SelectedIndex = srci;
this.Refresh();
}
}
}
(请原谅我发布死灵。)
更新
我编写了一个允许拖动和关闭选项卡(可配置)的实现,它在 Bitbucket上可用。
于 2014-04-11T14:25:31.877 回答
2
这是一种在不同 TAB 控件之间也启用拖动的方法。当第二个控件还没有选项卡时,这也有效(尽管覆盖了 Wndproc)。基于 bruce965 的回答,以及在此处找到的信息。希望这对寻找可拖动标签的人有所帮助!
namespace Utilities.Windows.Forms
{
public class DraggableTabControl : TabControl
{
private TabPage predraggedTab;
private const int WM_NCHITTEST = 0x84;
private const int HTTRANSPARENT = -1;
private const int HTCLIENT = 1;
public DraggableTabControl()
{
this.AllowDrop = true;
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
{
if (m.Result.ToInt32() == HTTRANSPARENT)
m.Result = new IntPtr(HTCLIENT);
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
predraggedTab = getPointedTab();
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && predraggedTab != null)
this.DoDragDrop(predraggedTab, DragDropEffects.Move);
base.OnMouseMove(e);
}
protected override void OnDragDrop(DragEventArgs drgevent)
{
TabPage draggedTab = (TabPage)drgevent.Data.GetData(typeof(TabPage));
if (draggedTab.Parent != this)
{
draggedTab.Parent = this;
this.SelectedTab = draggedTab;
}
predraggedTab = null;
base.OnDragDrop(drgevent);
}
protected override void OnDragOver(DragEventArgs drgevent)
{
TabPage draggedTab = (TabPage)drgevent.Data.GetData(typeof(TabPage));
TabPage pointedTab = getPointedTab();
if (draggedTab == predraggedTab && pointedTab != null)
{
drgevent.Effect = DragDropEffects.Move;
if (pointedTab != draggedTab)
swapTabPages(draggedTab, pointedTab);
}
else if (draggedTab != null && draggedTab.Parent != this)
{
drgevent.Effect = DragDropEffects.Move;
}
base.OnDragOver(drgevent);
}
private TabPage getPointedTab()
{
for (int i = 0; i < this.TabPages.Count; i++)
if (this.GetTabRect(i).Contains(this.PointToClient(Cursor.Position)))
return this.TabPages[i];
return null;
}
private void swapTabPages(TabPage src, TabPage dst)
{
int srci = this.TabPages.IndexOf(src);
int dsti = this.TabPages.IndexOf(dst);
this.TabPages[dsti] = src;
this.TabPages[srci] = dst;
if (this.SelectedIndex == srci)
this.SelectedIndex = dsti;
else if (this.SelectedIndex == dsti)
this.SelectedIndex = srci;
this.Refresh();
}
}
}
于 2014-12-05T11:40:26.933 回答