2009-09-05 16 views
23

Tengo una ventana WPF muy simple: lo único que hay es un botón alineado a la derecha. Cuando cambio el tamaño de la ventana arrastrando el límite izquierdo, el botón salta alrededor, mucho. Pruébelo usted mismo, arrastre el límite izquierdo hacia adelante y hacia atrás.Cómo arreglar el tamaño de formulario de WPF: ¿controles rezagados y fondo negro?

Además, un fondo negro queda expuesto temporalmente durante el cambio de tamaño.

En this pregunta, hice una pregunta similar acerca de Windows Forms. La única respuesta que obtuve sugirió que esto se corrigió en WPF; sin embargo, sorprendentemente, no solo no está solucionado, sino que WPF también agrega un segundo error visual: el fondo negro temporal.

A continuación se muestra el aspecto del control de lag; esto ocurre cuando cambio el tamaño de la ventana por su borde superior (grabado con una cámara porque la pantalla-cap hizo menos evidente al hacer todo lo lento):

                                                  enter image description here

Ejemplo del borde negro: se capturó al cambiar el tamaño de la ventana; es sólo así durante una fracción de segundo, pero es muy notable:

                                      enter image description here

¿Estoy haciendo algo mal? ¿Cómo puedo mantener mis controles visualmente en un solo lugar durante el cambio de tamaño? ¿Cómo puedo evitar el borde negro?

Nota: el botón termina en el lugar correcto finalmente - que sólo salta de las brevemente durante el cambio de tamaño.

+0

Acabo de crear una lista de capturas de pantalla para demostrar la idea. –

+5

Me mantiene conmocionado. Microsoft crea una tecnología maravillosa para diseñar bellas interfaces de usuario e introdujo este horrible error visual. –

Respuesta

10

Este es el código de trabajo completo basado en la segunda solución de Wieser Software Ltd.

public partial class MainView : Window 
{ 
    public MainView() 
    { 
     InitializeComponent(); 

     //ensure win32 handle is created 
     var handle = new WindowInteropHelper(this).EnsureHandle(); 

     //set window background 
     var result = SetClassLong(handle, GCL_HBRBACKGROUND, GetSysColorBrush(COLOR_WINDOW)); 
    } 

    public static IntPtr SetClassLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) 
    { 
     //check for x64 
     if (IntPtr.Size > 4) 
      return SetClassLongPtr64(hWnd, nIndex, dwNewLong); 
     else 
      return new IntPtr(SetClassLongPtr32(hWnd, nIndex, unchecked((uint)dwNewLong.ToInt32()))); 
    } 

    private const int GCL_HBRBACKGROUND = -10; 
    private const int COLOR_WINDOW = 5; 

    [DllImport("user32.dll", EntryPoint = "SetClassLong")] 
    public static extern uint SetClassLongPtr32(IntPtr hWnd, int nIndex, uint dwNewLong); 

    [DllImport("user32.dll", EntryPoint = "SetClassLongPtr")] 
    public static extern IntPtr SetClassLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong); 

    [DllImport("user32.dll")] 
    static extern IntPtr GetSysColorBrush(int nIndex); 
} 
+0

Esto funciona para cambiar el color del bit negro que se muestra. Esto puede aliviar el problema hasta cierto punto, dependiendo del contenido de la ventana. Por supuesto, para fondos complejos (como una imagen), el bit que muestra sigue estando notablemente mal, ya que el problema subyacente (el retraso del diseño de control y el hecho de tener partes sin pintar de la ventana brevemente visibles) aún permanece. –

1

Creo que el fondo negro temporal es un problema de WPF relacionado con el hecho de que WPF usa DirectX como mecanismo de representación, y cuando cambia el tamaño de las ventanas tiene que sincronizar el dibujo con el sistema de ventanas. Esto también puede explicar por qué el botón está fuera de lugar en relación con la ventana mientras arrastra el borde de la ventana. Dibujar el área no cliente de la ventana es mucho más lento que dibujar lo que está dentro de la ventana, y si mueve el mouse rápidamente en una computadora lenta, las discrepancias entre el borde y el interior de la ventana probablemente serán más notorias.

Supuestamente esto solo ocurre en Vista con Aero habilitado, y debería haber sido arreglado en Vista SP1. Sin embargo, acabo de probar en SP2, y todavía veía un poco de fondo negro, pero solo cuando Aero estaba habilitado. Mi tarjeta gráfica es bastante rápida, por lo que apenas se nota.

Si mi análisis es correcto, la única forma en que puede solucionar su problema es obtener una tarjeta gráfica más rápida o apagar Aero.

+0

Gracias, su sugerencia puede hacer esto menos notable, pero no puede eliminarlo por completo. El problema no es cuánto tiempo es visible, sino que es visible en absoluto ... Por cierto, el problema también está presente en Win7 RTM. –

+5

Lo veo con WPF4.0 y Win7 64bit SP1 – sprocket12

2

Esto no parece posible en las versiones actuales de WPF.

4

Hay dos soluciones, que se describen aquí: http://wieser-software.blogspot.co.uk/2012/06/wpf-window-rendering-woes.html

  1. WndProc gancho y el mango WM_ERASEBKGND y dibujar el sistema WINDOW_COLOR en el fondo, u otro color para adaptarse a su tema de la aplicación. SetClassLong
  2. Call para configurar el fondo de la clase de la ventana Brush

    SetClassLong (Handle, GCL_HBRBACKGROUND, GetSysColorBrush (COLOR_WINDOW));

+0

Esto cambia el color, de hecho, así que +1, pero estoy tratando de hacer que el color no se muestre en primer lugar. Quiero decir que es como los días de GDI donde todo se repintaba de atrás hacia adelante. ¿No puede doble buffer? ... :) –

+0

Puede extender el cristal en el área del cliente para obtener un efecto diferente, pero solo funciona si se enciende el aero. –

Cuestiones relacionadas