WPF字体模糊问题- 解决方案

158
问题在以下链接中描述和展示: 说明:WPF中的文本清晰度。此链接具有字体对比。
我想收集此问题的所有可能解决方案。Microsoft Expression Blend使用WPF,但字体看起来可读性好。
  • 像Microsoft Expression Blend一样使用黑色背景
  • 增加字体大小并更改字体(Calibri ...)[链接]
  • 嵌入windows表格[链接]
  • 使用GDI +和/或Windows Forms TextRenderer类将文本呈现为位图,然后将该位图作为WPF控件呈现。[链接]
是否还有其他解决方案? 这将在VS2010(和WPF4)beta 2中得到解决

看起来问题终于解决了!

Scott Hanselman的ComputerZen.com:WPF和文本模糊问题,现在完全清晰了


VS2010RC对我来说完全无法使用 http://www.mpdreamz.nl/vs2010RC-blur.png - Martijn Laarman
我的机器上的VS2010RC看起来比你的图片好多了,实际上白色背景非常好,但是黑色背景仍然很糟糕。 - Robert Vuković
你找到这个问题的解决方案了吗?实际上,我在我的应用程序中也遇到了同样的问题,我正在使用WPF 3.5和VS2010。 - SharpUrBrain
最后三个链接已经失效。 - SHIN JaeGuk
12个回答

137

.NET 4终于解决了WPF文本渲染质量差的问题,但它隐藏得很好。在每个窗口中设置以下内容:

TextOptions.TextFormattingMode="Display"

默认值为"Ideal",但这并不是名称所暗示的意思。

在TextOptions中还有两个选项,即TextHintingMode和TextRenderingMode,但它们都有合理的默认值。


谢谢,那很有帮助。但你只需要在容器中定义一次像 <grid> 这样的东西就可以了。 - Peter Du
5
我只想要这个!我真的不在乎WPF渲染有多复杂,字体对于任何人来说都是不可接受的。 - OKEEngine
对我来说,“TextFormattingMode =“Ideal””(默认设置)和“TextHintingMode =“Fixed””效果最好。但仍不完美。 - Danny Beckett
太棒了!运行得非常好。你为我解决了很多疯狂的头痛问题。 - B.K.
1
"Ideal" 对我来说更好,而不是 "Display"。该项目使用 .NET 4.6.2。也许他们已经修复了这个混淆的名称。 - joe
显示剩余5条评论

109

技术背景

在windowsclient.net上有一篇关于WPF文本渲染的深度文章,由WPF文本项目经理撰写:WPF中的文本清晰度

问题归结为WPF需要线性缩放字体渲染器来实现平滑动画。而纯ClearType则需要对字体进行自由处理,以将垂直柄推入下一个像素。

如果将WinForms和WPF的经典“级联”图案进行比较,差异是显而易见的。WinForms位于左下方,WPF位于右上方:


(来源:black.co.at)

虽然我也不喜欢WPF的字体渲染特异性,但如果动画效果像Winforms级联那样跳跃,我可以想象会引起多大的争议。

改变注册表设置

对我来说特别有趣的是链接到MSDN文章“ClearType注册表设置”,它解释了注册表中可能的用户端调整:

  • ClearType级别:子像素提示量
  • 伽马级别
  • 像素结构:显示像素中颜色条纹的排列方式
  • 文本对比度级别:调整字形柄的宽度,使字体变粗

尝试调整这些设置并没有真正改善根本问题,但可以通过减少颜色渗透效应帮助敏感用户。

另一个方法

文本清晰度文章提供的最佳建议是增加字体大小并更改字体。对我来说,Calibri比标准Segoe UI更好用。由于Verdana作为Web字体很受欢迎,我也尝试了它,但14pt和15pt之间的重量跳跃非常明显,当动画字体大小时非常可见。

WPF 4.0

WPF 4将改进对字体渲染的支持。有一篇WPF Text博客文章介绍了这些变化。最突出的是,现在有至少三种不同的文本渲染方式:

text rendering comparison
(来源:windows.net)

<抱怨>这应该足够每个设计师使用了。</抱怨>


