Winforms 标签页上的关闭按钮 [英] Close button on Tab pages in Winforms

查看:36
本文介绍了Winforms 标签页上的关闭按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 TabControl 的标签页上添加关闭按钮将关闭按钮的颜色从浅灰色更改为黑色鼠标悬停在它上面.但是,颜色永远不会改变.

创建 DrawEventArgsCustom 类以指示鼠标在悬停在关闭按钮上.当它为真时,声明为改变颜色被执行,但颜色永远不会改变.

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e){尝试{矩形 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);字体 f = this.Font;字符串标题 = this.tabControl1.TabPages[e.Index].Text;e.Graphics.DrawString(title, f, TitleBrush, new PointF(r.X, r.Y));if (e 是 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));}捕获(异常前){}}private void tabControl1_MouseMove(object sender, MouseEventArgs e){矩形 mouseRect = new Rectangle(e.X, e.Y, 1, 1);图形图形 = CreateGraphics();for (int i = 0; i 

解决方案

不需要像那样创建新的 Graphics 对象,您应该在 DrawItem 中完成所有绘图事件.例如在这种情况下:

//一个类级别的变量.private int HoverIndex = -1;private void tabControl1_DrawItem(对象发送者,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);使用 (Font f = new Font(Marlett", 8f))使用 (StringFormat sf = new StringFormat(){对齐 = StringAlignment.Center,LineAlignment = StringAlignment.Center,修剪 = 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;}

请注意,现在每个 TabPage 控件的 Tag 属性都包含一个用于 x 按钮的矩形.

MouseMove 事件中遍历TabPages,从Tag 属性中投射x 矩形,检查如果x矩形包含当前e.Location,则调用TabControlInvalidate();方法更新绘图:

private void tabControl1_MouseMove(object sender, MouseEventArgs e){for (int i = 0; i 

必要时在 MouseLeave 事件中无效:

private void tabControl1_MouseLeave(object sender, EventArgs e){如果(悬停索引!= -1){悬停指数 = -1;tabControl1.Invalidate();}}

要关闭/处理页面,请处理 MouseUp 事件:

private void tabControl1_MouseUp(object sender, MouseEventArgs e){for(int i = 0; i 

<块引用>

相关帖子

带有关闭和添加按钮的 TabControl

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. However, the color never changes.

The DrawEventArgsCustom class is created to indicate that the mouse is hovering over the close button. 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. 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.

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(); method of the TabControl to update the drawing:

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:

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:

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

这篇关于Winforms 标签页上的关闭按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