如何确定给定固定宽度字体和最大宽度(以像素为单位)的最大字符数

发布于 2024-08-08 07:14:06 字数 312 浏览 1 评论 0原文

给定一定数量的像素(例如:300)和字体(固定类型、固定大小,如 Consolas),我如何确定可以使用 GDI+ 绘制的最大字符数?

文本不会写入标签等,而是使用 GDI+ 绘制:

public void DrawString( string s, Font font, Brush brush, 
    RectangleF layoutRectangle, StringFormat format );

但我想在绘制之前执行某些文本操作,因此为什么我想计算出可以安全输出的最大字符数。

Given a number of pixels (say: 300) and a Font (fixed type, fixed size, like Consolas), how could I determine the maximum number of characters that I could draw with GDI+?

The text won't be written to a Label or such, but drawn using GDI+:

public void DrawString( string s, Font font, Brush brush, 
    RectangleF layoutRectangle, StringFormat format );

But I want to perform certain text operations before drawing, hence why I'd like to figure out the maximum number of chars I can safely output.

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

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

发布评论

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

评论(7

白云悠悠 2024-08-15 07:14:06

System.Drawing.Graphics 方法MeasureString 用一些额外的像素填充字符串宽度(我不知道为什么),因此测量一个固定长度字符的宽度,然后将其除以可用的最大宽度将会对适合最大宽度的字符数给出过低的估计。

要获得最大字符数,您必须执行如下迭代操作:

using (Graphics g = this.CreateGraphics())
{
    string s = "";
    SizeF size;
    int numberOfCharacters = 0;
    float maxWidth = 50;
    while (true)
    {
        s += "a";
        size = g.MeasureString(s, this.Font);
        if (size.Width > maxWidth)
        {
            break;
        }
        numberOfCharacters++;
    }
    // numberOfCharacters will now contain your max string length
}

更新:您每天都会学到新东西。 Graphics.MeasureString(和 TextRenderer)用一些额外的像素填充边界以适应悬垂的字形。有道理,但可能会很烦人。请参阅:

http://msdn.microsoft.com/en-us/library/6xe5hazb .aspx

看起来更好的方法是:

using (Graphics g = this.CreateGraphics())
{
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
    SizeF size = g.MeasureString("a", this.Font, new PointF(0, 0), 
        StringFormat.GenericTypographic);
    float maxWidth = 50; // or whatever
    int numberOfCharacters = (int)(maxWidth / size.Width);
}

The System.Drawing.Graphics method MeasureString pads string widths with a few extra pixels (I do not know why), so measuring the width of one fixed-length character and then dividing that into the maximum width available would give a too-low estimate of the number of characters that could fit into the maximum width.

To get the maximum number of characters, you'd have to do something iterative like this:

using (Graphics g = this.CreateGraphics())
{
    string s = "";
    SizeF size;
    int numberOfCharacters = 0;
    float maxWidth = 50;
    while (true)
    {
        s += "a";
        size = g.MeasureString(s, this.Font);
        if (size.Width > maxWidth)
        {
            break;
        }
        numberOfCharacters++;
    }
    // numberOfCharacters will now contain your max string length
}

Update: you learn something new every day. Graphics.MeasureString (and TextRenderer) pad the bounds with a few extra pixels to accomodate overhanging glyphs. Makes sense, but it can be annoying. See:

http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx

Looks like a better way to do this is:

using (Graphics g = this.CreateGraphics())
{
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
    SizeF size = g.MeasureString("a", this.Font, new PointF(0, 0), 
        StringFormat.GenericTypographic);
    float maxWidth = 50; // or whatever
    int numberOfCharacters = (int)(maxWidth / size.Width);
}
白首有我共你 2024-08-15 07:14:06

还有 TextRenderer.MeasureText(),它会产生不同的结果(这是绘制窗口控件时使用的结果,因此通常更准确)。

在某处有一个关于它的讨论,但我现在找不到它。

编辑: 这篇 MSDN 文章更深入一些。

There is also TextRenderer.MeasureText(), which produces a different result (this is what is used when drawing windows controls, so it is generally more accurate).

There is a discussion on SO somewhere about it, but I cannot find it at the moment.

Edit: This MSDN Article goes a little more in depth.

佼人 2024-08-15 07:14:06

我阅读了一些网站并提出了解决方案,因为

using (System.Drawing.Graphics graphics = CreateGraphics())
{
    System.Drawing.Size size = TextRenderer.MeasureText(graphics, id, e.Appearance.Font);
    if (size.Width > e.Column.Width)
    {
        int charFit = (int)(((double)e.Column.Width / (double)size.Width) * (double)id.Length);
        if (id.Length - charFit + 2 < id.Length)
        {
            e.DisplayText = string.Format("{0}{1}","...", id.Substring(id.Length - charFit + 2));
        }
    }
}

我在 DevExpress 网格视图的 CustomDrawCell 事件中进行了此更改。
如果您发现此解决方案有任何缺陷,请告诉我。

I read few sites and come up with solution as,

using (System.Drawing.Graphics graphics = CreateGraphics())
{
    System.Drawing.Size size = TextRenderer.MeasureText(graphics, id, e.Appearance.Font);
    if (size.Width > e.Column.Width)
    {
        int charFit = (int)(((double)e.Column.Width / (double)size.Width) * (double)id.Length);
        if (id.Length - charFit + 2 < id.Length)
        {
            e.DisplayText = string.Format("{0}{1}","...", id.Substring(id.Length - charFit + 2));
        }
    }
}

I did this changes in CustomDrawCell event of the DevExpress grid view.
Please let me know if you see any flaw in this solution.

话少心凉 2024-08-15 07:14:06

You could use Drawing.Graphics.MeasureString() to get the size of one of your glyphs.
Then just check how many of them fit into your drawing area.

风筝在阴天搁浅。 2024-08-15 07:14:06

如果它的宽度是固定的,为什么不只使用 Floor(pixelcount/fontwidth) 呢?

If it's fixed width why not just use floor(pixelcount/fontwidth)?

陌路终见情 2024-08-15 07:14:06

我认为 System.Drawing.Graphics.MeasureString() 可以帮助你。您可以将其与 MeasureCharacterRanges 结合使用,或测量一个字符的大小,然后除以该值的像素数。像这样的事情,你可以利用结果来让它发挥作用。我确信这将是有效的解决方案,所以如果有不清楚的地方请询问 =)

I think System.Drawing.Graphics.MeasureString() can help you. You can combine it with MeasureCharacterRanges or measure a Size of one character and then divide you number of pixels on this value. Something like this, you can play with results to get it work. I am sure that this will be working solution, so please ask if something is unclear =)

没︽人懂的悲伤 2024-08-15 07:14:06

虽然回复晚了,但我也遇到了同样的问题。

我认为你的问题的答案就在你的问题中。您提到的函数 DrawString 函数具有自动修剪长字符串的功能。查看文档 http://msdn.microsoft.com/en-us /library/19sb1bw6.aspx

该函数将修剪字符串,使其适合布局矩形。您必须将作为参数传递的 stringformat 对象的修剪属性设置为除 none 之外的其他内容。

Although this is a late reply, I came across the same issue.

I think the answer to your question is inside your question. The function DrawString function you mention has facilities to automatically trim long strings. Have a look at the docs http://msdn.microsoft.com/en-us/library/19sb1bw6.aspx.

The function will trim the string so that it fits into the layout rectangle. You have to set the trimming property of the stringformat object you pass as parameter to something other than none.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文