11
优秀的解释,+1。可能解释了为什么Flash字体渲染如此可怕。 - Jeff Atwood
1
是的,这是一个很好的解释,但我仍然希望有一种方法可以打开字体提示,以便在您知道不会进行动画时获得漂亮的外观。我想这意味着您正在优化提示的给定比例。这种东西让WPF看起来仍然像测试版。 - PeterAllenWebb
这并不意味着“可扩展”变体不使用字体提示,只是WPF不像ClearType那样优化命中像素网格。可以说SnapToDevicePixels应该适用于文本,但这总是必须被继承,因为控件无法知道它是否可以捕捉。 - David Schmitt
2
特别相关的是TextOptions.TextFormattingMode附加属性(http://msdn.microsoft.com/en-us/library/ee169597.aspx)。 WPF4和Silverlight还具有UseLayoutRounding(http://msdn.microsoft.com/en-us/library/dd783605.aspx)和SnapsToDevicePixels(http://msdn.microsoft.com/en-us/library/system.windows.uielement.snapstodevicepixels.aspx)属性。 - Pat
这是原始图片(现在已经404):https://web.archive.org/web/20161229180247if_/https://club.black.co.at/david/pics/Fontcascade.png - Patrick
显示剩余2条评论

45
我前几天遇到了一个问题,当我使用一个应用了DropShadowEffect的边框时。结果是所有在该边框内部的文本都变得非常模糊。无论文本是否在其他面板内或直接位于边框下方 - 任何作为具有Effect的父级的子文本块似乎都会受到影响。
解决这个特定情况的方法是不要将带有效果的内容放在边框内,而是使用网格(或任何其他支持将内容放置在彼此上方的东西),并将矩形放置在文本的同一单元格中(即作为视觉树中的兄弟节点),然后将效果放在其上。
像这样:
<!-- don't do this --->
<Border>
     <Border.Effect>
          <DropShadowEffect BlurRadius="25" ShadowDepth="0" Opacity="1"/>
     </Border.Effect>
     <TextBlock Text="This Text Will Be Blurry" />
</Border>

<!-- Do this instead -->
<Grid>
  <Rectangle>
     <Rectangle.Effect>
          <DropShadowEffect BlurRadius="25" ShadowDepth="0" Opacity="1"/>
     </Rectangle.Effect>
  </Rectangle>
  <TextBlock Text="This Text Will Be Crisp and Clear" />
</Grid>

这个做得很好。有点取巧,但比折腾设置等要好。干得漂亮。谢谢。不过我必须做的一件事是将矩形的填充设置为某些内容。也许这只是我的设置问题。 - HAdes
是的,你说得对。矩形默认是透明的,这使得投影看起来很奇怪。 - Isak Savo
这在我的示例应用程序中没有发生,我正在使用WPF 3.5。 - SharpUrBrain
@SharpUrBrain:出了什么问题?即使使用了我的第二个示例,它仍然模糊吗? - Isak Savo
是的,即使使用您的第二个示例,它仍然模糊不清。 - SharpUrBrain
显示剩余3条评论


7
我觉得这并不是一个bug,但默认配置确实非常令人烦恼。这里有所有组合的比较:

TextOptions.TextRenderingMode
TextOptions.TextFormattingMode
RenderOptions.ClearTypeHint

SnapToDevicePixels 不会对文本呈现产生任何影响。

http://i.stack.imgur.com/cS3S2.png

我更倾向于:

TextOptions.TextRenderingMode="Auto"
TextOptions.TextFormattingMode="Ideal"
RenderOptions.ClearTypeHint="Auto"

垂直线条不会模糊。

所使用的字体是Open Sans Light,如果使用得当,像最新版本的TeamViewer一样,就可以非常美观。

对于使用Mahapps.Metro的人来说,问题出在TransitioningContentControl上。https://github.com/MahApps/MahApps.Metro/issues/889


6
SnapToDevicePixels仅适用于WPF形状(例如线条),而不适用于文本渲染器。
目前没有已知的解决方法。根据微软的说法,这种行为是“按设计实现的”。
此外,还可以参见Microsoft论坛上帖子,讨论了这个问题,并得到了微软工作人员几个回复,澄清了他们对该问题的立场。

使用TextOptions.TextFormattingMode附加属性(http://msdn.microsoft.com/en-us/library/ee169597.aspx),在WPF 4中已经修复。 - Pat
1
属性名称应为“SnapsToDevicePixels”,而不是写成“SnapToDevicePixels”。 - Nir Kornfeld

6
从开发者的角度来看,到目前为止唯一已知的“解决方法”是使用GDI+和/或Windows Forms TextRenderer类将文本呈现为位图,然后将该位图呈现为WPF控件。除了明显的性能影响外,这并不能解决现有应用程序的问题。
我现在已经为此问题创建了Microsoft Connect票证(令人惊讶的是,尽管有所有的负面情绪,但指定的跟踪器中没有实际的错误报告)。
由于这是与Microsoft沟通请求和问题的官方渠道之一,我建议您也通过它以获得更快的答案。至少,如果您希望通过某种方式解决这个问题,那么在那里投票支持该票证和/或验证该问题将有助于吸引Microsoft PM和工程师对这个问题的关注,并可能提高其感知优先级。

4

哇,我简直无法相信我终于让我的WPF字体可读了。而且我也无法相信没有选项对话框可以使这些更改变得容易,而默认值在我的显示器上是可怕的。

这些注册表设置(十进制)对我有用,并且最接近我的常规清晰字体:

  • ClearTypeLevel:10(大多数灰度抗锯齿)
  • GammaLevel:1300(较高的伽马值会使字体过于细并且我能看到锯齿中的颜色)

4

我刚尝试了VS2010 beta版,它完全使用WPF完成,但是它非常严重地受到了字体模糊的问题,特别是在工具提示上。

这似乎表明WPF4实际上并不能解决这个问题(如果有什么变化,它看起来更糟糕了)。


3
我正在针对VS2010B1中模糊的文本位置提交错误报告。我同意,工具提示几乎令人发笑地糟糕。考虑到已经明确表示这将在WPF4中修复,我只能希望它只是没有被包括在该测试版中。 - Will Dean

3

他们说“SnapToDevicePixels = true”有效,但我从未看到过好的结果。

我通过切换不同的字体来解决模糊文本问题。

显然这不是问题的解决方案,但这是我绕过它的方法。


我刚刚比较了一个SnapToDevicePixels="true"的TextBlock和一个没有这个属性的TextBlock,使用Segoe UI字体在12duis下并没有任何区别。请问您使用哪种字体? - David Schmitt
我们通过更换字体来改善了情况。我们选择的字体是Avenir(我认为它不是默认安装的,至少在Windows XP上不是)。 - cplotts

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