Как сделать TabPages перетаскиваемым? - PullRequest
3 голосов
/ 13 февраля 2011

Я бы хотел, чтобы пользователь мог изменить порядок TabPages путем перетаскивания. Более того, было бы здорово разрешить пользователю перетаскивать TabPages из одного TabControl в другой. Оба способа как в Firefox и Total Commander. Как этого добиться?

Ответы [ 4 ]

5 голосов
/ 20 мая 2011

переупорядочение вкладок с помощью перетаскивания - от Людвига Б.
вдохновленный 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();
        }
4 голосов
/ 11 апреля 2014

Основано на ответах 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 здесь .

2 голосов
/ 05 декабря 2014

Здесь также можно включить перетаскивание между различными элементами 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();
        }
    }
}
1 голос
/ 13 февраля 2011

Существует статья CodeProject от 2002 года по этой теме.

...