2009-03-05 19 views
6

Usando C# y .Net 2.0, estoy usando una forma de forma irregular (TransparencyKey, FormBorderStyle = None, etc ...) y quiero permitir el modo de borde "normal".¿Puedo suspender el redibujado de un formulario hasta que haya realizado todas las actualizaciones?

puedo cambiar el color de fondo por defecto de cal cambio FormBorderStyle FixedSingle cambio la TransparencyKey Colour.None

Unfortuanately esto parece un completo desorden en la pantalla con la imagen El salto de unos pocos píxeles hacia abajo y hacia el lado y la forma verde lima.

Creo que esto es causado por el formulario que se vuelve a dibujar después de cada línea de código, ¿es posible suspender el dibujo hasta que haya realizado los cambios y luego vuelva a dibujar el formulario?

G

+1

[versión WPF] (http://stackoverflow.com/q/22563416/2596334) –

Respuesta

8

NUEVA respuesta: anule WndProc y bloquee el mensaje WM_PAINT mientras aplica las nuevas propiedades de Ventana.

OLD answer: anula WndProc y bloquea el mensaje WM_ERASEBKGND.

explicación de lo que hace el código de abajo:

Cuando se invalida región de una ventana, Windows envía una serie de mensajes al control que se traducen en un recién pintadas de widgets. Un mensaje temprano en esta serie es WM_ERASEBKGND. Normalmente, en respuesta a este mensaje, el control se pinta de un color sólido. Más tarde, en respuesta al mensaje WM_PAINT (que normalmente usamos en el evento OnPaint), el dibujo real está hecho. Si este dibujo no es trivial, habrá un retraso antes de que se actualice el widget y obtendrá un molesto parpadeo.

Al volver a ver el código, estaba resolviendo un problema diferente. Prueba este nuevo ejemplo. Bloqueará la pintura del formulario/control si el indicador bAllowPaint está desactivado.

El ejemplo NUEVO:

private const int WM_PAINT = 0x000F; 

    protected override void WndProc(ref Message m) 
    { 
     if ((m.Msg != WM_PAINT) || 
      (bAllowPaint && m.Msg == WM_PAINT)) 
     { 
      base.WndProc(ref m); 
     } 
    } 

El ejemplo OLD:

private const int WM_ERASEBKGND = 0x0014; 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg != WM_ERASEBKGND) // ignore WM_ERASEBKGND 
     { 
      base.WndProc(ref m); 
     } 
    } 
+0

Podría explicar con más detalle lo que esta por favor? Entiendo el concepto de anulación, ¿pero qué impide/hace este código? –

2

Pruebe la propiedad Form.DoubleBuffered. Establézcalo en 'verdadero'.

Además, si su formulario tiene controles secundarios, también establezca DoubleBuffered en true para aquellos también (y para hijos de niños, etc., en la línea).

Por último, llame a SuspendLayout antes de sus cambios y ResumeLayout después. Tenga en cuenta que esto solo afecta la ubicación de los controles secundarios. Si está haciendo un dibujo personalizado, la propiedad DoubleBuffered le dará más dinero por el dinero.

0

una forma de enviar toda la "imagen" de la forma a la pantalla en un solo paso es habilitar DoubleBuffer.

en el constructor se puede establecer el ControlStyles

VB.NET:

SetStyle(ControlStyles.DoubleBuffer, True) 
4

Está modificando propiedades que tienen un impacto bastante grande en un formulario. TransparencyKey y FormBorderStyle requieren cambiar los bits de estilo de ventana. Windows no permite cambiar esos bits de estilo. Windows Forms los implementa al destruir por completo la ventana y volver a crearla desde cero. Buen truco, pero eso lleva tiempo y el formulario se volverá a pintar cada vez que cambies el estilo. Causando el efecto visual desagradable que ves.

Prueba esto: 1. Conjunto opacidad al 0 por lo que la forma se vuelve invisible 2. Cambio BackColor, no hay problema 3. Cambio FormBorderStyle, la ventana se regenere 4. Cambio TransparencyKey, la ventana se regenere 5. Cambiar la opacidad a 1, la ventana se vuelve a crear, a continuación, visibles

por ejemplo:

this.Opacity = 0; 
    this.BackColor = Color.FromKnownColor(KnownColor.Control); 
    this.FormBorderStyle = FormBorderStyle.Sizable; 
    this.TransparencyKey = Color.Empty; 
    this.Opacity = 1; 
+0

FYI: el uso de este método no funciona en WPF. Cerca del 50% del tiempo de parpadeo todavía se puede ver. –

+0

Por supuesto, este es el código de Winforms. –

+0

Todavía estoy buscando una forma de suspender la pintura de una ventana de WPF temporalmente (mientras cambia el tamaño de la ventana/ubicación) ... –

2

Si todo esto falla, puede intentar alguna piratería de bajo nivel mediante el bloqueo de todos los mensajes de pintura a su formulario.

ADVERTENCIA: No estoy promoviendo el uso de este método, pero puede intentarlo si realmente lo desea. Me ha ayudado en el pasado.

Win32.LockWindowUpdate(this.Handle); 
try 
{ 
    //make your changes here 
} 
finally 
{ 
    //release the lock 
    Win32.LockWindowUpdate((IntPtr)0); 
} 

Este código se basa en el siguiente código de apoyo:

public class Win32 
{ 
    private Win32() { } 

    /// <summary> 
    /// Lock ore relase the wndow for updating. 
    /// </summary> 
    [DllImport("user32")] 
    public static extern int LockWindowUpdate(HWND hwnd); 
} 
+0

Según msdn, esto solo se debe usar al arrastrar y soltar: msdn.microsoft.com/en-us/library/windows/desktop/dd145034(v=vs.85).aspx –

Cuestiones relacionadas