TabControlを拡張した。
タブ部分に対するマウスイベントを実装して、操作対象のタブが容易に判別出来るようにした。
また、プロパティの操作によってタブのドラッグ&ドロップでの並び替えが出来るようにした。
using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; namespace Anis.Controls { /// <summary>TabMouseClickイベントを処理するメソッドを表します。</summary> public delegate void TabMouseEventHandler(object sender, TabMouseEventArgs e); /// <summary>タブ部分がクリックされた際に、 /// クリックされたタブを取得出来るTabMouseClickイベントを備えたTabControl</summary> public class AnisTabControl: TabControl { #region//各種TabMouseEvent定義 /// <summary>クリックされたタブが取得可能なMouseDownイベント</summary> [Category("アクション"), Description("マウスでタブをクリックした時に発生します。")] public event TabMouseEventHandler TabMouseDown; /// <summary>クリックされたタブが取得可能なMouseClickイベント</summary> [Category("アクション"),Description("マウスでタブをクリックした時に発生します。")] public event TabMouseEventHandler TabMouseClick; /// <summary>クリックされたタブが取得可能なMouseUpイベント</summary> [Category("アクション"), Description("マウスでタブをクリックした時に発生します。")] public event TabMouseEventHandler TabMouseUp; /// <summary>クリックされたタブが取得可能なMouseDoubleClickイベント</summary> [Category("アクション"), Description("マウスでタブをダブルクリックした時に発生します。")] public event TabMouseEventHandler TabMouseDoubleClick; /// <summary>クリックされたタブが取得可能なMouseWheelイベント</summary> [Category("アクション"), Description("マウスホイールがタブ上で動かされた時に発生します。")] public event TabMouseEventHandler TabMouseWheel; /// <summary>クリックされたタブが取得可能なMouseMoveイベント</summary> [Category("アクション"), Description("マウスポインタがコントロール上を移動すると発生します。")] public event TabMouseEventHandler TabMouseMove; #endregion /// <summary>XMLコメントが無いって警告うざい</summary> public AnisTabControl() { #region//TabMouseEvent関連イベント登録 this.MouseDown += new MouseEventHandler(AnisTabControl_MouseDown); this.MouseClick += new MouseEventHandler(AnisTabControl_MouseClick); this.MouseUp += new MouseEventHandler(AnisTabControl_MouseUp); this.MouseDoubleClick += new MouseEventHandler(AnisTabControl_MouseDoubleClick); this.MouseWheel += new MouseEventHandler(AnisTabControl_MouseWheel); this.MouseMove += new MouseEventHandler(AnisTabControl_MouseMove); #endregion } /// <summary>Point上のタブコントロールのタブ部分に対応したTabPageのインデックスを取得</summary> /// <param name="point">インデックスを取得するPoint</param> /// <returns>Point上にタブが無ければ-1が返ります。。</returns> private int TabIndexFromPoint(Point point) { for(int i = 0; i <= this.TabPages.Count - 1; i++) { if(this.GetTabRect(i).Contains(point)) { return i; } } return -1; } //#region//Tabマウスイベント void AnisTabControl_MouseDown(object sender, MouseEventArgs e) { try { int index = TabIndexFromPoint(e.Location); if(index != -1) { TabMouseEventArgs E = new TabMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); this.TabMouseDown(sender, E); } } catch(NullReferenceException) { } } void AnisTabControl_MouseClick(object sender, MouseEventArgs e) { try { int index = TabIndexFromPoint(e.Location); if(index != -1) { TabMouseEventArgs E = new TabMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); this.TabMouseClick(sender, E); } } catch(NullReferenceException) { } } void AnisTabControl_MouseUp(object sender, MouseEventArgs e) { try { int index = TabIndexFromPoint(e.Location); if(index != -1) { TabMouseEventArgs E = new TabMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); this.TabMouseUp(sender, E); } } catch(NullReferenceException) { } } void AnisTabControl_MouseDoubleClick(object sender, MouseEventArgs e) { try { int index = TabIndexFromPoint(e.Location); if(index != -1) { TabMouseEventArgs E = new TabMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); this.TabMouseDoubleClick(sender, E); } } catch(NullReferenceException) { } } void AnisTabControl_MouseWheel(object sender, MouseEventArgs e) { try { int index = TabIndexFromPoint(e.Location); if(index != -1) { TabMouseEventArgs E = new TabMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); this.TabMouseWheel(sender, E); } } catch(NullReferenceException) { } } void AnisTabControl_MouseMove(object sender, MouseEventArgs e) { try { int index = TabIndexFromPoint(e.Location); if(index != -1) { TabMouseEventArgs E = new TabMouseEventArgs(index, e.Button, e.Clicks, e.X, e.Y, e.Delta); this.TabMouseMove(sender, E); } } catch(NullReferenceException) { } } //#endregion #region//ドラッグ&ドロップ Point mouseDownPoint = Point.Empty; bool sortTabDragDrop; /// <summary>trueでドラッグ&ドロップによるタブの並び替えを可能にします。</summary> [Category("動作"),Description("trueでドラッグ&ドロップによるタブの並び替えを可能にします。")] public bool SortTabDragDrop { set { if(sortTabDragDrop == value) return; sortTabDragDrop = value; if(value) { this.MouseDown += new MouseEventHandler(AnisTabControl_MouseDown1); this.MouseUp += new MouseEventHandler(AnisTabControl_MouseUp1); this.TabMouseMove += new TabMouseEventHandler(AnisTabControl_TabMouseMove); this.DragEnter += new DragEventHandler(AnisTabControl_DragEnter); this.DragOver += new DragEventHandler(AnisTabControl_DragOver); this.DragDrop += new DragEventHandler(AnisTabControl_DragDrop); } else { this.MouseDown -= new MouseEventHandler(AnisTabControl_MouseDown1); this.MouseUp -= new MouseEventHandler(AnisTabControl_MouseUp1); this.TabMouseMove -= new TabMouseEventHandler(AnisTabControl_TabMouseMove); this.DragEnter -= new DragEventHandler(AnisTabControl_DragEnter); this.DragOver -= new DragEventHandler(AnisTabControl_DragOver); this.DragDrop -= new DragEventHandler(AnisTabControl_DragDrop); } } get { return sortTabDragDrop; } } void AnisTabControl_MouseDown1(object sender, MouseEventArgs e) { if(e.Button == MouseButtons.Left) { mouseDownPoint = e.Location; } else { mouseDownPoint = Point.Empty; } } void AnisTabControl_MouseUp1(object sender, MouseEventArgs e) { mouseDownPoint = Point.Empty; } void AnisTabControl_TabMouseMove(object sender, TabMouseEventArgs e) { if(mouseDownPoint != Point.Empty) { Rectangle mouseMoveRectangle = new Rectangle( mouseDownPoint.X - 5, mouseDownPoint.Y - 5, 10, 10); if(!mouseMoveRectangle.Contains(e.Location)){ this.DoDragDrop(this.TabPages[e.TabIndex], DragDropEffects.Move); } } } void AnisTabControl_DragOver(object sender, DragEventArgs e) { mouseDownPoint = Point.Empty; } void AnisTabControl_DragEnter(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(typeof(TabPage)) && this.TabPages.Contains((TabPage)(e.Data.GetData(typeof(TabPage)))) && this.TabIndexFromPoint(this.PointToClient(new Point(e.X,e.Y))) != -1){ e.Effect = DragDropEffects.Move; } else { e.Effect = DragDropEffects.None; } } void AnisTabControl_DragDrop(object sender, DragEventArgs e) { int index = TabIndexFromPoint(this.PointToClient(new Point(e.X,e.Y))); TabPage tabPage = (TabPage)(e.Data.GetData(typeof(TabPage))); this.TabPages.Remove(tabPage); this.TabPages.Insert(index, tabPage); this.SelectTab(index); } #endregion } /// <summary>TabMouseClickイベントのデータ</summary> public class TabMouseEventArgs :MouseEventArgs { private int tabIndex_; /// <param name="tabIndex">クリックされたタブに対応したタブのインデックス</param> public TabMouseEventArgs(int tabIndex, MouseButtons button, int clicks, int x, int y, int delta) : base(button, clicks, x, y, delta) { tabIndex_ = tabIndex; } /// <summary>クリックされたタブに対応したタブページ</summary> public int TabIndex { get { return tabIndex_; } } } }