c#重写TabControl控件实现关闭按钮

原创 2013年03月31日 12:54:56

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();


我的程序效果如下




c#重写TabControl控件实现关闭按钮的方法

转载自:http://www.jb51.net/article/35248.htm 1.c#里面的TabControl控件没有关闭按钮,而且很难看。 2.有一些已经做好的第三方控件,但是收费。 ...
  • mao_mao37
  • mao_mao37
  • 2016年04月21日 20:33
  • 3140

winform tabpage 绘制关闭按钮点击关闭事件和双击tab关闭页面

winform tabpage绘制关闭按钮 1.button1用于添加tab页面 2.button2用户删除当前tab页面 3.tabcontrol 命名MainTabControl 关键部分:...
  • mofijeck
  • mofijeck
  • 2015年07月09日 14:03
  • 3506

TabControl控件带关闭按钮和多种样式

  • 2017年08月10日 08:23
  • 405KB
  • 下载

tabcontrol控件增强,添加关闭按钮功能、呼吸灯标签闪烁功能、类QQ消息数量标签提示TIP

  • 2015年09月07日 01:03
  • 213KB
  • 下载

对tabcontrol控件增强,添加关闭按钮功能、呼吸灯标签闪烁功能、类QQ消息数量标签提示TIP

在网上自绘tabcontrol的基础上增强,大部分代码写了注释。 关闭按钮的绘制思路:对padding属性修改以增加标签空白部分。在空白部分绘制十字,写个鼠标在十字区域点击关闭的事件以在适用控件时处理...
  • vencon_s
  • vencon_s
  • 2015年09月07日 00:40
  • 1089

C#仿QQ皮肤-TabControl控件实现

导读部分 ----------------------------------------------------------------------------------------------...
  • az44yao
  • az44yao
  • 2014年09月05日 11:26
  • 1784

c#TabControl控件左边选项卡左边显示,文字横向显示

c#TabControl控件左边选项卡左边显示,文字横向显示 2015-12-17 10:50 259人阅读 评论(0) 收藏 举报  分类: c#开发(6)  ...
  • kasama1953
  • kasama1953
  • 2016年08月06日 00:52
  • 7253

C#重绘TabControl的Tabpage标签,添加图片及关闭按钮

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->us...
  • li_xiao_ming
  • li_xiao_ming
  • 2013年04月04日 11:23
  • 938

C# Socket网络通信和串口通信集合,并涉及Tabcontrol控件的使用

  • 2017年12月21日 15:51
  • 63KB
  • 下载

C#窗体TabControl控件美化版源代码

  • 2012年04月17日 19:16
  • 137KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c#重写TabControl控件实现关闭按钮
举报原因:
原因补充:

(最多只允许输入30个字)