TextRenderer.MeasureText 和 Graphics.MeasureString 大小不匹配

发布于 2024-11-24 16:50:20 字数 394 浏览 1 评论 0原文

这不是舍入问题。差异 ~ 5+ 像素。

测试用例字符串:“”MACD(26,12,9)-0.000016”

e.Graphics.MeasureString("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)
TextRenderer.MeasureText("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)

结果总是:

139.3942
134

为什么大小差异如此之大?我只需要在paint方法之外对字符串宽度进行舍入。但它应该匹配 MeasureString 或反之亦然。

This is not a rounding problem. Difference ~ 5+ pixels.

Test Case String: ""MACD (26,12,9) -0.000016"

e.Graphics.MeasureString("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)
TextRenderer.MeasureText("MACD (26,12,9) -0.000016", SystemFonts.DefaultFont).Width)

The result is always:

139.3942
134

Why is there so much difference in size? I just need the round of width of string outside paint method. But it should match MeasureString or vice versa.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深爱不及久伴 2024-12-01 16:50:20

TextRenderer 使用 GDI 渲染文本,而 Graphics 使用 GDI+。两者使用稍微不同的方法来布局文本,因此大小不同。

您应该使用哪一种取决于最终用于实际绘制文本的内容。如果您使用 GDI+ Graphics.DrawString 进行绘制,请使用 Graphics.MeasureString 进行测量。如果您使用 GDI TextRenderer.DrawText 进行绘制,请使用 TextRenderer.MeasureText 进行测量。

如果文本将显示在 Windows 窗体控件内,则当 UseCompatibleTextRendering 设置为 false(这是默认值)时,它将使用 TextRenderer

阅读问题的字里行间,您似乎正在使用 TextRenderer 因为您在 Paint 事件之外没有 Graphics 实例。如果是这种情况,您可以自己创建一个来进行测量:

using( Graphics g = someControl.CreateGraphics() )
{
    SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

如果您无权访问控件来创建图形实例,您可以使用它为屏幕创建一个实例,这对于测量目的来说效果很好。

using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
     SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

TextRenderer uses GDI to render the text, whereas Graphics uses GDI+. The two use a slightly different method for laying out text so the sizes are different.

Which one you should use depends on what will eventually be used to actually draw the text. If you are drawing it with GDI+ Graphics.DrawString, measure using Graphics.MeasureString. If you are drawing using GDI TextRenderer.DrawText, measure using TextRenderer.MeasureText.

If the text will be displayed inside a Windows Forms control, it uses TextRenderer if UseCompatibleTextRendering is set to false (which is the default).

Reading between the lines of your question, you seem to be using TextRenderer because you don't have a Graphics instance outside the Paint event. If that's the case, you can create one yourself to do the measuring:

using( Graphics g = someControl.CreateGraphics() )
{
    SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}

If you don't have access to a control to create the graphics instance you can use this to create one for the screen, which works fine for measurement purposes.

using( Graphics g = Graphics.FromHwnd(IntPtr.Zero) )
{
     SizeF size = g.MeasureString("some text", SystemFonts.DefaultFont);
}
蓦然回首 2024-12-01 16:50:20

我创建了以下类来在绘制事件之外使用 MeasureString,并且效果非常好。

public interface ITextMeasurer
    {
        SizeF MeasureString(string text, Font font, StringFormat format);
    }

    public class TextMeasurer : ITextMeasurer
    {
        private readonly Image _fakeImage;
        private readonly Graphics _graphics;

        public TextMeasurer()
        {
            _fakeImage = new Bitmap(1, 1);
            _graphics = Graphics.FromImage(_fakeImage);
        }

        public SizeF MeasureString(string text, Font font, StringFormat format)
        {
            return _graphics.MeasureString(text, font, int.MaxValue, format);
        }
    }

I Made the following class to use MeasureString outside the paint event, and it works pretty well.

public interface ITextMeasurer
    {
        SizeF MeasureString(string text, Font font, StringFormat format);
    }

    public class TextMeasurer : ITextMeasurer
    {
        private readonly Image _fakeImage;
        private readonly Graphics _graphics;

        public TextMeasurer()
        {
            _fakeImage = new Bitmap(1, 1);
            _graphics = Graphics.FromImage(_fakeImage);
        }

        public SizeF MeasureString(string text, Font font, StringFormat format)
        {
            return _graphics.MeasureString(text, font, int.MaxValue, format);
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文