首页 > 解决方案 > TextOutW 在屏幕和打印机上的显示不同

问题描述

我们有一个用于打印的 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 给出不同结果的原因。

此代码计算差异并被绘制事件用于尝试调整间距以解决它,但如果我们能首先找出为什么存在差异会更好,因为它不能解释字符宽度差异。GetTextExtentPoints32 隐藏在对 TextWidthU 的调用之后。

' Call GetTextExtentPoint32W(hdc, StrPtr(strText), Len(strText), textSize)
printerTextWidth = TextWidthU(printerDC, strOutputText) * (screenXdpi / printerXdpi)
screenTextWidth = TextWidthU(UserControl.hdc, strOutputText)
totalDifference = printerTextWidth - screenTextWidth

标签: winapiprintingvb6dpi

解决方案


文本光栅器对齐像素边界上的所有字符。例如,字母“i”对于 96 DPI 可以有 3 个像素宽度,但对于 192 DPI,可以有 5、6 或 7 个像素宽度。如果要匹配屏幕宽度和打印机宽度,则应根据打印机分辨率计算宽度并适当调整屏幕位置。

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

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

在此处输入图像描述

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


推荐阅读