软件渲染模式-WPF

发布于 2024-10-16 10:10:14 字数 650 浏览 11 评论 0原文

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

I have a WPF user control for which I need to force rendering in RenderMode.SoftwareOnly. Since I am using .NET 3.5, I had to do something like this:

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

But this is not working on my application, The WPF program is crashing on few machines and turning off the hardware acceleration at the registry level seems to fix the issue.

The above code is written in the Loaded event of the window. If I am correct, Loaded event happens after the controls are rendered (MSDN). So does it make sense to have the above code in that event? If not, which event would be appropriate for it?

Also, will setting RenderMode on a visual affects its children? Or do I need to set this specifically for each child elements?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

跨年 2024-10-23 10:10:14

这就是我们所做的:

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 中,微软添加了一个非常适合我们的应用程序范围设置。这是一个更好的选择,因为您不需要在每个窗口上设置它。您只需设置一次,它就会应用于所有窗口。

System.Windows.Media.RenderOptions。 ProcessRenderMode

已编辑

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

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

Here's what we did:

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

It worked OK for us, EXCEPT... This needs to be done for every Window. In .NET 3.5 there was no way to make the setting take effect application-wide. And there are some windows that you won't have as much control over - for example, right-click "context" windows. We found that there was no good solution for .NET 3.5 except the registry setting.

Edited

Here's the logic we used to determine when to force software rendering. It was suggested by a Microsoft support engineer.

public bool ForceSoftwareRendering 
{
    get 
    { 
        int renderingTier = (System.Windows.Media.RenderCapability.Tier >> 16);
        return renderingTier == 0;
    }
}

In .NET 4 Microsoft added an application-wide setting that works perfectly for us. Its a much better option because you don't need to set it on every window. You just set it once and it applies to all windows.

System.Windows.Media.RenderOptions.ProcessRenderMode

Edited

The new .NET 4.0 property can be set at application startup like this:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        if (ForceSoftwareRendering)
            RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
    }
}
久隐师 2024-10-23 10:10:14

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

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;

也可以在运行时切换

You can also disable hardware rendering for the whole process by putting the next line in the application startup handler:

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;

It is also possible to switch during runtime

一杆小烟枪 2024-10-23 10:10:14

事件问题
对于缺少的 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 涉及视觉对象所在窗口中的所有内容。在本例中,范围是窗口范围内的。

event -problem
For the missing hwnd-source, try the following:

    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
As far as I know, there is only one Win32-window for each WPF window and all the rest is rendered native in WPF. That's why I think that setting RenderMode concerns all content in the window the visual was in. The scope is in this case window-wide.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文