TextOutW 在屏幕上与打印机上的显示不同

TextOutW showing differently on screen vs printer

我们有一个用于打印的 VB6 应用程序,目前无法在 .NET 中重写。 :) 我们要解决的问题是打印的文本与 UI 预览不完全匹配。我们有一个自定义文本框控件,它分别使用 ExtTextOut 和 TextOut 自行处理绘画和打印。它们的输出应该是相同的,但如果字体相同,文本在屏幕或打印机上可能会更大。高度是完美的,只是间距和字符宽度不同。我还不相信这是一个字体字距调整问题,但差异确实取决于打印机 DPI 的间距和字符宽度。 DPI 越高,差异越大。 4000 DPI 可生成更细的字符。但我可以确信我们在某处处理 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))

UI 的绘制代码非常相似。用户看到的问题:UI 不是了解文本字段大小何时太小的好标准,因为如果打印机 DC 上的文本比屏幕 DC 稍宽,则最终字符(例如句号),被切断了。

此差异随字体大小而变化,在 28 时差异为 0。它很容易在 +14 和 -14 之间变化,打印或绘制的文本宽度更大。到目前为止,我一直无法找出导致 TextOut、ExtTextOut 和 GetTextExtentPoint32 给出不同结果的原因。

此代码计算差异并由绘画事件使用以尝试调整间距以解决差异,但如果我们能够首先找出差异的原因会更好,因为它不能' t 考虑字符宽度差异。 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' 对于 96 DPI 可以有 3 个像素宽度,但是对于 192 DPI 可以有 5、6 或 7。如果要匹配屏幕宽度和打印机宽度,应根据打印机分辨率计算宽度并适当调整屏幕位置。

您可以调整单个字母、整个单词的位置,或保持屏幕布局不变,但根据打印机文本大小剪切或扩展右边距。

MS Word调整字母位置(观察字母之间的space):

有趣的起点: http://www.antigrain.com/research/font_rasterization/index.html#FONT_RASTERIZATION