2011-02-09 6 views
9

Tengo un control de usuario WPF para el que necesito forzar la representación en RenderMode.SoftwareOnly. Desde que estoy usando .NET 3.5, que tenía que hacer algo así,Modo de procesamiento de software - WPF

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

Pero esto no está funcionando en mi solicitud, el programa WPF está fallando en algunas máquinas y apagar la aceleración de hardware a nivel del registro parece para arreglar el problema

El código anterior está escrito en el evento Loaded de la ventana. Si estoy en lo correcto, el evento Loaded ocurre después de que se procesaron los controles (MSDN). Entonces, ¿tiene sentido tener el código anterior en ese caso? Si no, ¿qué evento sería apropiado para eso?

Además, ¿afectará la configuración RenderMode a sus hijos? ¿O debo configurar esto específicamente para cada elemento secundario?

Cualquier ayuda sería grande!

+0

Hola, soy curioso. ¿Te ha ayudado la solución de despachador? – HCL

Respuesta

16

Aquí es lo que hicimos:

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

Se trabajó bien para nosotros, excepto ... Esto tiene que ser hecho por todas las ventanas. En .NET 3.5 no había forma de que la configuración tuviese efecto en toda la aplicación. Y hay algunas ventanas sobre las que no tendrá tanto control, por ejemplo, haga clic con el botón derecho en las ventanas de "contexto". Descubrimos que no había una buena solución para .NET 3.5, excepto la configuración del registro.

Editado

Ésta es la lógica que usamos para determinar cuándo se debe forzar la representación del software. Fue sugerido por un ingeniero de soporte de Microsoft.

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

En .NET 4 Microsoft agregó una configuración para toda la aplicación que funciona perfectamente para nosotros. Es una opción mucho mejor porque no necesita configurarlo en todas las ventanas. Usted acaba de configurarlo una vez y se aplica a todas las ventanas.

http://msdn.microsoft.com/en-us/library/system.windows.media.renderoptions.processrendermode(VS.100).aspx

editado

La nueva propiedad .NET 4.0 se pueden configurar al inicio de la aplicación de esta manera:

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

¿De dónde viene "ForceSoftwareRendering"? ¿Encontraste una manera de detectar qué máquinas se bloquearían con la representación del software? –

+0

@EduardoWada Actualizaré la respuesta para incluir esto. –

+0

¿Alguien sabe algo igual pero para WinForms? – user1722669

2

caso -problema
Por la falta hwnd- fuente, intente lo siguiente:

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

alcance de RenderMode
Por lo que yo sé, sólo hay una ventana de Win32 para cada ventana de WPF y todo lo demás se rinde nativa en WPF. Es por eso que creo que establecer RenderMode se refiere a todo el contenido en la ventana en la que se encontraba el visualizador. El alcance es en este caso en toda la ventana.

+0

gracias. ¿Puedes explicar por qué se requiere Dispatcher en este caso? –

+0

@appu: No es obligatorio, pero si el hwnd no está presente en el momento de la ejecución del evento cargado (si este es el problema), entonces espere explícitamente hasta que el sistema haya terminado todas las tareas importantes (como la representación :) puede ayudar. Ya he visto una gran cantidad de escenarios poco comunes con problemas que podrían resolverse de esta manera. Pero es solo una idea, no puedo garantizar que funcione. Por cierto, utilizo el código anterior sin el despachador y no tuve ningún problema hasta ahora. Pero solo lo uso en una aplicación y allí es una opción que rara vez se usa. Por lo tanto, esta afirmación seguramente no es representativa. – HCL

15

También puede inhabilitar el procesamiento de hardware para todo el proceso, poniendo la siguiente línea en el controlador de inicio de la aplicación:

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; 

También es posible cambiar en tiempo de ejecución

+2

+1 para posible conmutación durante el tiempo de ejecución. Esto no es inmediatamente obvio desde MSDN, pero es información importante. – Charlie

+1

.Net 4.0 y superior –

Cuestiones relacionadas