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

时间:2010-10-30 00:29:58

标签: c# caption groupbox

我有2个分组框,我想自定义一点,我不想诉诸于带有标签的面板(这意味着我必须为面板和父母具有相同的背景颜色控制我是否想要一个边框,因为标签必须有一个颜色设置来掩盖文本背后的边框。

我设法通过捕获绘制事件并使用以下代码来更改边框颜色:

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 个答案:

答案 0 :(得分:2)

很容易得到字符串的大小,正如我发现你已经发现的那样。但我认为对控件进行子类化会更容易,允许更好的外观为您提供设计时支持。这是一个例子:

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。)

答案 1 :(得分:0)

我现在已经知道如何获取一段文字的长度......我使用了以下内容:

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

其中gfx是Graphics,gb是GroupBox。但是我认为编写我自己的继承自Panel的自定义类可能是值得的,为它添加一个标签,然后我就可以告诉它将标签放置1,5,10,200,254等像素。或者甚至一个百分比。我还发现我无法覆盖标准边框 - 如果我的边框是1px,它仍会通过我添加的边框显示 - 使用GroupBox的另一个缺点。

此致

理查德