代码之家  ›  专栏  ›  技术社区  ›  ClarkeyBoy

C GroupBox-自定义边框/标题的外观

  •  1
  • ClarkeyBoy  · 技术社区  · 14 年前

    我有两个分组框,我想定制更多,我不想诉诸于有一个带标签的面板(这意味着如果我想要一个边框,我必须有相同的面板和父控件的背景色,因为标签必须有一个颜色设置来覆盖文本后面的边框)。

    我通过捕捉油漆事件并使用以下代码成功地改变了边框颜色:

    Graphics gfx = e.Graphics;
    Pen p = new Pen(Color.FromArgb(86, 136, 186), 3);
    
    GroupBox gb = (GroupBox)sender;
    Rectangle r = new Rectangle(0, 0, gb.Width, gb.Height);
    
    gfx.DrawLine(p, 0, 5, 0, r.Height - 2);
    gfx.DrawLine(p, 0, 5, 10, 5);
    gfx.DrawLine(p, 62, 5, r.Width - 2, 5);
    gfx.DrawLine(p, r.Width - 2, 5, r.Width - 2, r.Height - 2);
    gfx.DrawLine(p, r.Width - 2, r.Height - 2, 0, r.Height - 2);
    

    我的问题是,像这样,如果标题太长,那么它会与边框重叠。因为它与顶部的左侧边界重叠,所以只需调整第二个边界就可以轻松解决问题。 DrawLine 线。不过,我想检测文本的x和宽度测量值,以便正确定位边框。

    有人知道怎么做吗?我已经在谷歌上搜索了一段时间,但没有什么能跳出来。我知道标题是通过 GroupBox.Text .

    另外,如果我需要其他的测量方法,我也在改变边框厚度的基础上,所以如果字体很小,但是边框从下半部分开始是10个像素,看起来会很奇怪…

    事先谢谢。

    当做,

    理查德

    2 回复  |  直到 14 年前
        1
  •  2
  •   steinar Justin CI    14 年前

    很容易得到绳子的大小,我看你已经知道了。但是我认为子类化控件要容易得多,允许更好的外观 为您提供设计时支持。下面是一个例子:

    public class GroupBoxEx : GroupBox
    {
        SizeF sizeOfText;
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            CalculateTextSize();            
        }
    
        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            CalculateTextSize();
        }
    
        protected void CalculateTextSize()
        {
            // measure the string:
            using (Graphics g = this.CreateGraphics())
            {
                sizeOfText = g.MeasureString(Text, Font);
            }
            linePen = new Pen(Color.FromArgb(86, 136, 186), sizeOfText.Height * 0.1F);
        }
    
        Pen linePen;
    
        protected override void OnPaint(PaintEventArgs e)
        {
            // Draw the string, we now have complete control over where:
    
            Rectangle r = new Rectangle(ClientRectangle.Left + Margin.Left, 
                ClientRectangle.Top + Margin.Top, 
                ClientRectangle.Width - Margin.Left - Margin.Right, 
                ClientRectangle.Height - Margin.Top - Margin.Bottom);
    
            const int gapInLine = 2;
            const int textMarginLeft = 7, textMarginTop = 2;
    
            // Top line:
            e.Graphics.DrawLine(linePen, r.Left, r.Top, r.Left + textMarginLeft - gapInLine, r.Top);
            e.Graphics.DrawLine(linePen, r.Left + textMarginLeft + sizeOfText.Width, r.Top, r.Right, r.Top);
            // and so on...
    
            // Now, draw the string at the desired location:            
            e.Graphics.DrawString(Text, Font, Brushes.Black, new Point(this.ClientRectangle.Left + textMarginLeft, this.ClientRectangle.Top - textMarginTop));
        }
    }
    

    你会注意到控件不再绘制自己了,你负责整个过程。这可以让你确切地知道文本的绘制位置——你自己绘制。

    (还要注意,该行是字符串高度的1/10。)

        2
  •  0
  •   ClarkeyBoy    14 年前

    好吧,我现在已经知道如何得到一段文字的长度…我使用了以下方法:

    SizeF textsize = gfx.MeasureString(gb.Text, gb.Font);
    

    其中gfx是图形,gb是分组框。不过,我认为只要编写继承自panel的自定义类,在其中添加一个标签,就可以让它将标签1、5、10、200、254等像素放入其中。甚至是一个百分比。我还发现我无法覆盖标准边框-如果我的边框是1px,它仍然显示通过我添加的边框-使用GroupBox的另一个缺点。

    当做,

    理查德