在WinForms MDI应用程序中托管WPF用户控件时,如何避免视觉瑕疵?
在WinForms MDI应用程序中托管WPF用户控件时,如果有多个表单相互重叠,则会出现绘图问题,从而导致非常明显的视觉瑕疵。在将一个子窗体拖动到另一个子窗体(该子窗体也承载WPF内容)上之后,或者在拖动子窗体时允许主MDI父窗体剪裁子窗体的边缘,这些构件大部分是可见的。在完成子窗体的拖放之后,工件通常会保留下来,但我发现将焦点设置为不同应用程序的窗口,然后重新聚焦到我的应用程序窗口,它会被重新绘制,并且一切正常,直到再次移动子窗体。请参见下面的图片,它演示了问题 微软的那些人坚持认为WinForms MDI已经是MDI的一个足够的解决方案,不需要在WPF中重新发明,尽管我发现很难相信他们试图以这种方式创建WPF应用程序,因为存在明显的缺点 更新:我遗漏的几个额外注意事项是,如果我在创建这些表单时没有设置MDI父级,它们将被创建为常规表单,并且不会发生此问题。这个问题似乎是WinForms MDI场景所独有的。另外,我目前在Windows7企业版上运行,我知道在WindowsXP上的结果可能会有很大的不同,但我还没有能够测试这一点 更新:我找到了一些关于这个问题的其他相关资源,我认为应该与大家分享在WinForms MDI应用程序中托管WPF用户控件时,如何避免视觉瑕疵?,wpf,mdi,winforms-interop,visual-artifacts,Wpf,Mdi,Winforms Interop,Visual Artifacts,在WinForms MDI应用程序中托管WPF用户控件时,如果有多个表单相互重叠,则会出现绘图问题,从而导致非常明显的视觉瑕疵。在将一个子窗体拖动到另一个子窗体(该子窗体也承载WPF内容)上之后,或者在拖动子窗体时允许主MDI父窗体剪裁子窗体的边缘,这些构件大部分是可见的。在完成子窗体的拖放之后,工件通常会保留下来,但我发现将焦点设置为不同应用程序的窗口,然后重新聚焦到我的应用程序窗口,它会被重新绘制,并且一切正常,直到再次移动子窗体。请参见下面的图片,它演示了问题 微软的那些人坚持认为Win
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;