C# GDI+;,从图形抽绳()中删除空白

C# GDI+;,从图形抽绳()中删除空白,c#,gdi+,C#,Gdi+,我对C#GDI+绘制字符串函数有一个问题——我无法获得绘制字符串的精确大小——没有内部前导和外部前导,只有em高度。Microsoft提供的字体/字符串度量API似乎总是输出一个比文本图形大几个像素的边界框,即使在我删除了内部前导之后也是如此 private void pictureBox1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color

我对C#GDI+绘制字符串函数有一个问题——我无法获得绘制字符串的精确大小——没有内部前导和外部前导,只有em高度。Microsoft提供的字体/字符串度量API似乎总是输出一个比文本图形大几个像素的边界框,即使在我删除了内部前导之后也是如此

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.Clear(Color.Black);
        String text = "The quick brown fox jumps over the lazy dog";
        Font font = new System.Drawing.Font(FontFamily.GenericSerif, 24);
        float internalLeading = font.Size * (font.FontFamily.GetCellAscent(font.Style) + font.FontFamily.GetCellDescent(font.Style) - font.FontFamily.GetEmHeight(font.Style)) / font.FontFamily.GetEmHeight(font.Style);
        StringFormat format = StringFormat.GenericTypographic;
        format.Trimming = StringTrimming.None;
        format.FormatFlags = StringFormatFlags.NoWrap;
        System.Drawing.RectangleF rect = new System.Drawing.RectangleF(0, 0, pictureBox1.Width,pictureBox1.Height);
        System.Drawing.CharacterRange[] ranges = { new System.Drawing.CharacterRange(0, text.Length) };
        System.Drawing.Region[] boundings = new System.Drawing.Region[1];
        format.SetMeasurableCharacterRanges(ranges);
        boundings = g.MeasureCharacterRanges(text, font, rect, format);
        rect = boundings[0].GetBounds(g);
        g.DrawString(text, font, new SolidBrush(Color.Red), new RectangleF(0,0,rect.Width,rect.Height), format);
        g.DrawRectangle(Pens.Yellow, rect.X, rect.Y + internalLeading, rect.Width, rect.Height - internalLeading);
    }
输出如下所示。我们可以看到在文本和边界框的上边缘之间仍然有一些像素


我可以通过读取图像中的像素得到绘制字符串的精确大小,并自己计算边界框。但是速度很慢。我能知道是否有一种简单的方法来解决这个问题吗?

GDI+处理的不仅仅是英语,而且行高是固定的(想象一下,如果每一行都是该行文本的高度,会有多恐怖)

边界框还解释了可以修饰这些字符的各种变音符号,包括类似的英语单词,如
COÖoperate

见:

请注意,diaresis(diaresis)(the
)
)几乎不适合在边界框内,而
ˇ
显然在外部-但在底部,有足够的空间容纳
q
。有什么好处?嗯,
MeasureString
是用于文本格式化的,而不是用于获取文本可能呈现的最小矩形-这当然会因为不应该改变文本对齐方式的事情而变得更加复杂,例如使用ClearType

该函数是基于这样一个假设构建的,即您非常希望线条具有相同的高度——这就是所有文本通常呈现的方式

要直接引用MSDN:

MeasureString方法设计用于单个字符串,并在字符串前后包含少量额外空间,以允许悬垂图示符。此外,DrawString方法会调整图示符点以优化显示质量,并且可能会显示比MeasureString报告的字符串窄的字符串


我通常可以使用排版参数。但是要得到一个像素精确的边界框,我想你需要使用GraphicsPath并获得它的边界..啊,GraphicsPath,谢谢!我会试试的!谢谢,至少现在我能理解为什么绘制字符串函数如此复杂@ncite是的,这是一个表面上看起来非常简单的非常复杂的主题,比如日期/时间(显示日期和时间有什么困难?!)或多线程:D