为什么TextRenderer.MeasureText不能正常工作?

问题描述 投票:5回答:2

我想根据给定的可用画布宽度来测量文本的高度。我传递的文字非常长,我知道会自动换行。为此,我称呼以下:

using System.Windows.Forms;
...
string text = "Really really long text that is sure to wrap...";
Font font = new Font("Arial", 14);
Size canvas = new Size(1100, 850);
Size size = TextRenderer.MeasureText(text, font, canvas);

无论我为画布传递什么,它总是为size.Height返回14。

我想念一些简单的东西吗?

c# .net winforms .net-4.0 textrenderer
2个回答
5
投票

请使用如下所示的TextFormatFlags测量参数:

Size size = TextRenderer.MeasureText(text, font, canvas, TextFormatFlags.WordBreak);

0
投票

DimitryG的解决方案似乎很好用,但是仅当没有一个单词能填满整个行时才有用。如果存在这样的单词,则宽度将大于建议的宽度。在这种情况下有标志TextFormatFlags.EndEllipsis,但是我没有设法以某种方式组合标志以使输出正确(如果我使用TextFormatFlags.WordEllipsis | TextFormatFlags.WordBreak则宽度正确,但是Word Ellipsis时高度不会更新发生,这意味着大词将被修剪,但高度将与未修剪的高度相同)。我也尝试了标志TextFormatFlags.EndEllipsis,但没有结果。

所以直到有人清楚这一点之前,我建议使用TextBox进行自动换行,然后将TextBox中的行数乘以Font的高度。

代码:

int MeasureMultilineTextHeigh(string text, Font font, int proposedWidth)
{
    // Exception handling.

    TextBox textBox = new TextBox()
    {
        Multiline = true,
        BorderStyle = BorderStyle.None,
        Width = proposedWidth,
        Font = font,
        Text = text,
    };

    int lineCount = textBox.GetLineFromCharIndex(int.MaxValue) + 1;
    int fontHeight = TextRenderer.MeasureText("X", font).Height;

    return lineCount * fontHeight;
}

[但是,这种方法有一个问题:只有当MultilineTextBox属性设置为true时,每个Font才会有自己的左右填充。有关更多详细信息,请参见this stackoverflow.com questionthis social.msdn.microsoft.com question。因此,这意味着在某些情况下返回的值可能会大于预期值。要解决此问题,您可以使用SetPadding函数删除填充(您可以在第一个问题中找到该方法作为答案),代码:

private const int EM_SETRECT = 0xB3;

[DllImport(@"User32.dll", EntryPoint = @"SendMessage", CharSet = CharSet.Auto)]
private static extern int SendMessageRefRect(IntPtr hWnd, uint msg, int wParam, ref RECT rect);

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
    public readonly int Left;
    public readonly int Top;
    public readonly int Right;
    public readonly int Bottom;

    private RECT(int left, int top, int right, int bottom)
    {
        Left = left;
        Top = top;
        Right = right;
        Bottom = bottom;
    }

    public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
}

public void SetPadding(TextBox textBox, Padding padding)
{
    var rect = new Rectangle(padding.Left, padding.Top, textBox.ClientSize.Width - padding.Left - padding.Right, textBox.ClientSize.Height - padding.Top - padding.Bottom);
    RECT rc = new RECT(rect);
    SendMessageRefRect(textBox.Handle, EM_SETRECT, 0, ref rc);
}

int MeasureMultilineTextHeigh(string text, Font font, int proposedWidth)
{
    // Exception handling.

    TextBox textBox = new TextBox()
    {
        Multiline = true,
        BorderStyle = BorderStyle.None,
        Width = proposedWidth,
        Font = font,
    };
    SetPadding(textBox, Padding.Empty);
    textBox.Text = text;

    int lineCount = textBox.GetLineFromCharIndex(int.MaxValue) + 1;
    int fontHeight = TextRenderer.MeasureText("X", font).Height;

    return lineCount * fontHeight;
}

需要使用语句:

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;

我希望这会有所帮助。如果我有任何错误,对不起,我的英语。

© www.soinside.com 2019 - 2024. All rights reserved.