软件渲染模式 – WPF
我有一个WPF用户控件,我需要在RenderMode.SoftwareOnly
强制渲染。 由于我使用的是.NET 3.5,我不得不做类似的事情,
var hwndSource = PresentationSource.FromVisual(this) as HwndSource; if (hwndSource != null) { hwndSource.CompositionTarget.RenderMode = RenderMode.SoftwareOnly; }
但这不适用于我的应用程序,WPF程序在少数计算机上崩溃,关闭注册表级别的硬件加速似乎解决了这个问题。
上面的代码是在窗口的Loaded
事件中编写的。 如果我是正确的,则在呈现控件( MSDN )之后发生Loaded
事件。 那么在这个事件中有上面的代码是否有意义? 如果没有,哪个事件适合它?
另外,在视觉上设置RenderMode
会影响它的孩子吗? 或者我是否需要为每个子元素专门设置它?
任何帮助都会很棒!
这是我们做的:
private void Window_Loaded(object sender, RoutedEventArgs e) { if (ForceSoftwareRendering) { HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; HwndTarget hwndTarget = hwndSource.CompositionTarget; hwndTarget.RenderMode = RenderMode.SoftwareOnly; } }
它对我们有效,除了……这需要为每个窗口完成。 在.NET 3.5中,无法使应用程序在应用程序范围内生效。 并且有些窗口你没有那么多的控制权 – 例如,右键单击“上下文”窗口。 我们发现.NET 3.5除了注册表设置外没有好的解决方案。
编辑
这是我们用来确定何时强制进行软件渲染的逻辑。 它是由Microsoft支持工程师建议的。
public bool ForceSoftwareRendering { get { int renderingTier = (System.Windows.Media.RenderCapability.Tier >> 16); return renderingTier == 0; } }
在.NET 4中,Microsoft添加了一个适用于我们的应用程序范围的设置。 它是一个更好的选择,因为你不需要在每个窗口上设置它。 你只需设置一次,它适用于所有窗口。
http://msdn.microsoft.com/en-us/library/system.windows.media.renderoptions.processrendermode(VS.100).aspx
编辑
可以在应用程序启动时设置新的.NET 4.0属性,如下所示:
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { if (ForceSoftwareRendering) RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; } }
您还可以通过将下一行放在应用程序启动处理程序中来禁用整个过程的硬件渲染:
RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
也可以在运行时切换
事件 – 问题
对于缺少的hwnd-source,请尝试以下操作:
Dispatcher.BeginInvoke(new Action(delegate { HwndSource hwndSource = PresentationSource.FromVisual(this) as System.Windows.Interop.HwndSource; if (null == hwndSource) { throw new InvalidOperationException("No HWND"); } HwndTarget hwndTarget = hwndSource.CompositionTarget; hwndTarget.RenderMode = RenderMode.SoftwareOnly; }),System.Windows.Threading.DispatcherPriority.ContextIdle, null);
RenderMode的范围
据我所知,每个WPF窗口只有一个Win32窗口,其余所有窗口都在WPF中呈现。 这就是为什么我认为设置RenderMode
涉及视觉所在窗口中的所有内容。在这种情况下,范围是在窗口范围内。