首页 文章

软件渲染模式 - WPF

提问于
浏览
12

我有一个WPF用户控件,我需要在 RenderMode.SoftwareOnly 中强制渲染 . 由于我使用的是.NET 3.5,我不得不做类似的事情,

var hwndSource = PresentationSource.FromVisual(this) as HwndSource;
if (hwndSource != null)
{
    hwndSource.CompositionTarget.RenderMode = RenderMode.SoftwareOnly;        
}

但这不适用于我的应用程序,WPF程序在少数几台机器上崩溃,关闭注册表级别的硬件加速似乎解决了这个问题 .

上面的代码是在窗口的 Loaded 事件中编写的 . 如果我是正确的,则在呈现控件后发生 Loaded 事件(MSDN) . 那么在这个事件中有上面的代码是否有意义?如果没有,哪个事件适合它?

另外,在视觉上设置 RenderMode 会影响它的孩子吗?或者我是否需要为每个子元素专门设置它?

任何帮助都会很棒!

3 回答

  • 15

    这是我们做的:

    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除了注册表设置外没有好的解决方案 .

    Edited

    这是我们用来确定何时强制进行软件渲染的逻辑 . 它是由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

    Edited

    可以在应用程序启动时设置新的.NET 4.0属性,如下所示:

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            if (ForceSoftwareRendering)
                RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
        }
    }
    
  • 23

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

    RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
    

    也可以在运行时切换

  • 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);
    

    scope of RenderMode
    据我所知,每个WPF窗口只有一个Win32窗口,其余所有窗口都在WPF中呈现 . 这就是为什么我认为设置 RenderMode 涉及视觉所在窗口中的所有内容 . 在这种情况下,范围是在窗口范围内 .

相关问题