Режим программного рендеринга - WPF - PullRequest
12 голосов
/ 10 февраля 2011

У меня есть пользовательский элемент управления 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 ]

23 голосов
/ 10 февраля 2011

Вот что мы сделали:

    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;
    }
}
15 голосов
/ 13 июня 2012

Вы также можете отключить аппаратный рендеринг для всего процесса, поместив следующую строку в обработчик запуска приложения:

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;

Также возможно переключение во время выполнения

3 голосов
/ 10 февраля 2011

событие -проблема
Для отсутствующего источника hwnd попробуйте следующее:

    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 относится ко всему содержимому окна, в котором находился визуал. В этом случае область действия - для всего окна.

...