c#重寫TabControl控制項實現關閉按鈕的方法

來源:互聯網
上載者:User

1.c#裡面的TabControl控制項沒有關閉按鈕,而且很難看。

2.有一些已經做好的第三方控制項,但是收費。

3.由於我的故障樹推理診斷項目在繪圖的時候允許同時開啟多個文檔進行操作,就要實作類別似於瀏覽器的多標籤功能,而且要可以關閉。

4.所以自己寫一個類繼承TabControl類,然後重寫一些裡面的方法即可實現。

5.特色:有關閉按鈕,標籤有背景顏色,選中的標籤和沒選中的顏色不一樣,實現滑鼠中鍵和右鍵的功能

先看我的項目中的完整代碼,有很多代碼是我的項目需要,可根據你的項目需求刪減,核心的代碼後面詳細解釋:

複製代碼 代碼如下: /// <summary>
/// 重寫的TabControl控制項 帶關閉按鈕
/// </summary>
public class MyTabControl : TabControl
{
private int iconWidth = 16;
private int iconHeight = 16;
private Image icon = null;
private Brush biaocolor = Brushes.Silver; //選項卡的背景色
private Form_paint father;//父視窗,即繪圖介面,為的是當選項卡全關後調用父視窗的dispose事件關閉父視窗
private AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl axDrawingControl1;
public MyTabControl(AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl axDrawingControl)
: base()
{
this.axDrawingControl1 = axDrawingControl;
this.ItemSize = new Size(50, 25); //設定選項卡標籤的大小,可改變高不可改變寬
//this.Appearance = TabAppearance.Buttons; //選項卡的顯示模式
this.DrawMode = TabDrawMode.OwnerDrawFixed;
icon = Properties.Resources.close.ToBitmap();
iconWidth = icon.Width; iconHeight = icon.Height;
}
/// <summary>
/// 設定父視窗
/// </summary>
/// <param name="fp">畫圖視窗</param>
public void setFather(Form_paint fp)
{
this.father = fp;
}
/// <summary>
/// 重寫的繪製事件
/// </summary>
/// <param name="e"></param>
protected override void OnDrawItem(DrawItemEventArgs e)//重寫繪製事件。
{
Graphics g = e.Graphics;
Rectangle r = GetTabRect(e.Index);
if (e.Index == this.SelectedIndex) //當前選中的Tab頁,設定不同的樣式以示選中
{
Brush selected_color = Brushes.Gold; //選中的項的背景色
g.FillRectangle(selected_color, r); //改變選項卡標籤的背景色
string title = this.TabPages[e.Index].Text + " ";
g.DrawString(title, this.Font, new SolidBrush(Color.Black), new PointF(r.X + 3, r.Y + 6));//PointF選項卡標題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項卡上的表徵圖的位置 fntTab = new System.Drawing.Font(e.Font, FontStyle.Bold);
}
else//非選中的
{
g.FillRectangle(biaocolor, r); //改變選項卡標籤的背景色
string title = this.TabPages[e.Index].Text + " ";
g.DrawString(title, this.Font, new SolidBrush(Color.Black), new PointF(r.X + 3, r.Y + 6));//PointF選項卡標題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項卡上的表徵圖的位置
}
}

protected override void OnMouseClick(MouseEventArgs e)
{
#region 左鍵判斷是否在關閉地區
if (e.Button == MouseButtons.Left)
{
Point p = e.Location;
Rectangle r = GetTabRect(this.SelectedIndex);
r.Offset(r.Width - iconWidth - 3, 2);
r.Width = iconWidth;
r.Height = iconHeight;
if (r.Contains(p)) //點擊特定地區時才發生
{
string temp = this.SelectedTab.Text;
if (temp[temp.Length - 5] == '*')//有變化才儲存
{
//確認是否儲存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否儲存故障樹" + this.SelectedTab.Name + "到圖形檔案", "請確認", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認儲存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//儲存當前文檔到檔案夾
string datetime = DateTime.Now.ToString();//擷取目前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//儲存vsd文檔到資料庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果資訊已存在則將xml中的日期更新,如果不存在直接插入

this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//儲存後取消星號標誌,還原為沒變化的時候的樣式
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點擊取消或者關閉
{
return;//直接退出,撤銷這次關閉程式的事件。
}
}
if (this.TabCount == 1)//是最後一個選項卡,直接關閉父介面,即畫圖介面
{
father.DisposeForTabControl(true);
}
else//不是最後一個
{
this.TabPages.Remove(this.SelectedTab);
}
}
}
#endregion
#region 右鍵 選中
else if (e.Button == MouseButtons.Right) // 右鍵選中
{
for (int i = 0; i < this.TabPages.Count; i++)
{
TabPage tp = this.TabPages[i];
if (this.GetTabRect(i).Contains(new Point(e.X, e.Y)))
{
this.SelectedTab = tp;
break;
}
}
}
#endregion
#region 中鍵 選中 關閉
else if (e.Button == MouseButtons.Middle)//滑鼠中鍵關閉
{
for (int i = 0; i < this.TabPages.Count; i++)
{
TabPage tp = this.TabPages[i];
if (this.GetTabRect(i).Contains(new Point(e.X, e.Y)))//找到後,關閉
{
this.SelectedTab = tp;
string temp = tp.Text;
if (temp[temp.Length - 5] == '*')//有變化才儲存
{
//確認是否儲存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否儲存故障樹" + this.SelectedTab.Name + "到圖形檔案", "請確認", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認儲存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//儲存當前文檔到檔案夾
string datetime = DateTime.Now.ToString();//擷取目前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//儲存vsd文檔到資料庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果資訊已存在則將xml中的日期更新,如果不存在直接插入

this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//儲存後取消星號標誌,還原為沒變化的時候的樣式
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點擊取消或者關閉
{
return;//直接退出,撤銷這次關閉程式的事件。
}
}
if (this.TabCount == 1)//是最後一個選項卡,直接關閉父介面,即畫圖介面
{
father.DisposeForTabControl(true);
}
else//不是最後一個
{
this.TabPages.Remove(this.SelectedTab);
}

break;
}
}
}
#endregion
}
}

