Точность результатов TextRenderer.MeasureText

Вызов TextRenderer.MeasureText следующим образом:

TextRenderer.MeasureText(myControl.Text, myControl.Font);

и сравнение результата с размером элемента управления, чтобы проверить, подходит ли текст. Результаты иногда неверны. Наблюдали следующие две проблемы:

  • Часто, когда для Label установлено значение AutoSize, TextRenderer сообщает о ширине, которая на 1 пиксель превышает ширину элемента управления с автоматическими размерами.
  • Ложный минус, когда TextRenderer сообщает, что ширина меньше, чем у элемента управления, но текст все еще обрезан. Это произошло с "Estación de trabajo" - не уверен, что акцент может как-то повлиять на вычисление ширины?

Есть ли способ повысить точность метода MeasureText? Должен ли я вызывать одно из переопределений, которое принимает контекст устройства и / или флаги формата?

5 ответов

Решение

Есть ли способ повысить точность метода MeasureText? Должен ли я вызывать одно из переопределений, которое принимает контекст устройства и / или флаги формата?

Вы сами ответили на свой вопрос. На самом деле MeasureText основан на Win32 DrawTextEx, и эта функция не может работать без допустимого контекста устройства. Поэтому, когда вы вызываете переопределение MeasureText без HDC, он внутренне создает HDC, совместимый с рабочим столом, для проведения измерений.

Конечно, измерение зависит от дополнительных TextFormatFlags. Также имейте в виду, что рисование меток (и измерение) зависит от UseCompatibleTextRendering.

Итак, общий вывод: вы должны использовать MeasureText для своего собственного кода, например, когда вы затем вызываете DrawText с точно такими же параметрами, во всех других случаях размер, возвращаемый MeasureText, не может рассматриваться как точный.

Если вам нужно получить ожидаемый размер метки, вы должны использовать метод GetPreferredSize.

Я знаю, что это, вероятно, больше не актуально. Но для будущих читателей здесь есть простой, но точный метод измерения текста в элементе управления:

Graphics g=Graphics.FromHwnd(YOUR CONTROL HERE.Handle);
SizeF s=g.MeasureString("YOUR STRING HERE", Font, NULL, NULL, STRING LENGTH HERE, 1)

Проверьте параметр TextFormatFlags для этой функции:

TextRenderer::MeasureText(String, Font, Size, TextFormatFlags) 

http://msdn.microsoft.com/en-us/library/8wafk2kt.aspx

"Размер текста в пикселях, нарисованного на одной строке с указанным шрифтом. Вы можете управлять способом рисования текста, используя одну из перегрузок DrawText, которая принимает параметр TextFormatFlags. Например, поведение TextRenderer по умолчанию: чтобы добавить отступы к ограничивающему прямоугольнику нарисованного текста для размещения нависающих глифов. Если вам нужно нарисовать линию текста без этих лишних пробелов, вы должны использовать версии DrawText и MeasureText, которые принимают параметр Size и TextFormatFlags. Например, см. MeasureText(IDeviceContext, String, Font, Size, TextFormatFlags)."

НТН

Я не знаю, есть ли у меня идеальное решение, но я столкнулся с этим, когда делал WinForms несколько лет назад. В итоге я получил компенсацию, настроив возвращаемое измерение в процентах. Я не могу вспомнить, что я использовал (может быть, 5% или 105?), Но я помню, что я использовал постоянный процент в приложении и всегда округлялся.

У меня еще недостаточно баллов, чтобы прокомментировать, поэтому мне пришлось поставить это как ответ:

Возможно, ClearType влияет на точность измерения, потому что, хотя ширина символа рассчитывается по его глифу, его рендеринг и положение настраиваются таким образом, чтобы осевые линии размещались на целых пикселях.

Просто мысль.

Другие вопросы по тегам