TextOutW по-разному отображается на экране и на принтере

У нас есть приложение VB6, используемое для печати, которое мы не можем переписать в .NET в настоящее время. :) Проблема, которую мы пытаемся решить, заключается в том, что печатный текст не соответствует в точности предварительному просмотру пользовательского интерфейса. У нас есть настраиваемый элемент управления текстовым полем, который самостоятельно обрабатывает рисование и печать с помощью ExtTextOut и TextOut соответственно. Их вывод должен быть одинаковым, но при таком же шрифте текст на экране или на принтере может быть больше. Высота идеальная, отличается только интервал и ширина символов. Я еще не уверен, что это проблема кернинга шрифтов, но разница действительно зависит от DPI принтера как для интервала, так и для ширины символов. Чем выше DPI, тем больше разница. 4000 точек на дюйм делает символы чуть тоньше. Но я мог быть уверен, что мы где-то неправильно обрабатываем DPI.

Следующий код относится к печатающей стороне вещей, которая устанавливает шрифт и печатает некоторый текст.

fntHeight = MulDiv(m_Font.SIZE, GetDeviceCaps(printerDC, LOGPIXELSY), 72)

fnt = CreateFont(-fntHeight, 0, escapement, escapement, FW_BOLD, Font.Italic, Font.Underline, _
Font.Strikethrough, Font.Charset, 0, CLIP_LH_ANGLES, FontQuality, 0, Font.Name)

SelectObject(printerDC, fnt)

TextOutW(printerDC, x, y, StrPtr(strOutputText), Len(strOutputText))

Код рисования для пользовательского интерфейса почти такой же. Пользователи видят проблему: пользовательский интерфейс не является хорошим индикатором для определения того, когда размер текстового поля слишком мал, потому что, если текст на DC принтера немного шире, чем DC экрана, последний символ, например точка, обрезается.

Эта разница зависит от размера шрифта, и для 28 разница равна 0. Она может легко варьироваться от +14 до -14, при этом ширина напечатанного или раскрашенного текста будет больше. Мне пока не удалось выяснить, что заставляет TextOut, ExtTextOut и GetTextExtentPoint32 давать разные результаты.

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

' Call GetTextExtentPoint32W(hdc, StrPtr(strText), Len(strText), textSize)
printerTextWidth = TextWidthU(printerDC, strOutputText) * (screenXdpi / printerXdpi)
screenTextWidth = TextWidthU(UserControl.hdc, strOutputText)
totalDifference = printerTextWidth - screenTextWidth
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
192
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Растеризатор текста выравнивает все символы по границам пикселей. Например, буква «i» может иметь ширину 3 пикселя для 96 точек на дюйм, но 5, 6 или 7 для 192 точек на дюйм. Если вы хотите согласовать ширину экрана и ширину принтера, вам следует рассчитать ширину на основе разрешения принтера и соответствующим образом отрегулировать положение экрана.

Вы можете настроить положение отдельных букв, целых слов или оставить макет на экране как есть, но обрезать или расширить правое поле в зависимости от размера текста на принтере.

MS Word изменяет положение букв (соблюдайте пробелы между буквами):

Интересная отправная точка: http://www.antigrain.com/research/font_rasterization/index.html#FONT_RASTERIZATION

Что объясняет его. Эта статья очень помогает.

Ross Lombardi 06.06.2018 21:31

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