Режим программного рендеринга - WPF
У меня есть пользовательский элемент управления 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 ответа
Вот что мы сделали:
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 добавила настройку для всего приложения, которая идеально подходит для нас. Это гораздо лучший вариант, потому что вам не нужно устанавливать его в каждом окне. Вы просто устанавливаете его один раз, и он применяется ко всем окнам.
отредактированный
Новое свойство.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 попробуйте следующее:
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
касается всего содержимого в окне, в котором находился визуал. В этом случае область действия - для всего окна.