在WinForms MDI应用程序中托管WPF用户控件时,如何避免视觉瑕疵?

在WinForms MDI应用程序中托管WPF用户控件时,如何避免视觉瑕疵?,wpf,mdi,winforms-interop,visual-artifacts,Wpf,Mdi,Winforms Interop,Visual Artifacts,在WinForms MDI应用程序中托管WPF用户控件时,如果有多个表单相互重叠,则会出现绘图问题,从而导致非常明显的视觉瑕疵。在将一个子窗体拖动到另一个子窗体(该子窗体也承载WPF内容)上之后,或者在拖动子窗体时允许主MDI父窗体剪裁子窗体的边缘,这些构件大部分是可见的。在完成子窗体的拖放之后,工件通常会保留下来,但我发现将焦点设置为不同应用程序的窗口,然后重新聚焦到我的应用程序窗口,它会被重新绘制,并且一切正常,直到再次移动子窗体。请参见下面的图片,它演示了问题 微软的那些人坚持认为Win

在WinForms MDI应用程序中托管WPF用户控件时,如果有多个表单相互重叠,则会出现绘图问题,从而导致非常明显的视觉瑕疵。在将一个子窗体拖动到另一个子窗体(该子窗体也承载WPF内容)上之后,或者在拖动子窗体时允许主MDI父窗体剪裁子窗体的边缘,这些构件大部分是可见的。在完成子窗体的拖放之后,工件通常会保留下来,但我发现将焦点设置为不同应用程序的窗口,然后重新聚焦到我的应用程序窗口,它会被重新绘制,并且一切正常,直到再次移动子窗体。请参见下面的图片,它演示了问题

微软的那些人坚持认为WinForms MDI已经是MDI的一个足够的解决方案,不需要在WPF中重新发明,尽管我发现很难相信他们试图以这种方式创建WPF应用程序,因为存在明显的缺点

更新:我遗漏的几个额外注意事项是,如果我在创建这些表单时没有设置MDI父级,它们将被创建为常规表单,并且不会发生此问题。这个问题似乎是WinForms MDI场景所独有的。另外,我目前在Windows7企业版上运行,我知道在WindowsXP上的结果可能会有很大的不同,但我还没有能够测试这一点

更新:我找到了一些关于这个问题的其他相关资源,我认为应该与大家分享


嗯,我可能已经找到了一个解决方案,尽管这感觉有点像黑客。如果在移动子MDI窗体时调用MDI父窗体上的Refresh方法,则所记录的工件将消失。从视觉上看,拖动窗口时,事情似乎有点紧张,但这似乎比我在原始帖子中展示的示例更容易接受

private void Form1_Move(object sender, EventArgs e)
{
    this.ParentForm.Refresh();

    System.Diagnostics.Debug.WriteLine(string.Format("Form Moved to: ({0},{1})", this.Left, this.Top));
}
我也尝试过许多类似的组合,比如只刷新通过调用方法移动的子窗口,比如更新()无效()刷新(),我也在MDI父窗口和调度程序.Invoke(DispatcherPriority.Render,…)上尝试过这些相同的方法InvalidateVisual()在我托管的WPF控件上,但这些其他方法都不适用于专门在MDI父控件上调用Refresh()


我意识到这可能不是最佳解决方案,因为每次子窗口移动几个像素时,我都会强制整个主应用程序窗口刷新,但就目前而言,这是我发现唯一可行的合理解决方案。如果其他人对此有任何替代解决方案或改进,我将欣然接受您的回答。

另一个解决方法似乎是恢复到软件渲染,而不是利用硬件加速。这是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父解决方案上使用我的原始刷新,但对于其他本机互操作应用程序,例如,当我的WPF控件托管在Visual FoxPro中时,我将使用此解决方案。当然,除非为这两种情况找到了更优雅的解决方案


另外,值得注意的是,据我所知,软件渲染是XP系统上的唯一选项,通常VisualFoxproNoreWinForms通常利用与Vista操作系统及更高版本上的本机WPF应用程序相同类型的硬件加速。因此,当您必须处理互操作时,使用此选项可能不像听起来那么糟糕。目前,我不知道使用此解决方案时有任何相关的副作用,但如果有副作用,则必须认真考虑。

检查视频驱动程序并尝试禁用硬件加速。大多数瑕疵是由坏驱动程序、视频卡故障或完成刷新的时间不足引起的

故障排除的第一步:更新视频驱动程序。很明显,我知道

我有类似的问题,检查我的显卡设置(NVidia控制面板)显示全局设置设置非常高,导致刷新间隔较长,如果时间过长,刷新间隔可能会中止。将我的设置恢复为默认设置解决了大部分问题。但我也运行过大量使用GPU的散列程序,所以这可能是我的Remaging工件问题的原因,现在很少出现这种问题,而且在VisualStudio中大部分都表现出了它的丑陋面目

我遇到的另一个故障排除步骤是禁用WPF的硬件加速,这可以在“HKEY_CURRENT_USER/SOFTWARE/Microsoft/Avalon.Graphics”中完成,也可以由应用程序完成,但这仅用于故障排除;永远不要在应用程序中设置这些,因为它将禁用所有WPF应用程序。我没有这个注册表设置,也没有添加它,所以我不确定它是否成功,但许多人说这解决了他们的问题。另请注意,有些应用程序有此选项,如果可用,请尝试禁用它

另一个故障排除步骤是确保视频卡是用于渲染的适当层。任何支持DX9或更高版本的卡都应该足够了,但还涉及其他因素(如我的情况),因此,仅仅因为它在列表中,并不意味着它适合您的用途

最后,您可以使用VisualProfiler(WindowsSDK的一部分)和其他工具,帮助更准确地确定WPF在图形功能方面缺乏性能的情况

呈现层级别注释和WPF性能信息-->

希望这有帮助
this.WindowState = System.Windows.WindowState.Minimized;

this.WindowState = System.Windows.WindowState.Normal;