在不使用Graphics对象的情况下测量String?

时间:2023-02-09 15:19:37

I am using pixels as the unit for my font. In one place, I am performing a hit test to check if the user has clicked within the bounding rectangle of some text on screen. I need to use something like MeasureString for this. Unfortunately, the code doing the hit test is deep within a library which does not have access to a Graphics object or even a Control.

我使用像素作为我的字体的单位。在一个地方,我正在执行命中测试以检查用户是否在屏幕上的某些文本的边界矩形内单击。我需要使用像MeasureString这样的东西。不幸的是,执行命中测试的代码深入到一个库中,该库无法访问Graphics对象甚至Control。

How do I get the bounding box of a string given the font without using the Graphics class? Why do I even need a Graphics object when my font is in pixels?

如何在不使用Graphics类的情况下获取给定字体的字符串的边界框?为什么我的字体以像素为单位时甚至需要一个Graphics对象?

5 个解决方案

#1


If you have a reference to System.Windows.Forms, try using the TextRenderer class. There is a static method (MeasureText) which takes the string and font and returns the size. MSDN Link

如果您有对System.Windows.Forms的引用,请尝试使用TextRenderer类。有一个静态方法(MeasureText),它接受字符串和字体并返回大小。 MSDN链接

#2


You don't need to use the graphics object that you are using to render to do the measuring. You could create a static utility class:

您不需要使用用于渲染的图形对象来进行测量。您可以创建一个静态实用程序类:

public static class GraphicsHelper
{
    public static SizeF MeasureString(string s, Font font)
    {
        SizeF result;
        using (var image = new Bitmap(1, 1))
        {
            using (var g = Graphics.FromImage(image))
            {
                result = g.MeasureString(s, font);
            }
        }

        return result;
    }
}

It might be worthwile, depending on your situation to set the dpi of the bitmap as well.

可能值得,根据您的情况设置位图的dpi。

#3


MeasureString method in @NerdFury answer will give a higher string width than expected.Additional info you can find here. If you want to measure only the physical length please add this two lines :

@NerdFury答案中的MeasureString方法将提供比预期更高的字符串宽度。您可以在此处找到其他信息。如果您只想测量物理长度,请添加以下两行:

g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
result = 
  g.MeasureString(measuredString, font, int.MaxValue, StringFormat.GenericTypographic);

#4


This example does great job of illustrating the use of FormattedText. FormattedText provides low-level control for drawing text in Windows Presentation Foundation (WPF) applications. You can use it to measure the Width of a string with a particular Font without using a Graphics object.

这个例子很好地说明了FormattedText的使用。 FormattedText为Windows Presentation Foundation(WPF)应用程序中的绘图文本提供低级控件。您可以使用它来测量具有特定Font的字符串的宽度,而无需使用Graphics对象。

public static float Measure(string text, string fontFamily, float emSize)
{
    FormattedText formatted = new FormattedText(
        item, 
        CultureInfo.CurrentCulture, 
        System.Windows.FlowDirection.LeftToRight, 
        new Typeface(fontFamily), 
        emSize, 
        Brushes.Black);

    return formatted.Width;
}

Include WindowsBase and PresentationCore libraries.

包括WindowsBase和PresentationCore库。

#5


This may not be but a repeat of others, but my problem was the unwanted Graphics object as well. After listening to the above frustrations I simply tried:

这可能不是其他人的重复,但我的问题也是不需要的Graphics对象。在听完上述挫折之后,我只是尝试了:

Size proposedSize = new Size(int.MaxValue, int.MaxValue);
TextFormatFlags flags = TextFormatFlags.NoPadding;
Size ressize = TextRenderer.MeasureText(content, cardfont, proposedSize, flags);

(where 'content' is the string to measure and cardfont the font it is in)

(其中'content'是要测量的字符串,cardfont是它所在的字体)

... and was in luck. I could use the result to set the width of my column in VSTO.

......并且很幸运。我可以使用结果在VSTO中设置列的宽度。

#1


If you have a reference to System.Windows.Forms, try using the TextRenderer class. There is a static method (MeasureText) which takes the string and font and returns the size. MSDN Link

如果您有对System.Windows.Forms的引用,请尝试使用TextRenderer类。有一个静态方法(MeasureText),它接受字符串和字体并返回大小。 MSDN链接

#2


You don't need to use the graphics object that you are using to render to do the measuring. You could create a static utility class:

您不需要使用用于渲染的图形对象来进行测量。您可以创建一个静态实用程序类:

public static class GraphicsHelper
{
    public static SizeF MeasureString(string s, Font font)
    {
        SizeF result;
        using (var image = new Bitmap(1, 1))
        {
            using (var g = Graphics.FromImage(image))
            {
                result = g.MeasureString(s, font);
            }
        }

        return result;
    }
}

It might be worthwile, depending on your situation to set the dpi of the bitmap as well.

可能值得,根据您的情况设置位图的dpi。

#3


MeasureString method in @NerdFury answer will give a higher string width than expected.Additional info you can find here. If you want to measure only the physical length please add this two lines :

@NerdFury答案中的MeasureString方法将提供比预期更高的字符串宽度。您可以在此处找到其他信息。如果您只想测量物理长度,请添加以下两行:

g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
result = 
  g.MeasureString(measuredString, font, int.MaxValue, StringFormat.GenericTypographic);

#4


This example does great job of illustrating the use of FormattedText. FormattedText provides low-level control for drawing text in Windows Presentation Foundation (WPF) applications. You can use it to measure the Width of a string with a particular Font without using a Graphics object.

这个例子很好地说明了FormattedText的使用。 FormattedText为Windows Presentation Foundation(WPF)应用程序中的绘图文本提供低级控件。您可以使用它来测量具有特定Font的字符串的宽度,而无需使用Graphics对象。

public static float Measure(string text, string fontFamily, float emSize)
{
    FormattedText formatted = new FormattedText(
        item, 
        CultureInfo.CurrentCulture, 
        System.Windows.FlowDirection.LeftToRight, 
        new Typeface(fontFamily), 
        emSize, 
        Brushes.Black);

    return formatted.Width;
}

Include WindowsBase and PresentationCore libraries.

包括WindowsBase和PresentationCore库。

#5


This may not be but a repeat of others, but my problem was the unwanted Graphics object as well. After listening to the above frustrations I simply tried:

这可能不是其他人的重复,但我的问题也是不需要的Graphics对象。在听完上述挫折之后,我只是尝试了:

Size proposedSize = new Size(int.MaxValue, int.MaxValue);
TextFormatFlags flags = TextFormatFlags.NoPadding;
Size ressize = TextRenderer.MeasureText(content, cardfont, proposedSize, flags);

(where 'content' is the string to measure and cardfont the font it is in)

(其中'content'是要测量的字符串,cardfont是它所在的字体)

... and was in luck. I could use the result to set the width of my column in VSTO.

......并且很幸运。我可以使用结果在VSTO中设置列的宽度。