1

我有 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 像素会看起来很奇怪......

提前致谢。

问候,

理查德

4

2 回答 2

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

于 2010-10-30T01:38:20.113 回答
0

好吧,我现在已经找到了如何获取一段文本的长度......我使用了以下内容:

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

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

问候,

理查德

于 2010-10-30T00:54:20.393 回答