9

TabControlIE や Firefox のように、実行時に WinForms のタブを並べ替えることができますか?

このようなリンクはあまり期待できません。

4

4 に答える 4

10

もちろん可能です!ソリューションを過度に複雑にしようとしている可能性が最も高いです。基本的に、標準をサブクラス化TabControlし、マウス イベント ハンドラにロジックを追加するだけです。ユーザーが現在ドラッグしているフォームを確認し、TabPagesコレクション内で並べ替えるだけです。

オンラインで入手できる完全なソリューションがいくつかあります。

于 2010-12-04T09:42:22.090 に答える
7

@Cody Gray によって最初に投稿されたソリューションは、ほとんどが私が望んでいたものであることがわかりましたが、それほど複雑にする必要があるとは思いませんでした。

これは、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;
    }
}

ドラッグ アンド ドロップ API は、個別のアプリケーション間、または少なくとも個別のコントロール間でドラッグすることを目的としています。この場合にそれらを使用するのはやり過ぎです。

それは彼に基づいているので、私のものに賛成票を投じる場合は、コーディの答えにも賛成票を投じてください。

于 2012-07-06T11:22:47.267 に答える
1

ドラッグ アンド ドロップによるタブページの並べ替え- http://dotnetrix.co.uk/tabcontrol.htm#tip7 に触発された Ludwig B.作

        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:52:04.677 に答える
1

ジェイコブ・スタンリーの答えを少し拡張しました。これにより、スワッピングが頻繁に発生することはありません。これは、異なるサイズのタブの場合に特に役立ちます。この場合、以前のソリューションではドラッグ中に頻繁に交換されていました。

ユーザー エクスペリエンスの違いは、実際にタブを移動するには、もう少しドラッグする必要があることです。しかし、これはブラウザでのタブの並べ替えに似ています。

また、ドラッグ中にハンドカーソルを追加し、ダブルバッファリングを有効にしました。

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;
        }
    }
}
于 2016-07-01T08:40:49.617 に答える