选项卡式记事本 - 无法删除关闭按钮

Tabbed Notepad - not able to remove close button

我正在尝试创建一个选项卡式记事本应用程序,但在删除选项卡上的 "close buttons" 时遇到问题。标签被删除,但我只能删除 1 个关闭按钮。谁能帮助我指引正确的方向:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace My_Notepad
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }


    int TabCount = 0;
    int btx = 96;
    private int i;

    public void newBox()
    {

        TabPage tp = new TabPage("New Document          ");
        RichTextBox rtb = new RichTextBox();
        rtb.Dock = DockStyle.Fill;
        tp.Controls.Add(rtb);
        tabControl1.TabPages.Add(tp);
        this.tabControl1.SelectedTab = tp;
        this.tabControl1.Appearance = TabAppearance.FlatButtons;


        Button btnPlay = new Button();
        this.btnPlay = btnPlay;

        btnPlay.Width = 16;
        btnPlay.Height = 18;
        btnPlay.FlatStyle = FlatStyle.Flat;
        btnPlay.FlatAppearance.BorderSize = 0;
        btnPlay.Top = 25;
        btnPlay.Left = btx;
        btnPlay.Image = Image.FromFile(@"C:\close-button.png");
        btnPlay.Click += new EventHandler(btnPlay_Click);
        this.Controls.Add(btnPlay);
        btnPlay.BringToFront();
        TabCount++;
        i++;

    }



    private void btnPlay_Click(object sender, EventArgs e)
    {

        tabControl1.SelectedTab.Dispose();
        this.Controls.Remove(btnPlay);

    }


    private void newToolStripMenuItem_Click(object sender, EventArgs e)
    {
        newBox();

        btx = btx + 126;
    }



    public Button btnPlay { get; set; }


   }
   }

您的问题似乎是,您没有保留对您创建的 Buttons 的单独引用。您编写代码的方式表明您有一个 class 级别变量 btnPlay,您向其分配一个动态创建的局部变量 btnPlay,从而覆盖对旧 [=20] 的引用=]:

Button btnPlay = new Button();
this.btnPlay = btnPlay;

稍后,当您尝试删除Buttons时,您只能删除最后一个。

为避免这种情况,您需要保留将每个 Button 连接到它所指的 TabPage 的引用。最常见的方法是使用页面的 Tag 来保存引用:

Button btnPlay = new Button();
this.btnPlay = btnPlay;  
tp.Tag = btnPlay;

现在只要 TabPage 还活着就可以到达它:

private void btnPlay_Click(object sender, EventArgs e)
{
    Button btnPlay = ((sender as TabPage).Tag as Button);
    ..
}

但是,由于您只想摆脱它,因此有一个更简单的解决方案:在 btnPlay_Click 事件中,您可以通过 [= 引用正确的 Button 27=] 参数..:[=​​35=]

private void btnPlay_Click(object sender, EventArgs e)
{
    tabControl1.SelectedTab.Dispose();
    (sender as Button).Dispose();
}

为此,您甚至不需要使用 Tag.. 不确定您是否使用 class 级别 btnPlay..??

不过..

..按照我的阅读方式,您的代码还有一个问题:每个 关闭按钮仅关闭当前 选定的TabPage 而不是它所属的那个。所以我们真正需要的是保持每个 Button 到它的 TabPage 的引用,而不是反过来..:

Button btnPlay = new Button();
this.btnPlay = btnPlay;  // what is it good for?
btnPlay.Tag = tp;

现在应该可以了:

private void btnPlay_Click(object sender, EventArgs e)
{
    Button btnPlay = sender as Button;
    (btnPlay.Tag as TabPage).Dispose();
    btnPlay.Dispose();
}

顺便说一句,如果您对自己的解决方案感到满意,请务必坚持下去!只是想提一下,通常人们使用 owner drawingTabControl 来添加像关闭按钮这样的装饰。你的方式听起来有点简单,我想说,至少在你想要移动或调整选项卡大小之前是这样..

更新: 既然你问的是所有者绘图,这里是一个最小的例子:

Rectangle currentCrossRect = Rectangle.Empty;

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    Bitmap cross = yourCloseImage;
    int xWidth = cross.Width;
    TabPage tp = tabControl1.TabPages[e.Index];
    e.DrawBackground();
    e.DrawFocusRectangle();
    Size size = tabControl1.ItemSize;
    using (SolidBrush brush = new SolidBrush(e.ForeColor))
        e.Graphics.DrawString(tp.Text, e.Font, brush, e.Bounds.Left + 2 , 5);
    if (tabControl1.SelectedTab == tp)
    {
        currentCrossRect = new Rectangle( 
                           e.Bounds.Left + size.Width - 20, 3, xWidth,xWidth);
        e.Graphics.DrawImage(cross, currentCrossRect.X, currentCrossRect.Y);
    }
}


private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
    TabPage tp = tabControl1.SelectedTab;

    if (currentCrossRect.Contains(e.Location)) tp.Dispose();
}