【问题标题】:Fastest API for rendering text in Windows Forms?在 Windows 窗体中呈现文本的最快 API?
【发布时间】:2010-09-09 10:33:35
【问题描述】:

我们需要优化 C# Windows Forms 应用程序的文本渲染,该应用程序在不规则网格中显示大量小字符串。任何时候都可能有超过 5000 个可见的单元格,每秒更新 4 次。各个单元格的字体系列和大小是一致的,尽管颜色可能因单元格而异,粗体/斜体/纯色也会有所不同。

我在网上看到了关于 TextRenderer.DrawTextGraphics.DrawString 是最快/最佳的相互矛盾的信息,这在 Win32 级别上减少到 GDIGDI+ 比较。

我在 Windows XP 和 Windows Vista 上也看到了截然不同的结果,但我的主要目标是 Windows XP。有望取得重大进展的文章 在WinFXDirectX 10 下在这里没有帮助:-)

这里最好的方法是什么?我不怕引入一个小的 C++/CLI 层并优化设备上下文处理以提高性能,但我想要一些关于采取哪个方向的明确建议。

编辑: 感谢您的初步回复。我将尝试结合使用背景位图渲染和 GDI 等效调用。

【问题讨论】:

    标签: c# windows performance


    【解决方案1】:

    一位微软开发人员在他的博客上发布了一篇GDI vs. GDI+ Text Rendering Performance 文章,回答了原始速度问题:在他的系统上,GDI DrawText 比 GDI+ DrawString 快大约 6 倍。

    如果你想成为一个真正的速度恶魔,TextOut 比 DrawText 快,但你必须自己处理剪辑和自动换行。 ExtTextOut 支持剪辑。

    GDI 渲染(TextRenderer)将与 Windows 其他部分使用 GDI 更加一致; GDI+ 尝试独立于设备,因此some spacing and emboldening are inconsistent。有关呈现不一致的示例,请参阅 SQL Server 2005 外围应用配置工具。

    【讨论】:

    • 博客链接中的示例应用程序是我看到 Vista 和 XP 之间的巨大差异时使用的那个 - 在我的 Vista PC 上,GDI 和 GDI+ 是相等的,而在 XP 上我看到了 6 倍的差异作者提到...这可能是 Vista 驱动程序问题,但突出了这里的一些困难 - 谢谢!
    • 历史记录:ExtTextOut 曾经是在某些卡/驱动程序上绘制实心矩形的最快方法 :)
    • 很遗憾,上面提到的文章似乎已经不存在了,这里是一个备份:blogs.msdn.com/cjacks/archive/2006/05/19/602021.aspx
    【解决方案2】:

    即使使用 GDI,5000+ 文本渲染也很慢,尤其是在您需要滚动时。创建一个单独的渲染线程,每 200 毫秒通知 UI 线程,并对当前结果进行 bitblt。它提供了流畅的用户体验。

    【讨论】:

      【解决方案3】:

      一般来说,GDI 的绘图速度比 GDI+ 快。我从事的项目必须绘制数千行和文本字符串,并且从 GDI+ 切换到 GDI 显着提高了性能。那是使用 Windows XP,所以我无法评论 Vista。我还建议对绘图使用双缓冲来提高性能。创建一个兼容的离屏位图,并在每次需要绘制时重复使用。

      【讨论】:

        【解决方案4】:

        创建一个 C++/CLI 互操作类以在本机代码中进行绘图将导致疯狂快速绘图。我们已经见证并衡量了这一点。

        如果您不愿意这样做,我们发现 graphics.DrawString 只比 TextRenderer.DrawText 快一点。

        【讨论】:

          【解决方案5】:

          在我的 Windows 7 64 位系统上,TextOut 甚至比 DrawString 慢一点! TextRenderer.DrawText 比 DrawString 慢很多。

          【讨论】:

          • 我也发现了这个......但我找不到任何原因!?
          【解决方案6】:

          根据最近的经验,最快的文本输出是通过带有ETO_GLYPH_INDEX 标志的ExtTextOut 实现的。这是有代价的,而且您不再打印字符,而是直接打印字体字形。这意味着您需要在调用ExtTextOut 之前将常规字符串转换为字形索引字符串,或者通过每次调用GetCharacterPlacement,或者只调用一次此函数来构建您自己的转换表,这将在新字体之前有效在 DC 中选择。请记住,字形索引是 16 位的,因此您可以将它们存储在 Unicode 字符串中并调用 ExtTextOutW 版本,而不管原始字符串字符大小如何。

          【讨论】:

            猜你喜欢
            • 2019-05-25
            • 2021-08-20
            • 2011-08-10
            • 2010-12-01
            • 2011-06-28
            • 1970-01-01
            • 2012-01-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多