實現關閉按鈕的關鍵代碼是重寫OnDrawItem(DrawItemEventArgs e)方法:

複製代碼 代碼如下:protected override void OnDrawItem(DrawItemEventArgs e)//重寫繪製事件。
{
Graphics g = e.Graphics;
Rectangle r = GetTabRect(e.Index);
if (e.Index == this.SelectedIndex) //當前選中的Tab頁,設定不同的樣式以示選中
{
Brush selected_color = Brushes.Gold; //選中的項的背景色
g.FillRectangle(selected_color, r); //改變選項卡標籤的背景色
string title = this.TabPages[e.Index].Text + " ";
g.DrawString(title, this.Font, new SolidBrush(Color.Black), new PointF(r.X + 3, r.Y + 6));//PointF選項卡標題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項卡上的表徵圖的位置 fntTab = new System.Drawing.Font(e.Font, FontStyle.Bold);
}
else//非選中的
{
g.FillRectangle(biaocolor, r); //改變選項卡標籤的背景色
string title = this.TabPages[e.Index].Text + " ";
g.DrawString(title, this.Font, new SolidBrush(Color.Black), new PointF(r.X + 3, r.Y + 6));//PointF選項卡標題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項卡上的表徵圖的位置
}
}

其中的if-else是用來判斷當前選項卡是否是選中的,使選中的顏色和未選中的不一樣,項目中不需要的可以去除。


具體實現關閉功能的原理是重寫protected override void OnMouseClick(MouseEventArgs e)方法,左鍵單擊會觸發對應事件,判斷單擊的地區位置是否在關閉按鈕的地區,實現關閉功能。另外有對中鍵和右鍵的處理,根據你的項目,修改對應按鈕事件下的代碼即可。

複製代碼 代碼如下:protected override void OnMouseClick(MouseEventArgs e)
{
#region 左鍵判斷是否在關閉地區
if (e.Button == MouseButtons.Left)
{
Point p = e.Location;
Rectangle r = GetTabRect(this.SelectedIndex);
r.Offset(r.Width - iconWidth - 3, 2);
r.Width = iconWidth;
r.Height = iconHeight;
if (r.Contains(p)) //點擊特定地區時才發生
{
string temp = this.SelectedTab.Text;
if (temp[temp.Length - 5] == '*')//有變化才儲存
{
//確認是否儲存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否儲存故障樹" + this.SelectedTab.Name + "到圖形檔案", "請確認", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認儲存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//儲存當前文檔到檔案夾
string datetime = DateTime.Now.ToString();//擷取目前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//儲存vsd文檔到資料庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果資訊已存在則將xml中的日期更新,如果不存在直接插入

this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//儲存後取消星號標誌,還原為沒變化的時候的樣式
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點擊取消或者關閉
{
return;//直接退出,撤銷這次關閉程式的事件。
}
}
if (this.TabCount == 1)//是最後一個選項卡,直接關閉父介面,即畫圖介面
{
father.DisposeForTabControl(true);
}
else//不是最後一個
{
this.TabPages.Remove(this.SelectedTab);
}
}
}
#endregion
#region 右鍵 選中
else if (e.Button == MouseButtons.Right) // 右鍵選中
{
for (int i = 0; i < this.TabPages.Count; i++)
{
TabPage tp = this.TabPages[i];
if (this.GetTabRect(i).Contains(new Point(e.X, e.Y)))
{
this.SelectedTab = tp;
break;
}
}
}
#endregion
#region 中鍵 選中 關閉
else if (e.Button == MouseButtons.Middle)//滑鼠中鍵關閉
{
for (int i = 0; i < this.TabPages.Count; i++)
{
TabPage tp = this.TabPages[i];
if (this.GetTabRect(i).Contains(new Point(e.X, e.Y)))//找到後,關閉
{
this.SelectedTab = tp;
string temp = tp.Text;
if (temp[temp.Length - 5] == '*')//有變化才儲存
{
//確認是否儲存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否儲存故障樹" + this.SelectedTab.Name + "到圖形檔案", "請確認", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認儲存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//儲存當前文檔到檔案夾
string datetime = DateTime.Now.ToString();//擷取目前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//儲存vsd文檔到資料庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果資訊已存在則將xml中的日期更新,如果不存在直接插入

this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//儲存後取消星號標誌,還原為沒變化的時候的樣式
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點擊取消或者關閉
{
return;//直接退出,撤銷這次關閉程式的事件。
}
}
if (this.TabCount == 1)//是最後一個選項卡,直接關閉父介面,即畫圖介面
{
father.DisposeForTabControl(true);
}
else//不是最後一個
{
this.TabPages.Remove(this.SelectedTab);
}

break;
}
}
}
#endregion
}

寫完之後如何使用呢???

在你的表單上拖一個TabControl,然後開啟對應表單代碼檔案的.Designer.cs檔案裡找到private void InitializeComponent()方法,然後找到裡面對應的TabControl的定義語句即 this.TabControl =。。。。改成this.TabControl = new MyTabControl();如果想傳參,就在前面重寫MyTabControl時加入帶參的建構函式(我的就帶有參數)。

值得一提的是.Designer.cs檔案裡找到private void InitializeComponent()方法都是程式根據你的可視化介面設計自動產生的,所以每次你在可視化的設計環境下重新編輯了,這裡就會重建,所以你得手動再次改一下this.TabControl = new MyTabControl();

我的程式效果如下

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.