2010-04-07 12 views
6

Cuando se alojan controles de usuario WPF dentro de una aplicación MDI de WinForms, hay un problema de dibujo cuando hay varios formularios que se superponen unos a otros y causan artefactos visuales muy distintos. Estos artefactos son en su mayoría visibles después de arrastrar un formulario secundario sobre otro que también aloja contenido WPF o permitiendo que los bordes del formulario secundario sean recortados por el padre principal MDI al arrastrarlo. Después de que se complete el arrastre y soltado del formulario secundario, los artefactos se mantienen en general, pero he encontrado que establecer el foco en la ventana de una aplicación diferente y volver a enfocar en la ventana de la aplicación para volver a dibujar y todo vuelve a funcionar hasta que el niño las formas se mueven una vez más. Por favor, mira la imagen a continuación que demuestra el problema.¿Cómo evitar artefactos visuales al alojar controles de usuario WPF dentro de una aplicación WinForms MDI?

Screenshot of described artifacts

Los que están en Microsoft Windows Forms insisten en que el MDI es ya una solución suficiente para el MDI y no necesita reinventar en WPF aunque lo encuentro difícil de creer que intentaron crear una aplicación de WPF de esta manera debido a la deficiencias obvias.

ACTUALIZACIÓN: Algunas notas extra que omití es que si creo estos formularios sin configurar el MdiParent, se crean como formularios regulares y este problema no ocurre. Este problema parece exclusivo del escenario de MDI de WinForms. Además, actualmente estoy ejecutando Windows 7 Enterprise y soy consciente de que los resultados pueden ser bastante diferentes en Windows XP, pero no he podido probar esto.

ACTUALIZACIÓN: He encontrado algunos otros recursos relacionados con este tema que pensé que debería compartir.

Respuesta

2

Bueno, puede que haya encontrado una solución a pesar de que se siente como un poco de un truco. Parece que si llama al método Refresh en el padre MDI cuando se mueve un Formulario MDI secundario, desaparecen los artefactos anotados. Visualmente las cosas parecen un poco nerviosas al arrastrar una ventana, pero parece mucho más aceptable que el ejemplo que mostré en mi publicación original.

private void Form1_Move(object sender, EventArgs e) 
{ 
    this.ParentForm.Refresh(); 

    System.Diagnostics.Debug.WriteLine(string.Format("Form Moved to: ({0},{1})", this.Left, this.Top)); 
} 

He probado muchas combinaciones en el mismo orden de ideas, tales como refrescante simplemente la ventana secundaria que estaba siendo trasladado por los métodos de llamada tales como Update(), Invalidar(), Actualizar() y también he probado estos mismos métodos en el padre MDI, así como Dispatcher.Invoke (DispatcherPriority.Render, ...) y InvalidateVisual() en mi control WPF alojado, pero ninguno de esos otros métodos trabajó aceptado para llamando al Actualizar() específicamente en el M DI padre.

Me doy cuenta de que probablemente esta no sea la solución óptima ya que obligo a la ventana principal de la aplicación a actualizarse cada vez que una ventana secundaria se mueve unos pocos píxeles, pero ahora es la única solución razonable que encontré trabajos. Si alguien más tiene soluciones alternativas o mejoras sobre esto, con gusto aceptaré su respuesta.

8

Parece que otra solución es volver a la representación de software en lugar de aprovechar la aceleración de hardware.Este fue el suggestion by Marco Zhou en los foros de MSDN.

public partial class UserControl1 : UserControl 
{ 
    public UserControl1() 
    { 
     InitializeComponent(); 
     this.Loaded += delegate 
     { 
      var source = PresentationSource.FromVisual(this); 
      var hwndTarget = source.CompositionTarget as HwndTarget; 
      if (hwndTarget != null) 
      { 
       hwndTarget.RenderMode = RenderMode.SoftwareOnly; 
      } 
     }; 
    } 
} 

He probado esto y esta solución parece funcionar muy bien y hasta ahora es la única solución que he encontrado para resolver este problema dentro de un escenario de interoperabilidad FoxPro que es muy similar a los de Windows Forms que yo publicado sobre originalmente. Por ahora estoy planeando usar mi Refresh original en la solución MDI Parent para mi proyecto WinForms pero luego para mis otras aplicaciones nativas de interoperabilidad, como cuando mis controles WPF están alojados en Visual FoxPro, usaré esta solución. Eso es a menos que, por supuesto, si se descubre una solución más elegante para cualquiera de los casos.

También es importante tener en cuenta que la revelación de software es la única opción en sistemas XP y normalmente en Visual FoxPro. WinForms normalmente aprovecha el mismo tipo de aceleración de hardware que las aplicaciones WPF nativas en el sistema operativo Vista y arriba. Así que usar esta opción puede no ser tan malo como parece cuando tienes que lidiar con la interoperabilidad. Actualmente no estoy al tanto de ningún efecto secundario relacionado al usar esta solución, pero si hay alguno debería considerarse seriamente.

2

Compruebe los controladores de video y intente deshabilitar la aceleración de hardware. La mayoría de los artefactos son causados ​​por controladores defectuosos, tarjetas de video defectuosas o tiempo insuficiente para completar la actualización.

Primer paso de solución de problemas: actualizar los controladores de video. Obvio, lo sé.

tuve problema similar, comprobando la configuración de mi tarjeta de video NVidia (Panel de control) mostraron configuración global fijado muy alto causando un intervalo más largo de refresco que puede ser abortado si se toma demasiado tiempo. Establecer la configuración de nuevo a los valores predeterminados resolvió la mayor parte del problema. Pero también ejecuto programas de hash que usan la GPU intensamente, así que esta es probablemente la causa de mi problema de artefactos de repetición, que ahora es muy raro y muestra su cara más fea en Visual Studio.

Otro paso me encontré con la solución de problemas es deshabilitar la aceleración de hardware para WPF, esto se puede hacer en 'HKEY_CURRENT_USER/Software/Microsoft/Avalon.Graphics', o tal vez una aplicación puede hacerlo, pero esto es sólo para la solución de problemas; nunca los configure dentro de una aplicación porque se deshabilitará para TODAS las aplicaciones de WPF. No tengo esta configuración de registro ni la agregué, así que no estoy seguro del éxito con ella, pero muchos dicen que esto resolvió su problema. También tenga en cuenta que algunas aplicaciones tienen esta opción disponible, intente desactivarla si está disponible.

Otro paso de solución de problemas es asegurarse de que la tarjeta de video tenga el nivel adecuado para el renderizado. Cualquier tarjeta que soporta DX9 o mayor debe ser suficiente, pero hay otros factores implicados (como es mi caso) por lo que sólo porque está en la lista no significa que sea adecuada para su propósito.

Finalmente, puede usar el Visual Profiler (parte del SDK de Windows) y otras herramientas para ayudar a determinar qué está sucediendo más precisamente con el rendimiento de WPF en relación con la capacidad de gráficos.

notas de nivel de representación de nivel y la información de rendimiento de WPF ->http://msdn.microsoft.com/en-us/library/vstudio/ms742196(v=vs.90).aspx

Esperamos que esto ayude a alguien.

--Ryan Estrasburgo

0

su UserControl o evento cargado ventana;

this.WindowState = System.Windows.WindowState.Minimized; 

this.WindowState = System.Windows.WindowState.Normal; 

puede parecer una mala solución. no es necesario golpearse la cabeza contra la pared.

Un proverbio turco dice: el mejor código es el código que se está ejecutando :)

Cuestiones relacionadas