簡體   English   中英

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

[英]Why doesn't TextRenderer.MeasureText work properly?

我想測量給定可用畫布寬度的文本高度。 我傳入的文本很長,我知道會自動換行。 為此,我稱之為:

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。

我錯過了一些簡單的東西嗎?

請使用TextFormatFlags度量參數,如下所示:

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

DimitryG 的解決方案似乎很好用,但前提是沒有足夠大的詞來填充整行。 如果存在這樣的詞,則寬度將大於建議的寬度。 在這種情況下有標志TextFormatFlags.EndEllipsis ,但是我沒有設法以某種方式組合標志所以輸出是正確的(如果我使用TextFormatFlags.WordEllipsis | TextFormatFlags.WordBreak寬度是正確的,但高度不是在出現單詞省略號時更新,這意味着大單詞將被修剪,但高度將與未修剪的高度相同)。 我還嘗試了標志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;
}

然而,這種方法有一個問題:當且僅當TextBox Multiline屬性設置為true ,每個Font都會有自己的左右填充。 有關更多詳細信息,請參閱此 stackoverflow.com 問題此 social.msdn.microsoft.com 問題 所以這意味着在某些情況下返回的值可能比預期的要大。 解決這個問題可以使用SetPadding函數去除padding(可以在第一個問題中找到該方法作為答案),代碼:

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;

我希望這有幫助。 如果我犯了任何錯誤,對不起我的英語。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM