2011-02-09 11 views
9

Ho un controllo utente WPF per il quale è necessario forzare il rendering in RenderMode.SoftwareOnly. Dal momento che sto usando .NET 3.5, ho dovuto fare qualcosa di simile,Modalità di rendering software - WPF

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

Ma questo non sta funzionando relativa alla mia domanda, il programma WPF si blocca su alcune macchine e disattivando l'accelerazione hardware a livello di registro sembra per risolvere il problema.

Il codice sopra riportato è scritto nell'evento Loaded della finestra. Se sono corretto, l'evento Loaded si verifica dopo il rendering dei controlli (MSDN). Quindi ha senso avere il codice sopra in quell'evento? In caso contrario, quale evento sarebbe appropriato per questo?

Inoltre, l'impostazione di RenderMode su un elemento visivo interessa i bambini? O devo impostare questo in modo specifico per ogni elemento figlio?

Qualsiasi aiuto sarebbe fantastico!

+0

Ciao, sono curioso. La soluzione del dispatcher ti ha aiutato? – HCL

risposta

16

Ecco quello che abbiamo fatto:

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

ha funzionato bene per noi, TRANNE ... Questo deve essere fatto per ogni finestra. In .NET 3.5 non c'era modo di rendere l'impostazione effettiva a livello di applicazione. E ci sono alcune finestre su cui non avrai più il controllo, ad esempio, fai clic con il pulsante destro del mouse sulle finestre "contesto". Abbiamo scoperto che non c'era una buona soluzione per .NET 3.5 tranne l'impostazione del Registro di sistema.

cura

Ecco la logica che abbiamo usato per determinare quando forzare il rendering software. È stato suggerito da un tecnico di supporto Microsoft.

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

In .NET 4 Microsoft ha aggiunto un'impostazione a livello di applicazione che funziona perfettamente per noi. È un'opzione molto migliore perché non è necessario impostarlo su ogni finestra. Basta impostarlo una volta e si applica a tutte le finestre.

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

a cura

La nuova proprietà .NET 4.0 può essere impostata all'avvio dell'applicazione in questo modo:

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

Da dove proviene "ForceSoftwareRendering"? Hai trovato un modo per rilevare quali macchine si sarebbero bloccate con il rendering del software? –

+0

@ EduardoWada aggiornerò la risposta per includere questo. –

+0

qualcuno sa qualcosa lo stesso, ma per WinForms? – user1722669

2

evento -problema
dei dispersi hwnd- fonte, provare quanto segue:

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

ambito di RenderMode
Per quanto ne so, non c'è un solo Win32-finestra per ogni finestra WPF e tutto il resto è reso nativo in WPF. Ecco perché penso che l'impostazione RenderMode riguardi tutto il contenuto della finestra in cui si trovava l'immagine. L'ambito è in questo caso a livello di finestra.

+0

grazie. puoi spiegare perché è richiesto il Dispatcher in questo caso? –

+0

@appu: Non è richiesto - Ma se hwnd non è presente al momento dell'esecuzione dell'evento caricato (se questo è il problema), quindi aspettando esplicitamente fino a quando il sistema ha finito tutto è compito importante (come il rendering :) posso aiutare. Ho già visto molti scenari insoliti con problemi che potrebbero essere risolti in questo modo. Ma è solo un'idea, non posso garantire che funzioni. A proposito, uso il codice sopra senza il dispatcher e non ho avuto problemi fino ad ora. Ma lo uso solo in un'app e lì è un'opzione usata raramente. Pertanto questa affermazione sicuramente non è rappresentativa. – HCL

15

È possibile anche disattivare il rendering hardware per l'intero processo inserendo la riga successiva nel gestore di avvio dell'applicazione:

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; 

E 'anche possibile passare durante il runtime

+2

+1 per poter passare durante l'esecuzione. Questo non è immediatamente evidente da MSDN ma è un'informazione importante. – Charlie

+1

.Net 4.0 e versioni successive –

Problemi correlati