65.9K
CodeProject 正在变化。 阅读更多。
Home

可关闭的 Tab 控件

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.44/5 (6投票s)

2007年5月20日

CPOL

3分钟阅读

viewsIcon

44264

downloadIcon

856

一个可关闭选项卡控件,扩展了 WinForms TabControl 的功能,以显示一个“关闭”图像。

Screenshot - ClosableTabs.gif

引言

我需要一个选项卡控件,允许用户通过单击关闭符号来关闭选项卡页面。 在网上搜索时,我发现了这个很棒的 Yoramo 的文章。 唯一的问题是关闭符号添加到了文本的左侧,而我的用户期望它在右侧。 所以我只是重新编写了 Yoramo 提供的代码,经过一些修改,我让它运行起来了,并且符合我的预期,所以我认为我应该在这里 Code Project 上与大家分享。

使用控件

使用该控件实际上非常简单。 您所需要做的就是

  1. 创建一个新的 Windows 应用程序项目,并将其命名为您想要的任何名称(例如:ClosableTabs)。
  2. 下载提供的 zip 文件并将其解压缩到您的项目文件夹中。
  3. 在解决方案资源管理器中右键单击您的项目,选择“添加 => 现有项目”,然后浏览到 ClosableTabs.cs
  4. 右键单击解决方案资源管理器中的 Form1.cs 文件,然后选择“查看代码”。
  5. Form1.cs 中添加以下 using 语句:using PL.TabControl;。 现在按 F6 键。
  6. 您的代码现在应该类似于这样

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    
    using PL.TabControl;
    
    namespace ClosableTabs
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
        }
    }
  7. 现在打开表单设计器(双击解决方案资源管理器中的 Form1.cs 文件)。
  8. 在工具箱列表中,现在应该添加一个名为 ClosableTabs 的组件。 像使用任何其他控件一样,单击并将其拖到设计器表面上。
  9. 确保选择了 ClosableTabs 控件(注意:必须选择整个控件;您可以通过单击其中一个选项卡来确保这一点)。
  10. 在“属性”窗口中,搜索“SetImage”属性,然后单击 [...] 按钮。
  11. 在“选择资源”对话框中,单击“本地资源”单选按钮,然后单击“导入”。 浏览到“close.gif”文件并单击“打开”。
  12. 返回到“选择资源”对话框,单击“确定”,然后按 F6 键,关闭图像应该会出现在选项卡上。

这就是它的全部内容; 每次您添加一个新选项卡时,它都会自动在其上获取一个关闭图像。

关注点

添加您自己的关闭符号图像不会导致任何问题,只要它的大小与提供的图像相同(10x10 像素),但如果它更大/更小,则需要遵循一些额外的步骤。

  1. 首先,您可能需要更改图像的位置; 这是通过更改 ClosableTabs 控件的 ImageLocation 属性来完成的。
  2. 注意ImageLocation 属性向后计数,因此通过增加它,图像将向左移动,减少它将向右移动图像。

  3. 其次,您可能需要更改 ClosableTabs 控件的 ImageHitArea 属性。
  4. 注意:设置 ImageHitArea 属性是通过猜测正确的数字来完成的。 您可以使用此作为经验法则:ImageLocation.X - 图像宽度 - x = 2; 其中 x 是要增加 ImageHitArea.X 值的数字。 例如

    • 20 - 10 - 8 = 2; ImageHitArea.X = 图像宽度 + 8;
    • 15 - 10 - 3 = 2; ImageHitArea.X = 图像宽度 + 3;
    • 17 - 10 - 5 = 2; ImageHitArea.X = 图像宽度 + 5;

注意:ImageHitArea.Y 值应始终为 2,除非您更改 ImageLocation.Y 属性,然后应使用与 ImageLocation.Y 属性相同的值来增加/减少它。 例如,如果将 ImageLocation.Y 从 5 增加到 7(增加 2),则应将 ImageHitArea.Y 从 2 增加到 4。

如果您对如何改进此控件或控件的任何其他部分有想法,请发表评论,我很乐意实施它。

ClosableTabs 代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace PL.TabControl
{
    public delegate bool OnBeforeCloseTab(int indx);

    class ClosableTab : System.Windows.Forms.TabControl
    {
        public event OnBeforeCloseTab BeforeCloseATabPage;

        private Image _img;
        private Point _imageLocation = new Point(15, 5);
        private Point _imgHitArea = new Point(13, 2);
        
        private bool _imgExist = false;
        private int _tabWidth = 0;

        public ClosableTab()
            : base()
        {
            BeforeCloseATabPage = null;
            this.DrawMode = TabDrawMode.OwnerDrawFixed;
            this.Padding = new Point(12, 3);
        }

        public Image SetImage
        {
            set 
            { 
                _img = value;
                if (_img != null)
                {
                    _imgExist = true;
                }
            }
            get { return _img; }
        }

        public Point ImageLocation
        {
            get { return _imageLocation; }
            set { _imageLocation = value; }
        }

        public Point ImageHitArea
        {
            get { return _imgHitArea; }
            set { _imgHitArea = value; }
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            Rectangle r = e.Bounds;
            r = GetTabRect(e.Index);
            r.Offset(2, 2);
            
            Brush TitleBrush = new SolidBrush(Color.Black);
            Font f = this.Font;
            
            string title = this.TabPages[e.Index].Text;
                        
            e.Graphics.DrawString(title, f, TitleBrush, new PointF(r.X, r.Y));

            try
            {
                e.Graphics.DrawImage(_img, new Point(r.X + 
                   (GetTabRect(e.Index).Width - _imageLocation.X), _imageLocation.Y));
            }
            catch (Exception) { }
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            if (_imgExist == true)
            {
                Point p = e.Location;
                for (int i = 0; i < TabCount; i++)
                {
                    _tabWidth = GetTabRect(i).Width - (_imgHitArea.X);

                    Rectangle r = GetTabRect(i);
                    r.Offset(_tabWidth, _imgHitArea.Y);
                    r.Width = _img.Width;
                    r.Height = _img.Height;
                    if (r.Contains(p))
                    {
                        CloseTab(i);
                    }
                }
            }
        }

        private void CloseTab(int i)
        {
            if (BeforeCloseATabPage != null)
            {
                bool CanClose = BeforeCloseATabPage(i);
                if (!CanClose)
                    return;
            }
            TabPages.Remove(TabPages[i]);
        }
    }
}
© . All rights reserved.