简体   繁体   English

Winforms 标签页上的关闭按钮

[英]Close button on Tab pages in Winforms

I am trying to add a close button on the tab pages of TabControl and change the color of the close button from light gray to black when mouse hovers over it.我试图在 TabControl 的标签页上添加一个关闭按钮,并在鼠标悬停在其上时将关闭按钮的颜色从浅灰色更改为黑色。 However, the color never changes.但是,颜色永远不会改变。

The DrawEventArgsCustom class is created to indicate that the mouse is hovering over the close button.创建 DrawEventArgsCustom 类以指示鼠标悬停在关闭按钮上。 When it's true, the statement to change the color is executed but color never changes.如果为真,则执行更改颜色的语句,但颜色永远不会改变。

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    try
    {

        Rectangle r = e.Bounds;
        r = this.tabControl1.GetTabRect(e.Index);
        r.Offset(2, 2);
        Brush TitleBrush = new SolidBrush(Color.Black);
        Brush CloseBrush = new SolidBrush(Color.Gray);
        Brush CloseBrushSelected = new SolidBrush(Color.Black);
        Font f = this.Font;
        string title = this.tabControl1.TabPages[e.Index].Text;

        e.Graphics.DrawString(title, f, TitleBrush, new PointF(r.X, r.Y));
        if (e is DrawEventArgsCustom)
        {
            if (((DrawEventArgsCustom)e) != null && ((DrawEventArgsCustom)e).HoverTrue == true)
                e.Graphics.DrawString("x", f, CloseBrushSelected, new PointF
             (r.X + (this.tabControl1.GetTabRect(e.Index).Width - _imageLocation.X), _imageLocation.Y));
        }
        e.Graphics.DrawString("x", f, CloseBrush, new PointF
              (r.X + (this.tabControl1.GetTabRect(e.Index).Width - _imageLocation.X), _imageLocation.Y));


    }
    catch (Exception ex)
    {

    }
}

private void tabControl1_MouseMove(object sender, MouseEventArgs e)
{
    Rectangle mouseRect = new Rectangle(e.X, e.Y, 1, 1);
    Graphics graphics = CreateGraphics();
    for (int i = 0; i < tabControl1.TabCount; i++)
    {
        if (tabControl1.GetTabRect(i).IntersectsWith(mouseRect))
        {

            tabControl1_DrawItem(this, new DrawEventArgsCustom(hoverTrue: true, graphics, this.Font, mouseRect, i, DrawItemState.Focus));

        }
    }
}

class DrawEventArgsCustom : DrawItemEventArgs
{


    public DrawEventArgsCustom(bool hoverTrue, Graphics graphics, Font font, Rectangle rect, int index, DrawItemState drawItemState)
        : base(graphics, font, rect, index, drawItemState)
    {
        this.HoverTrue = hoverTrue;
        this.Graph = graphics;
        this.Fnt = font;
        this.Rect = rect;
        this.ind = index;
        this.drawItemSt = drawItemState;
    }


    public bool HoverTrue { get; private set; }
    public Graphics Graph { get; private set; }
    public Font Fnt { get; private set; }
    public Rectangle Rect { get; private set; }
    public int ind { get; private set; }
    public DrawItemState drawItemSt { get; private set; }
}

No need to create new Graphics objects like that, you should do all the drawings in the DrawItem event.不需要像那样创建新的Graphics对象,您应该在DrawItem事件中完成所有绘图。 For example in this context:例如在这种情况下:

//a class level variable.
private int HoverIndex = -1;

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
    var g = e.Graphics;
    var tp = tabControl1.TabPages[e.Index];
    var rt = e.Bounds;
    var rx = new Rectangle(rt.Right - 20, (rt.Y + (rt.Height - 12)) / 2 + 1, 12, 12);

    if ((e.State & DrawItemState.Selected) != DrawItemState.Selected)
    {
        rx.Offset(0, 2);
    }

    rt.Inflate(-rx.Width, 0);
    rt.Offset(-(rx.Width / 2), 0);

    using (Font f = new Font("Marlett", 8f))
    using (StringFormat sf = new StringFormat()
    {
        Alignment = StringAlignment.Center,
        LineAlignment = StringAlignment.Center,
        Trimming = StringTrimming.EllipsisCharacter,
        FormatFlags = StringFormatFlags.NoWrap,
    })
    {
        g.DrawString(tp.Text, tp.Font ?? Font, Brushes.Black, rt, sf);
        g.DrawString("r", f, HoverIndex == e.Index ? Brushes.Black : Brushes.LightGray, rx, sf);
    }
    tp.Tag = rx;
}

Note that, now the Tag property of each TabPage control holds a rectangle for the x button.请注意,现在每个TabPage控件的Tag属性都TabPage x按钮的矩形。

In the MouseMove event iterate through the TabPages , cast the x rectangle from the Tag property, check if the x rectangle contains the current e.Location , and call Invalidate();MouseMove事件中迭代TabPages ,从Tag属性投射x矩形,检查x矩形是否包含当前的e.Location ,然后调用Invalidate(); method of the TabControl to update the drawing: TabControl更新绘图的方法:

private void tabControl1_MouseMove(object sender, MouseEventArgs e)
{
    for (int i = 0; i < tabControl1.TabCount; i++)
    {
        var rx =(Rectangle)tabControl1.TabPages[i].Tag;

        if (rx.Contains(e.Location))
        {
            //To avoid the redundant calls. 
            if (HoverIndex != i)
            {
                HoverIndex = i;
                tabControl1.Invalidate();
            }
            return;
        }
    }

    //To avoid the redundant calls.
    if (HoverIndex != -1)
    {
        HoverIndex = -1;
        tabControl1.Invalidate();
    }
}

In the MouseLeave event invalidate if necessary:如有必要,在MouseLeave事件中无效:

private void tabControl1_MouseLeave(object sender, EventArgs e)
{
    if (HoverIndex != -1)
    {
        HoverIndex = -1;
        tabControl1.Invalidate();
    }
}

And to close/dispose a page, handle the MouseUp event:要关闭/处理页面,请处理MouseUp事件:

private void tabControl1_MouseUp(object sender, MouseEventArgs e)
{
    for(int i = 0; i < tabControl1.TabCount; i++)
    {
        var rx = (Rectangle)tabControl1.TabPages[i].Tag;

        if (rx.Contains(rx.Location)) //changed e.Location to rx.Location
        {
            tabControl1.TabPages[i].Dispose();
            return;
        }                                    
    }
}

Related Posts相关文章

TabControl with Close and Add Button 带有关闭和添加按钮的 TabControl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM