Точность результатов 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 влияет на точность измерения, потому что, хотя ширина символа рассчитывается по его глифу, его рендеринг и положение настраиваются таким образом, чтобы осевые линии размещались на целых пикселях.
Просто мысль.