У нас есть приложение 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





Растеризатор текста выравнивает все символы по границам пикселей. Например, буква «i» может иметь ширину 3 пикселя для 96 точек на дюйм, но 5, 6 или 7 для 192 точек на дюйм. Если вы хотите согласовать ширину экрана и ширину принтера, вам следует рассчитать ширину на основе разрешения принтера и соответствующим образом отрегулировать положение экрана.
Вы можете настроить положение отдельных букв, целых слов или оставить макет на экране как есть, но обрезать или расширить правое поле в зависимости от размера текста на принтере.
MS Word изменяет положение букв (соблюдайте пробелы между буквами):
Интересная отправная точка: http://www.antigrain.com/research/font_rasterization/index.html#FONT_RASTERIZATION
Что объясняет его. Эта статья очень помогает.