c#重寫TabControl控件實(shí)現(xiàn)關(guān)閉按鈕的方法
1.c#里面的TabControl控件沒有關(guān)閉按鈕,而且很難看。
2.有一些已經(jīng)做好的第三方控件,但是收費(fèi)。
3.由于我的故障樹推理診斷項(xiàng)目在繪圖的時候允許同時打開多個文檔進(jìn)行操作,就要實(shí)現(xiàn)類似于瀏覽器的多標(biāo)簽功能,而且要可以關(guān)閉。
4.所以自己寫一個類繼承TabControl類,然后重寫一些里面的方法即可實(shí)現(xiàn)。
5.特色:有關(guān)閉按鈕,標(biāo)簽有背景顏色,選中的標(biāo)簽和沒選中的顏色不一樣,實(shí)現(xiàn)鼠標(biāo)中鍵和右鍵的功能
先看我的項(xiàng)目中的完整代碼,有很多代碼是我的項(xiàng)目需要,可根據(jù)你的項(xiàng)目需求刪減,核心的代碼后面詳細(xì)解釋:
protected override void OnMouseClick(MouseEventArgs e) this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//保存后取消星號標(biāo)志,還原為沒變化的時候的樣式 this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//保存后取消星號標(biāo)志,還原為沒變化的時候的樣式 break;
/// <summary>
/// 重寫的TabControl控件 帶關(guān)閉按鈕
/// </summary>
public class MyTabControl : TabControl
{
private int iconWidth = 16;
private int iconHeight = 16;
private Image icon = null;
private Brush biaocolor = Brushes.Silver; //選項(xiàng)卡的背景色
private Form_paint father;//父窗口,即繪圖界面,為的是當(dāng)選項(xiàng)卡全關(guān)后調(diào)用父窗口的dispose事件關(guān)閉父窗口
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); //設(shè)置選項(xiàng)卡標(biāo)簽的大小,可改變高不可改變寬
//this.Appearance = TabAppearance.Buttons; //選項(xiàng)卡的顯示模式
this.DrawMode = TabDrawMode.OwnerDrawFixed;
icon = Properties.Resources.close.ToBitmap();
iconWidth = icon.Width; iconHeight = icon.Height;
}
/// <summary>
/// 設(shè)置父窗口
/// </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) //當(dāng)前選中的Tab頁,設(shè)置不同的樣式以示選中
{
Brush selected_color = Brushes.Gold; //選中的項(xiàng)的背景色
g.FillRectangle(selected_color, r); //改變選項(xiàng)卡標(biāo)簽的背景色
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選項(xiàng)卡標(biāo)題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項(xiàng)卡上的圖標(biāo)的位置 fntTab = new System.Drawing.Font(e.Font, FontStyle.Bold);
}
else//非選中的
{
g.FillRectangle(biaocolor, r); //改變選項(xiàng)卡標(biāo)簽的背景色
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選項(xiàng)卡標(biāo)題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項(xiàng)卡上的圖標(biāo)的位置
}
}
{
#region 左鍵判斷是否在關(guān)閉區(qū)域
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)) //點(diǎn)擊特定區(qū)域時才發(fā)生
{
string temp = this.SelectedTab.Text;
if (temp[temp.Length - 5] == '*')//有變化才保存
{
//確認(rèn)是否保存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否保存故障樹" + this.SelectedTab.Name + "到圖形文件", "請確認(rèn)", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認(rèn)保存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//保存當(dāng)前文檔到文件夾
string datetime = DateTime.Now.ToString();//獲取當(dāng)前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//保存vsd文檔到數(shù)據(jù)庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果信息已存在則將xml中的日期更新,如果不存在直接插入
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點(diǎn)擊取消或者關(guān)閉
{
return;//直接退出,撤銷這次關(guān)閉程序的事件。
}
}
if (this.TabCount == 1)//是最后一個選項(xiàng)卡,直接關(guān)閉父界面,即畫圖界面
{
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 中鍵 選中 關(guān)閉
else if (e.Button == MouseButtons.Middle)//鼠標(biāo)中鍵關(guān)閉
{
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)))//找到后,關(guān)閉
{
this.SelectedTab = tp;
string temp = tp.Text;
if (temp[temp.Length - 5] == '*')//有變化才保存
{
//確認(rèn)是否保存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否保存故障樹" + this.SelectedTab.Name + "到圖形文件", "請確認(rèn)", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認(rèn)保存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//保存當(dāng)前文檔到文件夾
string datetime = DateTime.Now.ToString();//獲取當(dāng)前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//保存vsd文檔到數(shù)據(jù)庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果信息已存在則將xml中的日期更新,如果不存在直接插入
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點(diǎn)擊取消或者關(guān)閉
{
return;//直接退出,撤銷這次關(guān)閉程序的事件。
}
}
if (this.TabCount == 1)//是最后一個選項(xiàng)卡,直接關(guān)閉父界面,即畫圖界面
{
father.DisposeForTabControl(true);
}
else//不是最后一個
{
this.TabPages.Remove(this.SelectedTab);
}
}
}
}
#endregion
}
}
實(shí)現(xiàn)關(guān)閉按鈕的關(guān)鍵代碼是重寫OnDrawItem(DrawItemEventArgs e)方法:
protected override void OnDrawItem(DrawItemEventArgs e)//重寫繪制事件。
{
Graphics g = e.Graphics;
Rectangle r = GetTabRect(e.Index);
if (e.Index == this.SelectedIndex) //當(dāng)前選中的Tab頁,設(shè)置不同的樣式以示選中
{
Brush selected_color = Brushes.Gold; //選中的項(xiàng)的背景色
g.FillRectangle(selected_color, r); //改變選項(xiàng)卡標(biāo)簽的背景色
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選項(xiàng)卡標(biāo)題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項(xiàng)卡上的圖標(biāo)的位置 fntTab = new System.Drawing.Font(e.Font, FontStyle.Bold);
}
else//非選中的
{
g.FillRectangle(biaocolor, r); //改變選項(xiàng)卡標(biāo)簽的背景色
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選項(xiàng)卡標(biāo)題的位置
r.Offset(r.Width - iconWidth - 3, 2);
g.DrawImage(icon, new Point(r.X - 2, r.Y + 2));//選項(xiàng)卡上的圖標(biāo)的位置
}
}
其中的if-else是用來判斷當(dāng)前選項(xiàng)卡是否是選中的,使選中的顏色和未選中的不一樣,項(xiàng)目中不需要的可以去除。
具體實(shí)現(xiàn)關(guān)閉功能的原理是重寫protected override void OnMouseClick(MouseEventArgs e)方法,左鍵單擊會觸發(fā)對應(yīng)事件,判斷單擊的區(qū)域位置是否在關(guān)閉按鈕的區(qū)域,實(shí)現(xiàn)關(guān)閉功能。另外有對中鍵和右鍵的處理,根據(jù)你的項(xiàng)目,修改對應(yīng)按鈕事件下的代碼即可。
this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//保存后取消星號標(biāo)志,還原為沒變化的時候的樣式 this.SelectedTab.Text = temp.Substring(0, temp.Length - 5) + " ";//保存后取消星號標(biāo)志,還原為沒變化的時候的樣式 break;
protected override void OnMouseClick(MouseEventArgs e)
{
#region 左鍵判斷是否在關(guān)閉區(qū)域
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)) //點(diǎn)擊特定區(qū)域時才發(fā)生
{
string temp = this.SelectedTab.Text;
if (temp[temp.Length - 5] == '*')//有變化才保存
{
//確認(rèn)是否保存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否保存故障樹" + this.SelectedTab.Name + "到圖形文件", "請確認(rèn)", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認(rèn)保存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//保存當(dāng)前文檔到文件夾
string datetime = DateTime.Now.ToString();//獲取當(dāng)前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//保存vsd文檔到數(shù)據(jù)庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果信息已存在則將xml中的日期更新,如果不存在直接插入
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點(diǎn)擊取消或者關(guān)閉
{
return;//直接退出,撤銷這次關(guān)閉程序的事件。
}
}
if (this.TabCount == 1)//是最后一個選項(xiàng)卡,直接關(guān)閉父界面,即畫圖界面
{
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 中鍵 選中 關(guān)閉
else if (e.Button == MouseButtons.Middle)//鼠標(biāo)中鍵關(guān)閉
{
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)))//找到后,關(guān)閉
{
this.SelectedTab = tp;
string temp = tp.Text;
if (temp[temp.Length - 5] == '*')//有變化才保存
{
//確認(rèn)是否保存VSD文檔到ft_doc_Path
DialogResult response = MessageBox.Show("是否保存故障樹" + this.SelectedTab.Name + "到圖形文件", "請確認(rèn)", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (response == System.Windows.Forms.DialogResult.Yes)//確認(rèn)保存
{
axDrawingControl1.Document.SaveAs(GlobalVariables.ft_doc_Path + axDrawingControl1.Document.Title + ".vsd");//保存當(dāng)前文檔到文件夾
string datetime = DateTime.Now.ToString();//獲取當(dāng)前時間
helpTool.saveVsdDB(axDrawingControl1.Document.Title, datetime);//保存vsd文檔到數(shù)據(jù)庫
helpTool.setDatetimeToXml(axDrawingControl1.Document.Title, datetime);//如果信息已存在則將xml中的日期更新,如果不存在直接插入
}
else if (response == System.Windows.Forms.DialogResult.Cancel)//點(diǎn)擊取消或者關(guān)閉
{
return;//直接退出,撤銷這次關(guān)閉程序的事件。
}
}
if (this.TabCount == 1)//是最后一個選項(xiàng)卡,直接關(guān)閉父界面,即畫圖界面
{
father.DisposeForTabControl(true);
}
else//不是最后一個
{
this.TabPages.Remove(this.SelectedTab);
}
}
}
}
#endregion
}
在你的窗體上拖一個TabControl,然后打開對應(yīng)窗體代碼文件的.Designer.cs文件里找到private void InitializeComponent()方法,然后找到里面對應(yīng)的TabControl的定義語句即 this.TabControl =。。。。改成this.TabControl = new MyTabControl();如果想傳參,就在前面重寫MyTabControl時加入帶參的構(gòu)造函數(shù)(我的就帶有參數(shù))。
值得一提的是.Designer.cs文件里找到private void InitializeComponent()方法都是程序根據(jù)你的可視化界面設(shè)計(jì)自動生成的,所以每次你在可視化的設(shè)計(jì)環(huán)境下重新編輯了,這里就會重新生成,所以你得手動再次改一下this.TabControl = new MyTabControl();
我的程序效果如下
相關(guān)文章
c# 代碼調(diào)試技巧和如何遠(yuǎn)程調(diào)試
這篇文章主要介紹了c# 代碼調(diào)試技巧和如何遠(yuǎn)程調(diào)試,幫助大家更好的理解和使用c#編程語言,感興趣的朋友可以了解下2020-11-11C# Dictionary和SortedDictionary的簡介
今天小編就為大家分享一篇關(guān)于C# Dictionary和SortedDictionary的簡介,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10C#中調(diào)用SAPI實(shí)現(xiàn)語音識別的2種方法
這篇文章主要介紹了C#中調(diào)用SAPI實(shí)現(xiàn)語音識別的2種方法,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-06-06