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

有关问题已在以下连结说明及示范:

说明: WPF 中的文本清晰度。这个链接有字体比较。

我想收集这个问题的所有可能的解决方案。微软表达式混合使用 WPF,但字体看起来可读。

  • 在微软表达式混合中的暗背景
  • 增大字体大小并更改字体(Calibri...) [链接]
  • 嵌入窗口形式 [链接]
  • 使用 GDI + 和/或 Windows 窗体 TextRenderer 类将文本呈现为位图,然后将该位图呈现为 WPF 控件。[链接]

还有别的解决办法吗?

这个问题将在 VS2010(和 WPF4) beta 2中解决

看来问题终于解决了

Scott Hanselman 的 ComputerZen.com: WPF 和文本模糊,现在具有完整的清晰度

66837 次浏览

他们说“ SnapToDevicePixels = true”可以工作,但是我从来没有看到过任何好的结果。

我通过切换不同的字体来对抗模糊的文本。

显然,这不是解决问题的办法,但这是我解决问题的方法。

技术背景

有一篇关于 WPF 文本渲染的深度文章,来自于一个 WPF 文本程序管理器的 windowsclient.net : WPF 中的文本清晰度

问题归结为 WPF 需要一个平滑动画的线性缩放字体渲染器。另一方面,Pure ClearType 在字体方面有相当大的自由度,可以将垂直的词干推入下一个像素。

如果我们比较一下经典的“级联”模式,就会发现其中的差异是显而易见的。左下角是 WinForms,右上角是 WPF:

虽然我也不是 WPF 字体渲染特质的粉丝,但我可以想象如果动画像 Winform 级联那样跳跃的喧嚣。

在玩注册表

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

  • ClearType 级别: 子像素暗示的数量
  • 伽马值
  • 像素结构: 显示像素中彩色条纹的排列方式
  • 文字对比度: 调整字形茎的宽度,使字体更粗

使用这些设置并不能真正改善潜在的问题,但是可以减少敏感用户的色彩流失效果。

另一种方法

这篇文章给出的最好的建议是增加字体大小和改变字体。Calibri 比标准的 Segoe UI 更适合我。由于它作为 web 字体的受欢迎程度,我也尝试了 Verdana,但它的重量在14-15 pt 之间急剧上升,这在动画字体大小时非常明显。

WPF 4.0

WPF 4将改进对影响字体呈现的支持。WPF 文本博客上的一篇文章解释了这些变化。最重要的是,现在(至少)有三种不同类型的文本渲染:

text rendering comparison

这些绳子应该够每个设计师用了

SnapToDevicePixels 只适用于 WPF 形状(行等) ,不适用于文本呈现器。

对于这个问题没有已知的解决办法。根据微软的说法,这种行为是“设计好的”。

也可以在微软论坛上看到 这个讨论这个问题的帖子——它已经从微软的家伙那里得到了一些回复,澄清了他们在这个问题上的立场。

从开发人员的角度来看,迄今为止唯一已知的“解决方案”是使用 GDI + 和/或 Windows 窗体 TextRenderer 类将文本呈现为位图,然后将该位图呈现为 WPF 控件。除了明显的性能影响,这并不能缓解现有应用程序的问题。

我现在已经创建了一个 此问题的 MicrosoftConnect 票据(令我惊讶的是,尽管所有的负面影响,在指定的跟踪器中没有实际的 bug 报告)。

由于这是向微软传达请求和问题的官方渠道之一,我建议也通过它来寻求更快的答案。至少,如果你希望以某种方式解决这个问题,在那里投票和/或验证这个问题将有助于吸引微软 PM 和工程师对这个问题的注意,并可能提高其优先级。

刚刚尝试了 VS2010测试版,这是所有在 WPF 完成,它遭受严重的模糊字体问题。特别是在工具提示上。

这似乎提供了一些证据表明 WPF4事实上不会解决问题(如果有什么看起来更糟糕)

哇,真不敢相信我的 WPF 字体终于可读了。而且我也不敢相信在我的显示器上缺省值很糟糕的情况下,竟然没有选项对话框来简化这些更改。

这些 注册表设置(十进制)对我很有用,最接近我常用的 Cleartype 字体:

  • ClearTypeLevel: 10(主要是灰度别名)
  • 伽玛等级: 1300(高伽玛使字体太薄,我看到了别名中的颜色)

这个问题将在 VS2010(和 WPF4) beta 2中得到解决:

前几天我遇到了一个问题,当时我使用了一个应用了 投影效果的边框。结果是边框内的所有文本都非常模糊。无论文本是在其他面板内部还是直接在边框下面,任何应用了 效果的父文本块似乎都会受到影响。

这种特殊情况的解决方案是不要把有效果的东西放在边框里,而是使用一个网格(或者其他任何支持把内容放在一起的东西) ,把一个矩形放在与文本相同的单元格中(比如作为可视化树中的一个兄弟) ,然后把效果放在那个单元格上。

像这样:

<!-- 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>

.NET 4终于有了一个解决 WPF 文本渲染质量差的方案,但它是很好的隐藏。为每个窗口设置以下内容:

TextOptions.TextFormattingMode="Display"

默认值是“ Ideal”,这与名称的含义完全不同。

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

我不认为这是一个 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

如果你喜欢使用 C # 基类来定制应用程序的窗口(或者现在有理由这样做) ,这里介绍如何设置文本格式以使用吸引人的显示模式:

public class SnappyWindow : Window
{
public SnappyWindow()
{
SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Display);
}
}

对我有效的方法是在我的窗口中设置 UseLayoutRounding="True"(就像在 推特中所做的那样,在再次查看这里之后,就像 帕特在他的评论中所说的那样)。
UseLayoutRounding 文档对不同的布局大小进行修整,以便在设备像素上进行绘制:

在像素边界上绘制对象消除了当边缘位于设备像素中间时通过抗锯齿产生的半透明边缘。

解释 UseLayoutRoundingSnapToDevicePixels属性之间差异的一个很好的答案是 这个