C# Graphics.DrawString vs TextRenderer.DrawText?哪一个可以提供更好的质量
TextRenderer基于GDI和Graphics。DrawString基于GDI+。在图像上绘制文本时,以下哪种功能可以提供更高质量的文本。我的个人体验(我只知道这两个区别): DrawString支持Alpha通道,抗锯齿C# Graphics.DrawString vs TextRenderer.DrawText?哪一个可以提供更好的质量,c#,.net,text,gdi+,gdi,C#,.net,Text,Gdi+,Gdi,TextRenderer基于GDI和Graphics。DrawString基于GDI+。在图像上绘制文本时,以下哪种功能可以提供更高质量的文本。我的个人体验(我只知道这两个区别): DrawString支持Alpha通道,抗锯齿 TextRenderer只支持Uniscribe我的2美分:我总是使用Graphics.DrawString,除非我需要为我的(Windows窗体)控件进行自定义绘制。例如,在设置了OwnerDraw的列表框中,如果我附加了一个DrawItem事件处理程序,该处理程序可
TextRenderer只支持Uniscribe我的2美分:我总是使用Graphics.DrawString,除非我需要为我的(Windows窗体)控件进行自定义绘制。例如,在设置了OwnerDraw的列表框中,如果我附加了一个DrawItem事件处理程序,该处理程序可以完全绘制项目,包括项目文本。或者在自定义控件中,我必须自己绘制 在支持并启用了视觉样式的操作系统上使用视觉样式的应用程序中,与其他控件绘制的常规文本相比,使用Graphics.DrawString绘制的文本看起来“关闭”。这似乎主要是因为“ClearType”处理(或不处理)方式的不同,尽管我不确定,也没有文档支持该语句。(这有点像.NET1.x上的文本,或者从标准切换到系统和v.v时的文本。) 仅在这种情况下(Winforms控件上的文本绘制),我使用TextRenderer.DrawText使文本更好地与其他控件混合
如果“融入当地人”不是你关心的问题之一(看起来是这样,因为你想在图像上画画),我会选择Graphics.DrawString。另外,如果您想打印,您必须这样做,因为TextRenderer只在屏幕上工作(而不是在打印机画布上)。我将在上面交叉张贴我的答案,以便信息能够被传递
在.NET中绘制文本有两种方法:
- GDI+(
和graphics.MeasureString
)graphics.DrawString
- GDI(
和textrender.MeasureText
)textrender.DrawText
- GDI+的无状态特性导致了一些性能问题,在GDI+中,设备上下文将被设置,然后在每次调用后恢复原始上下文
- Windows/Uniscribe和Avalon(Windows Presentation Foundation)的国际文本成形引擎已多次更新,但尚未针对GDI+进行更新,这导致对新语言的国际呈现支持的质量不尽相同
graphics.DrawString
调用旧的DrawText
API而不是GDI+。但是
在Windows Forms 2.0中,我们添加了对绘制GDI文本的支持。起初,我们有宏伟的计划来戳和戳DrawText API,这样我们就可以使它与GDI+的DrawString API的工作方式完全匹配。事实上,我认为我们已经非常接近了,但在单词包装和字符间距方面存在着根本性的差异,而仅仅作为这两种API的消费者,Windows窗体无法解决这一问题
因此,现在我们遇到了一个问题:我们希望将每个人都切换到新的TextRenderer API,以便文本看起来更好、本地化更好、与操作系统中的其他对话框绘制更一致。。。但是我们不想破坏那些依靠GDI+度量值字符串计算文本排列位置的人们
因此,他们被迫保留graphics.DrawString
来调用GDI+(兼容性原因;调用graphics.DrawString
的人会突然发现他们的文本没有以前的包装方式):
在.NETFramework2.0中引入了基于GDI的类,以提高性能,使文本看起来更好,并改进对国际字体的支持。在.NET Framework的早期版本中,基于GDI+的类用于执行所有文本呈现。GDI计算字符间距和换行与GDI+不同。在使用类呈现文本的Windows窗体应用程序中,这可能会导致使用的控件的文本与应用程序中的其他文本不同。要解决此不兼容问题,可以将特定控件的UseCompatibleTextRendering
属性设置为true。要将应用程序中所有受支持控件的UseCompatibleTextRendering
设置为true,请使用参数true调用该方法
创建了一个新的静态TextRenderer
类来包装GDI文本呈现。它有两种方法:
TextRenderer.MeasureText
TextRenderer.DrawText
注意:TextRenderer
是GDI的包装,而graphics.DrawString
仍然是GDI+的包装
然后是如何处理所有现有的.NET控件的问题,例如:
标签
按钮
TextBox
textrender
(即GDI),但必须小心。可能有人像在.NET1.1中那样依赖于控件的绘制。于是“兼容文本呈现”诞生了
默认情况下,应用程序中的控件的行为与.NET 1.1中的控件类似(它们是“兼容的”)
您可以通过调用以下命令来关闭兼容模式:
Application.SetCompatibleTextRenderingDefault(false);
这使您的应用程序更好、更快,并获得更好的国际支持。总而言之:
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
注意GDI+
TextRenderingHint
与GDI字体绘图所用的相应字体之间的映射也很有用:
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)
样品 以下是GDI+(graphics.DrawString)与GDI(TextRenderer.DrawText)文本呈现的一些比较: GDI+:
textrendinghintcleartypegridfit
,GDI:CLEARTYPE\u-QUALITY
:
<
class Form1: Form
{
private string str = "hello world hello world hello world";
private int x = 32, yLabel = 0, yDraw = 64, yRenderer = 32;
public Form1()
{
Font = new Font("Times", 16);
Label label = new Label();
label.BorderStyle = BorderStyle.FixedSingle;
label.AutoSize = true;
label.Text = str;
label.Location = new Point(x, yLabel);
Controls.Add(label);
}
protected override void OnPaint(PaintEventArgs e)
{
SizeF a;
// TextRenderer
a = TextRenderer.MeasureText(str, Font);
TextRenderer.DrawText(e.Graphics, str, Font, new Point(x, yRenderer), Color.Pink);
e.Graphics.DrawRectangle(new Pen(Color.Blue), x, yRenderer, a.Width, a.Height);
// DrawString
e.Graphics.DrawString(str, Font, new SolidBrush(Color.Red), x, yDraw);
a = e.Graphics.MeasureString(str, Font);
e.Graphics.DrawRectangle(new Pen(Color.Lime), x, yDraw, a.Width, a.Height);
base.OnPaint(e);
}
}