¿Puedo suspender el redibujado de un formulario hasta que haya realizado todas las actualizaciones?

StackOverflow https://stackoverflow.com/questions/615781

Pregunta

Al usar C # y .Net 2.0, estoy usando una forma con forma irregular (TransparencyKey, FormBorderStyle = None, etc ...) y quiero permitir que " normal " modo bordeado.

Cambio el color de fondo a predeterminado de Lime Cambio FormBorderStyle a FixedSingle Cambio la Clave de Transparencia a Color. Ninguna

Desafortunadamente, esto parece un completo desorden en la pantalla con la imagen saltando unos pocos píxeles hacia abajo y hacia un lado y la forma verde lima.

Creo que esto se debe a que el formulario se vuelve a dibujar después de cada línea de código. ¿Es posible suspender el dibujo del formulario hasta que haya realizado mis cambios y luego simplemente volver a dibujar el formulario una vez?

G

¿Fue útil?

Solución

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

ANTIGUA respuesta: anule el WndProc y bloquee el mensaje WM_ERASEBKGND .

Explicación de lo que hace el siguiente código:

Cuando se invalida la región de una ventana, Windows envía una serie de mensajes al control que dan como resultado un widget recién pintado. 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 generalmente consumimos nosotros en el evento OnPaint), se realiza el dibujo real. Si este dibujo no es trivial, habrá un retraso antes de que se actualice el widget y obtendrás un parpadeo molesto.

Mirando tu código otra vez, estaba claramente resolviendo un problema diferente. Prueba este nuevo ejemplo. Bloqueará la pintura del formulario / control si la bandera bAllowPaint no está establecida.

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

Otros consejos

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

Además, si su formulario tiene controles secundarios, establezca también DoubleBuffered en true (y también en los hijos de los niños, etc.)

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

Está modificando las propiedades que tienen un impacto bastante grande en un formulario. TransparencyKey y FormBorderStyle requieren cambiar los bits de estilo de ventana. Windows no permite que esos bits de estilo se cambien. Windows Forms los implementa destruyendo completamente la ventana y volviéndola a crear desde cero. Buen truco, pero eso lleva tiempo y la forma se volverá a pintar cada vez que cambies el estilo. Causando el efecto visual desagradable que ves.

Prueba esto: 1. Ponga la opacidad en 0 para que la forma se vuelva invisible. 2. Cambiar BackColor, no hay problema 3. Cambie FormBorderStyle, la ventana se vuelve a crear 4. Cambiar TransparencyKey, la ventana se vuelve a crear 5. Cambie la opacidad a 1, la ventana se recreará y luego se verá

Por ejemplo:

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

Si todo esto falla, puedes intentar un poco de pirateo bloqueando todos los mensajes de Paint en tu formulario.

ADVERTENCIA: no estoy promocionando el uso de este método, pero puedes intentarlo si realmente lo deseas. 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 soporte:

public class Win32
{
  private Win32() { }

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

Una forma de enviar todas las " imagen " de la forma a la pantalla en un solo paso es habilitar DoubleBuffer.

En el Constructor puedes establecer los estilos de control

VB.NET:

SetStyle(ControlStyles.DoubleBuffer, True)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top