可关闭的 Tab 控件
一个可关闭选项卡控件,扩展了 WinForms TabControl 的功能,以显示一个“关闭”图像。
引言
我需要一个选项卡控件,允许用户通过单击关闭符号来关闭选项卡页面。 在网上搜索时,我发现了这个很棒的 Yoramo 的文章。 唯一的问题是关闭符号添加到了文本的左侧,而我的用户期望它在右侧。 所以我只是重新编写了 Yoramo 提供的代码,经过一些修改,我让它运行起来了,并且符合我的预期,所以我认为我应该在这里 Code Project 上与大家分享。
使用控件
使用该控件实际上非常简单。 您所需要做的就是
- 创建一个新的 Windows 应用程序项目,并将其命名为您想要的任何名称(例如:ClosableTabs)。
- 下载提供的 zip 文件并将其解压缩到您的项目文件夹中。
- 在解决方案资源管理器中右键单击您的项目,选择“添加 => 现有项目”,然后浏览到 ClosableTabs.cs。
- 右键单击解决方案资源管理器中的 Form1.cs 文件,然后选择“查看代码”。
- 在 Form1.cs 中添加以下
using
语句:using PL.TabControl;
。 现在按 F6 键。 - 现在打开表单设计器(双击解决方案资源管理器中的 Form1.cs 文件)。
- 在工具箱列表中,现在应该添加一个名为
ClosableTabs
的组件。 像使用任何其他控件一样,单击并将其拖到设计器表面上。 - 确保选择了
ClosableTabs
控件(注意:必须选择整个控件;您可以通过单击其中一个选项卡来确保这一点)。 - 在“属性”窗口中,搜索“
SetImage
”属性,然后单击 [...] 按钮。 - 在“选择资源”对话框中,单击“本地资源”单选按钮,然后单击“导入”。 浏览到“close.gif”文件并单击“打开”。
- 返回到“选择资源”对话框,单击“确定”,然后按 F6 键,关闭图像应该会出现在选项卡上。
您的代码现在应该类似于这样
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();
}
}
}
这就是它的全部内容; 每次您添加一个新选项卡时,它都会自动在其上获取一个关闭图像。
关注点
添加您自己的关闭符号图像不会导致任何问题,只要它的大小与提供的图像相同(10x10 像素),但如果它更大/更小,则需要遵循一些额外的步骤。
- 首先,您可能需要更改图像的位置; 这是通过更改
ClosableTabs
控件的ImageLocation
属性来完成的。 - 其次,您可能需要更改
ClosableTabs
控件的ImageHitArea
属性。 - 20 - 10 - 8 = 2;
ImageHitArea.X
= 图像宽度 + 8; - 15 - 10 - 3 = 2;
ImageHitArea.X
= 图像宽度 + 3; - 17 - 10 - 5 = 2;
ImageHitArea.X
= 图像宽度 + 5;
注意:ImageLocation
属性向后计数,因此通过增加它,图像将向左移动,减少它将向右移动图像。
注意:设置 ImageHitArea
属性是通过猜测正确的数字来完成的。 您可以使用此作为经验法则:ImageLocation.X
- 图像宽度 - x = 2; 其中 x 是要增加 ImageHitArea.X
值的数字。 例如
注意: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]);
}
}
}