Graphics.DrawString vs TextRenderer.DrawText?哪个可以提供更好的质量

tec*_*hno 17 .net c# text gdi+ gdi

TextRenderer基于GDI和Graphics.DrawString基于GDI +.这些函数中的哪些功能可以在图像上绘制文本时提供更高质量的文本.

Ian*_*oyd 72

我将在这里交叉发布我的答案,以便获取信息.


在.NET中有两种绘制文本的方法:

  • GDI +(graphics.MeasureStringgraphics.DrawString)
  • GDI(TextRenderer.MeasureTextTextRenderer.DrawText)

在.NET 1.1中,一切都使用GDI +进行文本渲染.但是有一些问题:

  • 由于GDI +的某种无状态特性会导致一些性能问题,其中将设置设备上下文,然后在每次调用之后恢复原始设备上下文.
  • 用于Windows/Uniscribe和Avalon(Windows Presentation Foundation)的国际文本的整形引擎已经多次更新,但尚未针对GDI +进行更新,这导致对新语言的国际渲染支持不具有相同的质量水平.

所以他们知道他们想要改变.NET框架以停止使用GDI +的文本渲染系统,并使用GDI.起初他们希望他们可以简单地改变:

graphics.DrawString
Run Code Online (Sandbox Code Playgroud)

调用旧DrawTextAPI而不是GDI +.但它们无法使文本包装和间距与GDI +完全匹配.

在Windows Forms 2.0中,我们添加了对绘制GDI文本的支持.起初,我们在DrawText API上有一些宏大的戳戳和刺激计划,这样我们可以使它与GDI +的DrawString API的工作方式完全匹配.我实际上认为我们非常接近,但是在自动换行和字符间距方面存在根本差异,仅作为这两种API的消费者,Windows Forms无法解决.

所以现在我们遇到了一个问题:我们希望将每个人都切换到新的TextRenderer API,这样文本看起来会更好,更好地本地化,与操作系统中的其他对话框更一致地绘制......但我们不想要打破人们指望GDI +测量字符串来计算他们的文本应该排成一行的位置.

所以他们不得不继续graphics.DrawString打电话给GDI +(兼容原因;那些打电话的人graphics.DrawString会突然发现他们的文字没有像过去那样包装).来自MSDN:

.NET Framework 2.0中引入了基于GDI的TextRenderer类,以提高性能,使文本看起来更好,并改进对国际字体的支持.在早期版本的.NET Framework中,基于GDI +的Graphics类用于执行所有文本呈现.GDI计算字符间距和自动换行与GDI +不同.在使用Graphics类呈现文本的Windows窗体应用程序中,这可能导致使用TextRenderer的控件的文本与应用程序中的其他文本不同.要解决此不兼容问题,可以将特定控件的UseCompatibleTextRendering属性设置为true.要对应用程序中所有受支持的控件设置UseCompatibleTextRenderingtrue,请使用参数true调用Application.SetCompatibleTextRenderingDefault方法.

TextRenderer创建了一个新的静态类来包装GDI文本呈现.它有两种方法:

TextRenderer.MeasureText
TextRenderer.DrawText
Run Code Online (Sandbox Code Playgroud)

注意: TextRenderer是GDI的包装器,同时graphics.DrawString仍然是GDI +的包装器.


然后是如何处理所有现有.NET控件的问题,例如:

  • Label
  • Button
  • TextBox

他们希望将它们切换到使用TextRenderer(即GDI),但他们必须小心.可能有些人依赖于他们的控件绘制,就像在.NET 1.1中那样.因此诞生了" 兼容的文本渲染 ".

默认情况下,应用程序中的控件的行为与它们在.NET 1.1中的行为相同(它们是" 兼容的 ").

您通过调用以下命令关闭兼容模式:

Application.SetCompatibleTextRenderingDefault(false);
Run Code Online (Sandbox Code Playgroud)

这使您的应用程序更好,更快,具有更好的国际支持.总结一下:

SetCompatibleTextRenderingDefault(true)  SetCompatibleTextRenderingDefault(false)
=======================================  ========================================
 default                                  opt-in
 bad                                      good
 the one we don't want to use             the one we want to use
 uses GDI+ for text rendering             uses GDI for text rendering
 graphics.MeasureString                   TextRenderer.MeasureText
 graphics.DrawString                      TextRenderer.DrawText
 Behaves same as 1.1                      Behaves *similar* to 1.1
                                          Looks better
                                          Localizes better
                                          Faster
Run Code Online (Sandbox Code Playgroud)

注意GDI + TextRenderingHint与用于GDI字体绘制的相应LOGFONT质量之间的映射也很有用:

TextRenderingHint           mapped by TextRenderer to LOGFONT quality
========================    =========================================================
ClearTypeGridFit            CLEARTYPE_QUALITY (5) (Windows XP: CLEARTYPE_NATURAL (6))
AntiAliasGridFit            ANTIALIASED_QUALITY (4)
AntiAlias                   ANTIALIASED_QUALITY (4)
SingleBitPerPixelGridFit    PROOF_QUALITY (2)
SingleBitPerPixel           DRAFT_QUALITY (1)
else (e.g.SystemDefault)    DEFAULT_QUALITY (0)
Run Code Online (Sandbox Code Playgroud)

样品

这里是GDI +(graphics.DrawString)与GDI(TextRenderer.DrawText)文本呈现的一些比较:

GDI +:TextRenderingHintClearTypeGridFit,GDI:CLEARTYPE_QUALITY:

在此输入图像描述

GDI +:TextRenderingHintAntiAlias,GDI:ANTIALIASED_QUALITY:

在此输入图像描述

GDI + : TextRenderingHintAntiAliasGridFit, GDI:不支持,使用ANTIALIASED_QUALITY:

在此输入图像描述

GDI +:TextRenderingHintSingleBitPerPixelGridFit,GDI:PROOF_QUALITY:

在此输入图像描述

GDI +:TextRenderingHintSingleBitPerPixel,GDI:DRAFT_QUALITY:

在此输入图像描述

我发现奇怪的DRAFT_QUALITYPROOF_QUALITY,它是相同的,与...相同CLEARTYPE_QUALITY.

也可以看看

  • +1**这应该是答案.**:) (9认同)

M-P*_*ror 5

只是我的2美分:我总是使用Graphics.DrawString,除非我需要为我的(Windows窗体)控件进行自定义绘制.例如,在设置了OwnerDraw的列表框中,如果我附加一个DrawItem事件处理程序,它完全绘制项目,包括项目文本.或者在自定义控件中我必须自己画画.

在支持它并启用它的操作系统上使用视觉样式的应用程序中,与其他控件绘制的常规文本相比,使用Graphics.DrawString绘制的文本看起来"关闭".这似乎主要是因为"ClearType"处理(或不处理)的方式不同,虽然我不确定,但我没有文档来支持该声明.(它看起来像文本在.Net 1.x上的方式或将FlatStyle从标准切换到系统和vv时的方式)

仅在这种情况下(Winforms控件上的文本绘制)我使用TextRenderer.DrawText使文本更好地融入其他控件.

如果"与本机混合"不是您关注的问题(它看起来像,因为您想要在图像上绘图),我会选择Graphics.DrawString.此外,如果您想要打印,您必须,因为TextRenderer仅适用于屏幕(而不是打印机画布).