2008-10-10 26 views
6

Tengo un RichTextBox donde necesito actualizar la propiedad de texto con frecuencia, pero cuando lo hago, el RichTextBox "parpadea" molestamente, ya que actualiza todo a lo largo de una llamada a un método.¿Cómo se evita que un RichTextBox refresque su pantalla?

Tenía la esperanza de encontrar una manera fácil de suprimir temporalmente la actualización de la pantalla hasta que mi método esté hecho, pero lo único que he encontrado en la web es anular el método WndProc. He empleado este enfoque, pero con algunas dificultades y efectos secundarios, y también dificulta la depuración. Parece que debe haber una mejor forma de hacerlo. ¿Puede alguien señalarme una mejor solución?

Respuesta

-3

Trate de hacer esto:

myRichTextBox.SuspendLayout(); 
DoStuff(); 
myRichTextBox.ResumeLayout(); 
+0

es posible que también tenga que añadir myRichTextBox.Enabled = false; y el último habilitado = verdadero; – Geoff

+4

SuspendLayout() realmente no ayuda aquí. –

0

Podría simplemente almacenar el texto en una cadena, hacer sus manipulaciones sobre la cuerda, y al final del método, almacenarlo de nuevo en la propiedad de texto?

3

encontrar aquí: http://bytes.com/forum/thread276845.html

que terminaron el envío de un WM_SETREDRAW a través de SendMessage para desactivar a continuación, volver a habilitar seguido de un Invalidar() después de haber terminado la actualización. Eso pareció funcionar.

Nunca he intentado este método. He escrito una aplicación con un RTB que tiene resaltado de sintaxis y utiliza el siguiente en la clase de OTR:

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == paint) 
    { 
     if (!highlighting) 
     { 
      base.WndProc(ref m); // if we decided to paint this control, just call the RichTextBox WndProc 
     } 
     else 
     { 
      m.Result = IntPtr.Zero; // not painting, must set this to IntPtr.Zero if not painting otherwise serious problems. 
     } 
    } 
    else 
    { 
     base.WndProc(ref m); // message other than paint, just do what you normally do. 
    } 
} 

Espero que esto ayude.

+0

WM_SETREDRAW funcionó para mí. Debería ser lo mismo que LockWindowUpdate. –

-1

Yo sugeriría mirar LockWindowUpdate

 

[DllImport("user32.dll", EntryPoint="LockWindowUpdate", SetLastError=true, 
ExactSpelling=true, CharSet=CharSet.Auto, 
CallingConvention=CallingConvention.StdCall)] 
+3

-1. Este no es su uso apropiado. Ver http://blogs.msdn.com/b/oldnewthing/archive/2007/02/19/1716211.aspx. –

9

hice la pregunta original, y la respuesta que funcionó mejor para mí era el uso de BoltBait de SendMessage() con WM_SETREDRAW. Parece tener menos efectos secundarios que el uso del método WndProc, y en mi aplicación funciona dos veces más rápido que LockWindowUpdate.

Dentro de mi clase RichTextBox extendida, acabo de agregar estos dos métodos, y los llamo cada vez que tengo que dejar de reiniciar el repintado mientras estoy procesando algo. Si quisiera hacer esto desde fuera de la clase RichTextBox, creo que funcionaría simplemente reemplazando "this" con la referencia a tu instancia de RichTextBox.

private void StopRepaint() 
    { 
     // Stop redrawing: 
     SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero); 
     // Stop sending of events: 
     eventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero); 
    } 

    private void StartRepaint() 
    { 
     // turn on events 
     SendMessage(this.Handle, EM_SETEVENTMASK, 0, eventMask); 
     // turn on redrawing 
     SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero); 
     // this forces a repaint, which for some reason is necessary in some cases. 
     this.Invalidate(); 
    } 
+0

¿Hay alguna posibilidad de completar el código? Esto no es casi compilable como está escrito actualmente. –

10

Aquí es completo y ejemplo de trabajo:

private const int WM_USER = 0x0400; 
    private const int EM_SETEVENTMASK = (WM_USER + 69); 
    private const int WM_SETREDRAW = 0x0b; 
    private IntPtr OldEventMask;  

    [DllImport("user32.dll", CharSet=CharSet.Auto)] 
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); 

    public void BeginUpdate() 
    { 
     SendMessage(this.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero); 
     OldEventMask = (IntPtr)SendMessage(this.Handle, EM_SETEVENTMASK, IntPtr.Zero, IntPtr.Zero); 
    }  

    public void EndUpdate() 
    { 
     SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero); 
     SendMessage(this.Handle, EM_SETEVENTMASK, IntPtr.Zero, OldEventMask); 
    } 
Cuestiones relacionadas