【问题标题】:Close button on Tab pages in WinformsWinforms 标签页上的关闭按钮
【发布时间】:2020-03-31 01:21:30
【问题描述】:

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

创建 DrawEventArgsCustom 类以指示鼠标是 将鼠标悬停在关闭按钮上。当它是真的时,声明 更改颜色已执行,但颜色永远不会改变。

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; }
}

【问题讨论】:

    标签: c# winforms tabs tabcontrol ownerdrawn


    【解决方案1】:

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

    //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;
    }
    

    请注意,现在每个TabPage 控件的Tag 属性都为x 按钮保存了一个矩形。

    MouseMove事件中遍历TabPages,从Tag属性中投射x矩形,检查x矩形是否包含当前e.Location,调用Invalidate();方法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();
        }
    }
    

    MouseLeave 事件中必要时无效:

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

    要关闭/处置页面,请处理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;
            }                                    
        }
    }
    

    相关帖子

    TabControl with Close and Add Button

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      相关资源
      最近更新 更多