LinkLabel требуется больше места, чем указано в TextRenderer.MeasureText

Если я дам TextRenderer.MeasureText какой-нибудь текст для измерения и ширину для использования, он вернет высоту, необходимую для отображения этого текста.

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

Если я передам этот текст, ширину и высоту в LinkLabel, он отобразит текст с предоставленной шириной и высотой без каких-либо обрезков.

Однако, если я помещаю ссылку в коллекцию LinkLabel.Links, LinkLabel будет рисовать текст с немного большим интервалом между символами, и иногда это приведет к обрезанию конца текста. Есть ли способ предотвратить это? Я пробовал добавлять отступы, когда есть ссылка, но нет надежного способа точно узнать, сколько еще места потребуется. Есть ли другие способы сделать это?


person Mike Hall    schedule 04.06.2009    source источник


Ответы (4)


Вам следует использовать Control.GetPreferredSize метод для расчета ширины или высоты, необходимой для управления (LinkLabel в вашем случае). Вы не должны использовать MeasureText для таких целей, более подробное объяснение вы можете найти здесь (точность результатов TextRenderer.MeasureText.)

person arbiter    schedule 29.07.2009

Если LinkLabel содержит более одной ссылки или есть части текста, которые не входят в ссылку, тогда элемент управления использует Graphics.DrawString/MeasureString вместо TextRenderer.DrawText/MeasureText. Вы можете легко увидеть это в действии, самая большая разница в рендеринге - маленькая буква L:

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 
person LukeSw    schedule 29.07.2009
comment
Нет, DrawString используется только тогда, когда включен UseCompatibleTextRendering. - person Hans Passant; 29.07.2009
comment
Извините, но вы не правы. Убедитесь сами и используйте этот код: linkLabel1.Text = new string ('l', 100); // 100 маленьких L linkLabel1.LinkArea = new LinkArea (0, 50); linkLabel2.Text = новая строка ('l', 100); // 100 x маленький L - person LukeSw; 29.07.2009
comment
Ваше предложение сработало в моем тестовом приложении при тестировании обычных Labels и LinkLabels, но в моем реальном приложении метод Control.GetPreferredSize был единственным, что сработало. - person Mike Hall; 29.08.2009

TextRenderer.MeasureText - это управляемая оболочка для DrawTextEx API. Возвращаемое значение поступает из структуры lprc. Возможно, вы захотите взглянуть на этот API для получения более подробной информации.

person Jeff Moser    schedule 05.06.2009
comment
Если исправление связано с получением правильного измерения и последующим использованием элемента управления LinkLabel, кажется, что через MeasureText или DrawTextEx необходимо будет знать, что текст будет отображаться как ссылка, но ни у одного из них нет ничего подобного. Как я уже сказал в вопросе, MeasureText отлично работает, если текст будет отображаться только как чистый текст. - person Mike Hall; 05.06.2009
comment
Включен ли у вас AutoSize на LinkLabel? - person Jeff Moser; 05.06.2009

Думаю, вы могли бы удалить стиль, который подчеркивает его. linkLabel.Styles.Add("text-decoration", "none"); но тогда это, конечно, не будет похоже на ссылку. : - /

Другим решением было бы добавить прокладку самостоятельно.

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;

Не самое красивое решение, но, думаю, оно работает.

person Patrick    schedule 05.06.2009