views:

422

answers:

4

If I give TextRenderer.MeasureText some text to measure and width to use it will return the height needed to display that text.

private static int CalculateHeight(string text, Font font, int width)
{
    Size size = TextRenderer.MeasureText(text, font, new Size(width, Int32.MaxValue), TextFormatFlags.NoClipping | TextFormatFlags.WordBreak);
    return size.Height;
}

If I give that text, width and height to a LinkLabel it would display the text in the width and height provided with nothing clipped off.

However, if I put a Link into the LinkLabel.Links collection, the LinkLabel will draw the text with what appears to be a little more spacing between the characters and at times this will cause the end of the text to be clipped. Is there anyway to prevent this? I've tried adding padding when there is a link, but there's no reliable way to know exactly how much more space will be needed. Are there any other ways to do this?

A: 

TextRenderer.MeasureText is a managed wrapper for the DrawTextEx API. The value returned comes from the lprc struct. You might want to look at that API for more details.

Jeff Moser
If the fix involves get a correct measurement and then still using the LinkLabel control, it seems as through either MeasureText or DrawTextEx would need to be made aware that the text will be displayed as a link, but neither has anything like that. As I said in the question, MeasureText works fine if the text will only be displayed as pure text.
Mike Hall
Do you have AutoSize enabled on the LinkLabel?
Jeff Moser
No, I do not...
Mike Hall
A: 

I guess you could remove the style that makes it underline. linkLabel.Styles.Add("text-decoration", "none"); but then of course it wouldn't look like a link. :-/

Another solution would be to add the padding yourself I guess.

int heightBefore = linkLabel.Height;
int fontHeight = CalculateHeight(linkLabel.Text, linkLabel.Font, linkLabel.Width);
int paddingHeight = heightBefore - fontHeight;
linkLabel.Font = otherFont;
linkLabel.Height = CalculateHeight(linkLabel.Text, otherFont, linkLabel.Width);
linkLabel.Height += paddingHeight;

Not the prettiest of solutions, but I would guess it works.

Patrick
+1  A: 

If a LinkLabel contains more than one link, or there are parts of text which are nor in a link, then the control uses Graphics.DrawString/MeasureString instead of TextRenderer.DrawText/MeasureText. You can easily see it in action, the biggest difference in rendering is with the small L letter:

linkLabel1.Text = new string('l', 100); // 100 x small L
linkLabel1.LinkArea = new LinkArea(0, 50);
linkLabel2.Text = new string('l', 100); // 100 x small L
LukeSw
No, DrawString is only used when UseCompatibleTextRendering is turned on.
Hans Passant
I am sorry, but you are not correct. See for yourself and use this code:linkLabel1.Text = new string('l', 100); // 100 x small LlinkLabel1.LinkArea = new LinkArea(0, 50);linkLabel2.Text = new string('l', 100); // 100 x small L
LukeSw
Your suggestion worked in my test app when testing regular Labels and LinkLabels, but in my real application the Control.GetPreferredSize method was the only thing that worked.
Mike Hall
+2  A: 

You should use Control.GetPreferredSize method to calculate width or height needed for control (LinkLabel in your case). You should not use MeasureText for such purposes, more detailed explanation you can find here (Accuracy of TextRenderer.MeasureText results.)

arbiter