在 WinForms MDI 应用程序中托管 WPF 用户控件时,当您有多个相互重叠的表单时,会出现绘图问题,从而导致非常明显的视觉效果。将一个子窗体拖动到另一个也托管 WPF 内容的子窗体上,或者在拖动子窗体时允许主 MDI 父窗体剪裁子窗体的边缘后,这些工件大多可见。子窗体的拖放完成后,工件通常会保留在周围,但我发现将焦点设置到不同的应用程序窗口,然后重新聚焦到我的应用程序窗口,它被重新绘制,一切都很好,直到子窗体表格再次移动。请参阅下图,该图演示了该问题。
微软的人坚持认为 WinForms MDI 已经是 MDI 的充分解决方案,不需要在 WPF 中重新发明,尽管我很难相信他们尝试以这种方式创建 WPF 应用程序,因为存在明显的缺点。
更新:我遗漏的一些额外注意事项是,如果我创建这些表单而不设置 MdiParent,它们将被创建为常规表单,并且不会发生此问题。此问题似乎是 WinForms MDI 场景所特有的。另外,我目前在 Windows 7 Enterprise 上运行,我知道 Windows XP 上的结果可能有很大不同,但我无法对此进行测试。
更新:我发现了一些关于此问题的其他相关资源,我认为我应该分享这些资源。
最佳答案
另一种解决方法似乎是恢复到软件渲染,而不是利用硬件加速。这是 suggestion by Marco Zhou在 MSDN 论坛上。
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.Loaded += delegate
{
var source = PresentationSource.FromVisual(this);
var hwndTarget = source.CompositionTarget as HwndTarget;
if (hwndTarget != null)
{
hwndTarget.RenderMode = RenderMode.SoftwareOnly;
}
};
}
}
我已经对此进行了测试,该解决方案似乎工作得很好,到目前为止,这是我在 FoxPro 互操作场景中找到的解决此问题的唯一解决方案,该方案与我最初发布的 WinForms 场景非常相似。目前,我计划在 WinForms 项目的 MDI Parent 解决方案上使用原始的 Refresh,但对于其他 native 互操作应用程序(例如当我的 WPF 控件托管在 Visual FoxPro 中时),我将使用此解决方案。当然,除非针对这两种情况找到更优雅的解决方案。
还需要注意的是,据我所知,软件渲染是 XP 系统上的唯一选择,通常 Visual FoxPro 或 WinForms 通常会利用与 Vista 操作系统及更高版本上的 native WPF 应用程序相同类型的硬件加速。因此,当您必须处理互操作时,使用此选项可能并不像听起来那么糟糕。目前,我不知道使用此解决方案时是否有任何相关副作用,但如果有任何副作用,则必须认真考虑。
关于wpf - 在 WinForms MDI 应用程序中托管 WPF 用户控件时如何避免视觉伪影?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2589948/