自动化:为什么基于 WPF 的 CEFSharp 使用 Bitmap 进行渲染而 winforms 不使用?

Automation: Why WPF based CEFSharp uses Bitmap for rendering while winforms does not?

我们能够使用自动化工具,它能够在 Winforms 上识别 html 对象,而在 WPF 上则不能,因为它被呈现为图像。

我的主要问题是 Winform CEFSharp 使用什么来渲染以及为什么 WPF 不能使用类似的渲染机制?

警告:这是一个非常笼统的答案。我简要地查看了 CEF 源代码(简要地 - 3-5 分钟),其余的是我根据自己的 WPF/WinForms 互操作经验进行的猜测。我有很多。我还尝试了一些早期的 Chromium 构建。然而,所有这些都是几年前的事了,所以它可能只是过时了。也许 Chromium 现在有 first-class WPF 支持。我还没有找到任何相关信息,但如果这真的发生了,我鼓励你更加强烈地遵循最后一段。

--

我怀疑这背后除了实施时间成本之外还有其他原因 - 在 CEF 或 Chromium 项目上。

WinForms 和 WPF 是完全不同的 GUI 框架,编写于不同的时代,使用不同的体系结构、不同的渲染技术、不同的平台特性等。这是尽可能不同的是 "Window" 本身的想法。

在 WinForms 中,几乎每个控件都是一个单独的小 window-like 东西,有一个系统范围的句柄,有一个系统跟踪区域等。所有控件几乎直接通过非托管 win32 GDI+ 呈现自己函数。

在 WPF 中他们没有。在 WPF 中,每个整体只有一个句柄 window,控件不会自行呈现。相反,它们有一个 "look" 的定义,WPF 将它们呈现给 'surface',然后 blitted/streamed(对不起,不记得了)到目标设备。

的确,CEF 使用了不同的方法。对于 WinForms,他们大量使用直接从 Chromium 获取的 'browser component',对于 WPF,他们渲染到位图并定期 show/update 位图。

为什么?我的猜测是,这是因为 Chromium 已经提供了一个 COM/OCX/ActiveX/whatever 组件,而 WinForms 几乎可以直接使用它,这要归功于 everything-has-a-handle "feature" - 如果你可以称之为功能 - 一个WPF 的目标和成功就是消除它。

但是,我不认为 Chromium 在那个时候为 WPF 提供了任何这样的组件。

如果它不存在,那么对于 WPF 只有两种选择 - 一种可以通过特殊的 'host' 中间控件将 WinForms 组件嵌入 WPF window,但这实际上会影响性能并且在使用一些高级渲染功能(如电影流)时也会出现很多问题。诊断和修复它们是复杂的、困难的,甚至是不稳定的(交叉主机组件在不同的 windows 和 .net 版本上表现 非常 不同,即使在 .net 补丁上 有时会更改它们,它可以在一个上工作,在另一个上冻结,在下一个上挂起并呈现为黑色,并在另一个上导致蓝屏)

WPF 的其他选项是使用 "offscreen" 模式。 Chromium 可以渲染成位图,所以为什么不呢。渲染为位图,并显示它。简单的。快的。没问题。

所以,我想说,这一切都归结为 Eric Lippert 的名言:

The question is "why does [snip] not have this feature?" The answer to that question is always the same. Features are unimplemented by default; [snip] does not have that feature because no one designed, implemented and shipped the feature to customers.

很高兴我们至少可以在 WPF 应用程序中显示 Chromium。如果您认为它可以做得更好并且值得做,它是开源的,请随意实施它 - 如果不在 CEF 中,那么在 Chromium 本身中。