2009-06-04 21 views

Respuesta

37

El método Invalidate() causará un repintado. serán levantados

MSDN Link

4

control.invalidate de llamadas y el evento de pintura.

+1

privada vacío Form1_Paint (object sender, System.Windows.Forms.PaintEventArgs e) { System.Drawing.Graphics gráficos = this.CreateGraphics(); System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle (0, 0, 50, 50); graphics.DrawEllipse (System.Drawing.Pens.Black, rectangle); graphics.DrawRectangle (System.Drawing.Pens.Red, rectangle); } ¿Cuándo se llama este método de pintura para volver a pintar el formulario? Sí vuelve a pintar la forma, ¿no? –

5

Creo que también puede llamar al Refresh().

+0

Gracias Brian. Funcionó muy bien.! –

77

En un método de su formulario o control, que tienen 3 opciones:

this.Invalidate(); // request a delayed Repaint by the normal MessageLoop system  
this.Update();  // forces Repaint of invalidated area 
this.Refresh();  // Combines Invalidate() and Update() 

Normalmente, usted acaba de llamar Invalidate() y dejar que el sistema se combinan con otras actualizaciones de la pantalla. Si tiene prisa, debe llamar al Refresh(), pero luego corre el riesgo de que se vuelva a pintar varias veces consecutivamente debido a otros controles (especialmente el principal) Invalidación.

La manera normal en que Windows (Win32 y WinForms.Net) maneja esto es esperar a que MessageQueue se ejecute en blanco y luego procesar todas las áreas de pantalla invalidadas. Eso es eficiente porque cuando algo cambia, generalmente cambia a otras cosas (controles) cambiando también.

El escenario más común para Update() es cuando cambia una propiedad (por ejemplo, etiqueta1.Texto, que invalidará la etiqueta) en un bucle for y ese bucle bloquea temporalmente el bucle de mensajes. Siempre que lo use, debería preguntarse si no debería usar un hilo en su lugar. Pero la respuesta no siempre es Sí.

+8

Me gustaría aclarar. Update() volverá a pintar inmediatamente cualquier parte del control que ya esté invalidado. Aún necesita invalidar primero. Refresh() invalidará e inmediatamente volverá a pintar todo el control. Cuando escribo un control que hace su propio dibujo, llamo a Invalidate() con un rectángulo sucio, luego llamo a Update() por razones de receptividad, y me mantengo alejado de Refresh() por el bien del rendimiento. – snarf

+0

Tenga en cuenta que puede haber una gran diferencia en el rendimiento de la CPU según el método que utilice. 'this.Invalidate()' requiere menos recursos de CPU ya que no está forzando cosas fuera del bucle de mensaje estándar, y esto es especialmente cierto si puede llamar a 'this.Invalidate (false)' para que solo llame 'OnPaint () 'en el control/formulario principal y no en los controles secundarios. Para uno de mis UserControls, pasar de 'this.Update()' a 'this.Invalidate (false)' reduce la carga de la CPU por un factor de 4. –

3

Actualizar probablemente también haría que el código sea mucho más legible, dependiendo del contexto.

6

Encontré Invalidate() creando demasiado parpadeo. Esta es mi situación. Un control personalizado que estoy desarrollando dibuja todo el contenido mediante la manipulación del evento Paint.

this.Paint += this.OnPaint; 

Este controlador llama a una rutina personalizada que hace la pintura real.

private void OnPaint(object sender, PaintEventArgs e) 
{ 
    this.DrawFrame(e.Graphics); 
} 

Para simular el desplazamiento Quiero pintar mi control cada vez que el cursor se mueva mientras se mantiene pulsado el botón izquierdo del ratón. Mi primera opción fue utilizar el Invalidate() como el siguiente.

private void RedrawFrame() 
{ 
    var r = new Rectangle(
     0, 0, this.Width, this.Height); 

    this.Invalidate(r); 
    this.Update(); 
} 

Los rollos de control bien, pero parpadea mucho más allá de cualquier nivel cómodo. Así que decidí, en lugar de repintar el control, llamar a mi método personalizado DrawFrame() directamente después de manejar el evento MouseMove. Eso produjo un desplazamiento suave sin parpadeos.

private void RedrawFrame() 
{ 
    var g = Graphics.FromHwnd(this.Handle); 
    this.DrawFrame(g); 
} 

Este enfoque puede no ser aplicable en todas las situaciones, pero hasta ahora me viene bien.

+0

+1 para 'this.Invalidate (r)' –

+1

Tenga cuidado, I piense que el resultado de FromHwnd() debería volver a Disposed (póngalo en un 'using() {}') –

+3

Use doble buffering para eliminar el parpadeo. – TheRealChx101

0

uso Control.InvokePaint también se puede utilizar para el doble buffer manual de

Cuestiones relacionadas