TextRenderer.DrawText在XP和Vista上呈现的Arial字体不同

6
我有一个C#应用程序,可以进行文本渲染,类似于简单的所见即所得文本编辑器。我使用TextRenderer.DrawText将文本呈现到屏幕上,并使用GetTextExtentPoint32测量文本,以便在同一行上定位不同字体样式/大小。在Vista中,这一切都很正常。但是在XP中,Arial的呈现方式不同,某些字符(如“o”和“b”)占用的宽度比Vista中要大。然而,GetTextExtentPoint32似乎仍然按照Vista中的方式测量字符串,具有较小的宽度。最终结果是,每隔一段时间,一系列文本将重叠在其前面的文本上,因为先前的文本被测量为比实际在屏幕上显示的要小。此外,我的文本呈现代码完全模仿ie的文本呈现(仅适用于简单格式和英语语言),并且ie的文本呈现在Vista和XP之间似乎是一致的,这就是我注意到不同字符大小变化的原因。有人对发生了什么有任何想法吗?总之,对于Arial字体,TextRenderer.DrawText和GetTextExtentPoint32在XP上不匹配。DrawText似乎以比Vista更大和/或更小的方式绘制某些字符,但是GetTextExtentPoint32似乎按照Vista中的方式测量文本(这似乎与xp和vista上ie的文本呈现相匹配)。希望这有意义。注意:不幸的是,TextRenderer.MeasureString速度不够快或准确,无法满足我的要求。我尝试使用它,但不得不摆脱它。

+1 因为我知道你正在处理什么!而我只需要处理固定宽度字体。 - leppie
你确定这不是 DPI 或 Cleartype 的问题吗? - Christian Wattengård
3个回答

2
感谢您抽出时间回复,Adrian。
我的理解是TextRenderer.DrawText实际上调用了GDI的一个函数,完全绕过了GDI+文本渲染。这就是为什么我对GetTextExtentPoint32的输出感到困惑。
不过,我认为我已经找到了问题所在。原来,如果将Graphics.TextRenderingHint设置为System.Drawing.Text.TextRenderingHint.ClearTypeGridFit,或者可能其他值,它会导致某些字体中的一些字符增大或缩小。这似乎在XP中比在Vista中更为明显。我在Vista中没有看到这种情况发生。总之,看起来GetTextExtentPoint32或者无法识别差异,或者我在调用时没有设置某种标志。
我的解决方案是使用系统默认的文本渲染提示设置。

看起来不错。我在这里找到了一些好的信息(但他也提出了一些可疑的声明,所以要小心)。http://blogs.msdn.com/cjacks/archive/2006/05/11/595525.aspx - Adrian McCarthy

1
实际上,TextRenderer的DrawText和MeasureString都基于DrawTextEx(这是User32函数,而不是Gdi函数)。 因此,您可以考虑使用对该函数的本机封送调用,而不是使用MeauseString,因为该函数会进行一些额外的计算(特别是如果您在没有HDC的情况下使用函数重载)。
此外,也许这个帖子对您也会有所帮助。

0

我不是C#专家,但我相信.NET渲染是建立在GDI+之上的。 我还非常确定,GDI+使用其自己的字体呈现方式,这种方式使用了未经提示的缩放。

另一方面,GetTextExtentPoint32是GDI的一部分。GDI使用大小提示,这可能会影响字符的宽度,具体取决于字体大小。通常情况下,在较小的字体大小下,GDI文本看起来会更好一些,但它不会线性缩放。

您必须始终使用一个模型来获得像素完美的结果。

XP和Vista可能存在其他因素,这可能使这个问题在XP上比Vista更明显,但根本问题在两者中都存在。这些其他因素可能包括DPI设置、DPI缩放、ClearType或抗锯齿设置、字体链接(如果您混合使用其他语言文字),字体替换(特别是在打印时),甚至可能是不同版本的Arial。我甚至不确定GDI+是否使用与GDI相同的默认映射模式。

另请参见我的打印预览答案


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接