C# 不使用图形对象测量字符串?

C# 不使用图形对象测量字符串?,c#,text,fonts,gdi+,C#,Text,Fonts,Gdi+,我使用像素作为我的字体单位。在一个地方,我正在执行命中测试,以检查用户是否在屏幕上某些文本的边框内单击。为此,我需要使用类似于MeasureString的方法。不幸的是,执行命中测试的代码深入到一个库中,该库无法访问图形对象,甚至无法访问控件 如何在不使用Graphics类的情况下获得给定字体的字符串的边界框?当我的字体以像素为单位时,为什么我甚至需要一个图形对象?如果您有System.Windows.Forms的引用,请尝试使用TextRenderer类。有一个静态方法(MeasureText

我使用像素作为我的字体单位。在一个地方,我正在执行命中测试,以检查用户是否在屏幕上某些文本的边框内单击。为此,我需要使用类似于
MeasureString
的方法。不幸的是,执行命中测试的代码深入到一个库中,该库无法访问
图形
对象,甚至无法访问
控件


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

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

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

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;
    }
}

根据您的情况,也可以设置位图的dpi。@NerdFury answer中的MeasureString方法将提供比预期更高的字符串宽度。您可以找到其他信息。如果只想测量物理长度,请添加以下两行:

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

这个例子很好地说明了格式化文本的使用。格式化文本为Windows演示基础(WPF)应用程序中的文本提供低级控制。您可以使用它来测量具有特定字体的字符串的宽度,而无需使用图形对象

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;
}

包括WindowsBase和PresentationCore库。

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

Size proposedSize = new Size(int.MaxValue, int.MaxValue);
TextFormatFlags flags = TextFormatFlags.NoPadding;
Size ressize = TextRenderer.MeasureText(content, cardfont, proposedSize, flags);
(其中“content”是要测量的字符串,cardfont是它所在的字体)


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

如果没有控件,您有什么功能?我假设是字体和字符串,但是还有别的吗?没有别的。我的图书馆是一种风景画。我试图避免对System.Drawing和System.Windows.FormsLook的依赖,但我认为不允许使用新位图(0,0),可能是(1,1)@AlexanderN我刚刚确认位图(0,0)无效。位图(1,1)的解决方案是正确的。图像对象可以是静态的,以避免每次重新创建对象。使用Graphics.FromHwnd(IntPtr.Zero)可避免创建位图。TextRenderer的一个小问题是,它使用整数作为返回值,如果需要亚像素精度,可能会导致问题。否则,这是一个很好的选择。这是如何解决的?链接中的示例显示
TextRenderer.DrawText(e.Graphics,
@jp2code-你读过我的答案吗?他问我如何在不使用Graphics类的情况下测量字符串。我建议在TextRenderer类上使用MeasureText方法。它回答了他的问题,我甚至提供了指向这个类的MSDN文档的链接。再看一看。@jp2code不知道你是否仍然在意,但我知道reText使用一个内部类
WindowsGraphicsCacheManager
。管理器有一个静态
MeasurementGraphics
属性,该属性在第一次使用时就被初始化。它通过使用PInvoke从设备上下文创建一个图形到gdi32.dll来实现。NerdFury的答案最终使用,当然图形不会被缓存但除此之外,它们是same@Jarrod嗯,我喜欢将表单相关的代码与绘图相关的代码分开,并与除了C#等之外没有依赖关系的代码分开。可能我正在将文本渲染到图像或命令行程序或服务中的某个东西。没有理由我需要对windows表单的引用,除了pt文本渲染器由于某种原因而存在,而不是在System.Drawing中。