软件渲染模式 - WPF

时间:2011-02-09 22:02:25

标签: c# .net wpf .net-3.5 hardware-acceleration

我有一个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会影响它的孩子吗?或者我是否需要专门为每个子元素设置它?

任何帮助都会很棒!

3 个答案:

答案 0 :(得分:23)

以下是我们的所作所为:

    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;
    }
}

答案 1 :(得分:15)

您还可以通过将下一行放在应用程序启动处理程序中来禁用整个过程的硬件渲染:

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;

也可以在运行期间切换

答案 2 :(得分:3)

event -problem
对于缺少的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涉及视觉所在窗口中的所有内容。在这种情况下,范围是在窗口范围内。