c# - 带有关闭和添加按钮的 TabControl

标签 c# .net winforms custom-controls tabcontrol

我正在尝试使选项卡控件具有“x”(关闭按钮)和“+”(新选项卡按钮)。我找到了添加 x button 的解决方案,标签现在看起来像这样:

enter image description here

但我想添加一个 + 现在那个黑色圆圈在哪里。我不知道如何,我尝试在最后一个选项卡的 Paint 事件上绘制,如下所示:

var p = tabs.TabPages[tabs.TabCount - 1];
p.Paint += new PaintEventHandler(tab_OnDrawPage);

private void tab_OnDrawPage(object sender, PaintEventArgs e)
{
    // e.ClipRectangle.
    e.Graphics.DrawString("+", 
                          new Font("verdana", 
                                   10, 
                                   FontStyle.Bold), 
                          Brushes.Black, 
                          e.ClipRectangle.X + 10, 
                          e.ClipRectangle.Y + 10);
}

但它没有显示任何平局。我想这与我传递给 DrawString() 调用的位置有关,但我不知道使用正确的位置。我用 +10 把它从最后一个选项卡上移开。如何解决?我自己没有做过任何自定义绘图,我正在学习。

最佳答案

作为一个选项,您可以添加一个显示添加图标的额外选项卡 Add并检查用户何时单击该选项卡,然后插入一个新的 TabPage在此之前。

您还可以简单地使用 Selecting 来阻止选择额外的选项卡TabControl的事件.这样最后一个选项卡对您来说就像一个添加按钮,就像 IE 和 Chrome。

Tab with close and add button

实现细节

我们将使用所有者绘制选项卡在每个选项卡上显示关闭图标,在最后一个选项卡上显示添加图标。我们使用 DrawItem关闭和添加图标,MouseDown 处理点击关闭和添加按钮,Selecting 防止选择最后一个选项卡,HandleCreated 调整选项卡宽度。您可以在下面看到所有实现设置和代码。

初始化

设置填充和 DrawMode并为 DrawItemMouseDownSelectingHandleCreated 事件分配事件处理程序。

this.tabControl1.Padding = new Point(12, 4);
this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;

this.tabControl1.DrawItem += tabControl1_DrawItem;
this.tabControl1.MouseDown += tabControl1_MouseDown;
this.tabControl1.Selecting += tabControl1_Selecting;
this.tabControl1.HandleCreated += tabControl1_HandleCreated;

处理关闭按钮和添加按钮的点击

您可以处理 MouseDownMouseClick 事件并检查最后一个选项卡矩形是否包含鼠标单击点,然后在最后一个选项卡之前插入一个选项卡。否则检查其中一个关闭按钮是否包含点击位置,然后关闭其关闭按钮被点击的选项卡:

private void tabControl1_MouseDown(object sender, MouseEventArgs e)
{
    var lastIndex = this.tabControl1.TabCount - 1;
    if (this.tabControl1.GetTabRect(lastIndex).Contains(e.Location))
    {
        this.tabControl1.TabPages.Insert(lastIndex, "New Tab");
        this.tabControl1.SelectedIndex = lastIndex;
    }
    else
    {
        for (var i = 0; i < this.tabControl1.TabPages.Count; i++)
        {
            var tabRect = this.tabControl1.GetTabRect(i);
            tabRect.Inflate(-2, -2);
            var closeImage = Properties.Resources.DeleteButton_Image;
            var imageRect = new Rectangle(
                (tabRect.Right - closeImage.Width),
                tabRect.Top + (tabRect.Height - closeImage.Height) / 2,
                closeImage.Width,
                closeImage.Height);
            if (imageRect.Contains(e.Location))
            {
                this.tabControl1.TabPages.RemoveAt(i);
                break;
            }
        }
    }
}

防止选择最后一个标签

要防止选择最后一个选项卡,可以处理控件的Selecting事件,检查选择的选项卡是否为最后一个选项卡,取消事件:

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
    if (e.TabPageIndex == this.tabControl1.TabCount - 1)
        e.Cancel = true;
}

绘制关闭按钮和添加按钮

要绘制关闭按钮和添加按钮,可以处理DrawItem 事件。我使用这些图标添加 Add并关闭 Close按钮。

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    var tabPage = this.tabControl1.TabPages[e.Index];
    var tabRect = this.tabControl1.GetTabRect(e.Index);
    tabRect.Inflate(-2, -2);
    if (e.Index == this.tabControl1.TabCount - 1)
    {
        var addImage = Properties.Resources.AddButton_Image;
        e.Graphics.DrawImage(addImage,
            tabRect.Left + (tabRect.Width - addImage.Width) / 2,
            tabRect.Top + (tabRect.Height - addImage.Height) / 2);
    }
    else
    {
        var closeImage = Properties.Resources.DeleteButton_Image;
        e.Graphics.DrawImage(closeImage,
            (tabRect.Right - closeImage.Width),
            tabRect.Top + (tabRect.Height - closeImage.Height) / 2);
        TextRenderer.DrawText(e.Graphics, tabPage.Text, tabPage.Font,
            tabRect, tabPage.ForeColor, TextFormatFlags.Left);
    }
}

调整标签宽度

要调整制表符宽度并让最后一个制表符的宽度更小,您可以处理 HandleCreated 事件并发送 TCM_SETMINTABWIDTH到控件并指定制表符宽度允许的最小尺寸:

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private const int TCM_SETMINTABWIDTH = 0x1300 + 49;
private void tabControl1_HandleCreated(object sender, EventArgs e)
{
    SendMessage(this.tabControl1.Handle, TCM_SETMINTABWIDTH, IntPtr.Zero, (IntPtr)16);
}

下载

您可以在此处下载代码或克隆存储库:

关于c# - 带有关闭和添加按钮的 TabControl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36895089/

相关文章:

c# - 在 Internet Explorer 中打开新的模式对话框窗口时会引发哪个事件?

c# - 更改 DataGridViewCell 用户输入处理行为

c# - 当以编程方式更改值时,不触发 DataGridView 中的单元格值更改事件

c# - 另一个类而不是 SHA1Managed 来制作长度小于 128 字节的校验和

c# - 是否可以将控件转换为组件或组件以在 winforms 中进行控制?

c# - Nuget 将文件从 packages 文件夹复制到项目目录

c# - VS 2005 中的字控件

C# 工具提示显示的时间不够长

.net - .net SqlCommand.ExecuteReader 是否关闭连接?

c# - 关闭对话框和启动对话框的窗体