En mi aplicación, me muevo constantemente de un control a otro. He creado no. de los controles de usuario, pero durante la navegación mis controles parpadean. tarda 1 o 2 segundos en actualizarse. Traté de configurar esto
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
or
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
pero no ayudó ... Cada control tiene la misma imagen de fondo con diferentes controles. Entonces, ¿cuál es la solución?
Gracias.
c#
winforms
user-controls
flicker
Royson
fuente
fuente
UpdateStyles
después de configurar estos? Está mal documentado, pero a veces puede ser necesario.Respuestas:
No es el tipo de parpadeo que puede resolver el doble búfer. Ni BeginUpdate o SuspendLayout. Tienes demasiados controles, la BackgroundImage puede hacer que sea un montón peor.
Comienza cuando UserControl se pinta a sí mismo. Dibuja la imagen de fondo, dejando huecos donde van las ventanas de control secundario. Luego, cada control secundario recibe un mensaje para pintarse a sí mismo, llenarán el agujero con el contenido de su ventana. Cuando tienes muchos controles, esos agujeros son visibles para el usuario por un tiempo. Normalmente son de color blanco, lo que contrasta mal con la imagen de fondo cuando está oscuro. O pueden ser negros si el formulario tiene su propiedad Opacity o TransparencyKey establecida, lo que contrasta mal con casi cualquier cosa.
Esta es una limitación bastante fundamental de Windows Forms, está atascada con la forma en que Windows representa Windows. Corregido por WPF por cierto, no usa ventanas para controles secundarios. Lo que querría es almacenar en búfer doble todo el formulario, incluidos los controles secundarios. Eso es posible, verifique mi código en este hilo para ver la solución. Sin embargo, tiene efectos secundarios y en realidad no aumenta la velocidad de pintura. El código es simple, pegue esto en su formulario (no en el control de usuario):
Hay muchas cosas que puede hacer para mejorar la velocidad de pintura, hasta el punto de que el parpadeo ya no se nota. Empiece por abordar la imagen de fondo. Pueden ser muy costosos cuando la imagen de origen es grande y necesita reducirse para ajustarse al control. Cambie la propiedad BackgroundImageLayout a "Tile". Si eso le da una aceleración notable, vuelva a su programa de pintura y cambie el tamaño de la imagen para que coincida mejor con el tamaño de control típico. O escriba el código en el método OnResize () de la UC para crear una copia de la imagen con el tamaño adecuado para que no tenga que cambiar de tamaño cada vez que el control vuelva a pintar. Utilice el formato de píxeles Format32bppPArgb para esa copia, se procesa unas 10 veces más rápido que cualquier otro formato de píxeles.
Lo siguiente que puedes hacer es evitar que los agujeros sean tan notorios y contrasten mal con la imagen. Puede desactivar la bandera de estilo WS_CLIPCHILDREN para UC, la bandera que evita que UC pinte en el área donde van los controles secundarios. Pegue este código en el código de UserControl:
Los controles secundarios ahora se pintarán sobre la imagen de fondo. Es posible que aún los vea pintándose uno por uno, pero el feo agujero intermedio blanco o negro no será visible.
Por último, pero no menos importante, la reducción del número de controles secundarios es siempre un buen enfoque para resolver problemas de pintura lenta. Anule el evento OnPaint () de la UC y dibuje lo que ahora se muestra en un niño. Particular Label y PictureBox son un desperdicio. Conveniente para apuntar y hacer clic, pero su alternativa liviana (dibujar una cadena o una imagen) toma solo una línea de código en su método OnPaint ().
fuente
Este es un problema real, y la respuesta que dio Hans Passant es excelente para salvar el parpadeo. Sin embargo, hay efectos secundarios, como él mencionó, y pueden ser feos (UI fea). Como se dijo, "Puede desactivar la
WS_CLIPCHILDREN
bandera de estilo para el UC", pero eso solo lo desactiva para un UC. Los componentes del formulario principal todavía tienen problemas.Por ejemplo, una barra de desplazamiento del panel no se pinta, porque técnicamente está en el área secundaria. Sin embargo, el componente secundario no dibuja la barra de desplazamiento, por lo que no se pinta hasta que se pasa el mouse (u otro evento lo activa).
Además, los íconos animados (cambiar íconos en un ciclo de espera) no funcionan. La eliminación de íconos en un
tabPage.ImageKey
no redimensiona / repinta las otras páginas de pestañas de manera apropiada.Así que estaba buscando una manera de desactivar la
WS_CLIPCHILDREN
pintura inicial para que mi formulario se cargue bien pintado, o mejor aún, solo lo encienda mientras cambia el tamaño de mi formulario con muchos componentes.El truco consiste en hacer que la aplicación llame
CreateParams
con elWS_EX_COMPOSITED/WS_CLIPCHILDREN
estilo deseado . Encontré un truco aquí ( https://web.archive.org/web/20161026205944/http://www.angryhacker.com/blog/archive/2010/07/21/how-to-get-rid-of- flicker-on-windows-forms-applications.aspx ) y funciona muy bien. ¡Gracias AngryHacker!Pongo la
TurnOnFormLevelDoubleBuffering()
llamada en elResizeBegin
evento de formulario yTurnOffFormLevelDoubleBuffering()
llamo en el evento ResizeEnd de formulario (o simplemente lo dejoWS_CLIPCHILDREN
después de que se haya pintado inicialmente correctamente).fuente
Si está haciendo alguna pintura personalizada en el control (es decir, anulando OnPaint), puede probar el doble búfer usted mismo.
E invalidar tu control con una propiedad
NeedRepaint
De lo contrario, la respuesta anterior con SuspendLayout y ResumeLayout es probablemente lo que desea.
fuente
if (image != null) image.Dispose();
antesimage = new Bitmap...
Pruebe los métodos BeginUpdate / EndUpdate O SuspendLayout / ResumeLayout. Consulte a continuación
Cómo solucionar problemas de parpadeo del control de winform anidado
Parpadeo durante las actualizaciones de controles en WinForms (por ejemplo, DataGridView)
fuente
En el formulario principal o control de usuario donde reside la imagen de fondo, establezca la
BackgroundImageLayout
propiedad enCenter
oStretch
. Notará una gran diferencia cuando el control de usuario esté renderizando.fuente
Traté de agregar esto como un comentario pero no tengo suficientes puntos. Esto es lo único que ha ayudado a mis problemas de parpadeo. Muchas gracias a Hans por su publicación. Para cualquiera que esté usando el constructor de c ++ como yo, aquí está la traducción
Agregue la declaración CreateParams al archivo .h del formulario principal de su aplicación, por ejemplo
y agregue esto a su archivo .cpp
fuente
Coloque el código a continuación en su constructor o evento OnLoad y si está utilizando algún tipo de control de usuario personalizado que tenga subcontroles, deberá asegurarse de que estos controles personalizados también tengan doble búfer (aunque en la documentación de MS dicen está establecido en verdadero de forma predeterminada).
Si está creando un control personalizado, es posible que desee agregar esta bandera a su ctor:
Opcionalmente, puede usar este código en su formulario / control:
Repasamos todos los controles del formulario / control y
DoubleBuffered
accedemos a su propiedad y luego lo cambiamos a verdadero para que cada control del formulario tenga doble búfer. La razón por la que reflexionamos aquí es porque imagina que tienes un control que tiene controles secundarios que no son accesibles, de esa manera, incluso si son controles privados, cambiaremos su propiedad a verdadera.Puede encontrar más información sobre la técnica de doble búfer aquí .
Hay otra propiedad que normalmente anulo para solucionar este problema:
WS_EX_COMPOSITED
- Pinta todos los descendientes de una ventana en orden de pintura de abajo hacia arriba usando doble búfer.Puedes encontrar más de estas banderas de estilo aquí .
¡Espero que ayude!
fuente
Solo para agregar a la respuesta que dio Hans:
(Versión TLDR: la transparencia es más pesada de lo que cree, use solo colores sólidos en todas partes)
Si WS_EX_COMPOSITED, DoubleBuffered y WS_CLIPCHILDREN no resolvieron su parpadeo (para mí WS_CLIPCHILDREN lo empeoró aún más), intente esto: revise TODOS sus controles y todo su código, y donde sea que tenga cualquier transparencia o semitransparencia para BackColor, ForeColor o cualquier otro color, solo quítalo, usa solo colores sólidos. En la mayoría de los casos en los que pensar que sólo tiene que usar la transparencia, no es así. Rediseñe su código y controles, y use colores sólidos. Tenía un parpadeo terrible, terrible y el programa funcionaba lento. Una vez que eliminé la transparencia, se aceleró significativamente y hay 0 parpadeo.
EDITAR: Para agregar más, acabo de descubrir que WS_EX_COMPOSITED no tiene que ser en toda la ventana, ¡podría aplicarse solo a controles específicos! Esto me ahorró muchos problemas. Simplemente cree un control personalizado heredado de cualquier control que necesite y pegue la anulación ya publicada para WS_EX_COMPOSITED. De esta manera, obtiene doble búfer de bajo nivel solo en este control, ¡evitando los desagradables efectos secundarios en el resto de la aplicación!
fuente
Sé que esta pregunta es muy antigua, pero quiero dar mi experiencia al respecto.
Tuve muchos problemas con el
Tabcontrol
parpadeo en un formulario anuladoOnPaint
y / oOnPaintBackGround
en Windows 8 usando .NET 4.0.Lo único que ha funcionado ha sido NO UTILIZAR el
Graphics.DrawImage
método enOnPaint
overrides, es decir, cuando se dibujaba directamente en los Gráficos proporcionados por elPaintEventArgs
, incluso pintando todo el rectángulo, el parpadeo desaparecía. Pero si llama alDrawImage
método, incluso dibujando un mapa de bits recortado, (creado para doble búfer) aparece el parpadeo.¡Espero eso ayude!
fuente
Combiné esta corrección de parpadeo y esta corrección de fuente , luego tuve que agregar un poco de mi propio código para iniciar un temporizador en la pintura para invalidar el TabControl cuando sale de la pantalla y regresa, etc.
Los tres hacen esto:
No soy el creador, pero por lo que tengo entendido, el mapa de bits evita todos los errores.
Esto fue lo único que resolvió definitivamente el parpadeo de TabControl (con iconos) para mí.
video de resultado de diferencia: vanilla tabcontrol vs tabcontrolex
http://gfycat.com/FineGlitteringDeermouse
PD. deberá establecer HotTrack = true, porque esto también corrige ese error
fuente
¿Probaste
Control.DoubleBuffered
Property?También esto y esto podrían ayudar.
fuente
No hay necesidad de ningún búfer doble y todas esas cosas chicos ...
Una solución simple ...
Si está utilizando la interfaz MDI, simplemente pegue el código a continuación en el formulario principal. Eliminará todo parpadeo de las páginas. Sin embargo, algunas páginas que requieren más tiempo para cargarse aparecerán en 1 o 2 segundos. Pero esto es mejor que mostrar una página parpadeante en la que cada elemento viene uno por uno.
Esta es la única mejor solución para toda la aplicación. Vea el código para poner en el formulario principal:
fuente