visual tamaño formularios formulario eventos escala controles autoscalemode automático ajuste ajustar c# .net winforms performance

c# - tamaño - Formularios de Windows: el uso de BackgroundImage ralentiza el dibujo de los controles del formulario



autoscalemode c# (6)

Tengo un Windows Form (C # .NET 3.5) con una cantidad de botones y otros controles, todos asignados a un Panel superior que abarca todo el Formulario. Por ejemplo, la jerarquía es: Formulario -> Panel -> otros controles.

Tan pronto como asigno una Imagen de Fondo al Panel, los controles se dibujan muy lentamente. Tengo el mismo efecto si utilizo la propiedad BackgroundImage del Formulario y establezco BackgroundColor del Panel como "transparente". Parece que la ventana con el fondo se dibuja primero, luego cada control se agrega uno a uno con un ligero retraso antes de dibujar el siguiente. En otras palabras, puede seguir el orden en que cada control se dibuja en el formulario. Una vez que se han dibujado todos los controles una vez que este efecto ya no ocurre, la capacidad de respuesta del formulario es aún lenta.

En el diseñador de Visual Studio obtengo el mismo efecto, especialmente notable cuando muevo controles alrededor. A veces, el dibujo del formulario se detiene por completo durante uno o dos segundos, lo que hace que trabajar con BackgroundImage sea un arrastre total, tanto en el diseñador como en la aplicación resultante.

Por supuesto, traté de usar DoubleBuffered = true, y también lo configuré en todos los controles usando reflection, sin efecto.

Además, aquí está el código de carga de formularios porque es un poco inusual. Copia todos los controles de otra forma en el formulario actual. Esto se hace para poder editar el aspecto visual de cada pantalla por separado utilizando el diseñador mientras se comparte una forma común y una base de código común. Tengo la corazonada de que puede ser la causa de las ralentizaciones, pero aún no explica por qué las ralentizaciones ya son evidentes en el diseñador.

private void LoadControls(Form form) { this.SuspendLayout(); this.DoubleBuffered = true; EnableDoubleBuffering(this.Controls); this.BackgroundImage = form.BackgroundImage; this.BackColor = form.BackColor; this.Controls.Clear(); foreach (Control c in form.Controls) { this.Controls.Add(c); } this.ResumeLayout(); }

Como puede ver, SuspendLayout() y ResumeLayout() se utilizan para evitar el redibujado innecesario.

Aún así, la forma es "lenta como el infierno" una vez que se utiliza una imagen de fondo. Incluso traté de convertirlo a PNG, JPG y BMP para ver si eso marca alguna diferencia. Además, la imagen tiene un tamaño de 1024x768, pero las imágenes más pequeñas tienen el mismo efecto de desaceleración (aunque un poco menos).

¿Que debería hacer?


SuspendLayout() y ResumeLayout() no suspenden el dibujo, solo las operaciones de diseño. Dale una oportunidad a este tipo:

public static class ControlHelper { #region Redraw Suspend/Resume [DllImport("user32.dll", EntryPoint = "SendMessageA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)] private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); private const int WM_SETREDRAW = 0xB; public static void SuspendDrawing(this Control target) { SendMessage(target.Handle, WM_SETREDRAW, 0, 0); } public static void ResumeDrawing(this Control target) { ResumeDrawing(target, true); } public static void ResumeDrawing(this Control target, bool redraw) { SendMessage(target.Handle, WM_SETREDRAW, 1, 0); if (redraw) { target.Refresh(); } } #endregion }

El uso debe ser bastante autoexplicativo, y la sintaxis es idéntica a SuspendLayout() y ResumeLayout() . Estos son métodos de extensión que se mostrarán en cualquier instancia de Control.


También me enfrenté al mismo problema y pude resolverlo reduciendo la resolución de la imagen de fondo. Cuando utiliza imágenes de gran tamaño (p. Ej .: 1280X800) como fondo, tomará tiempo dibujar controles en el formulario. Es mejor abrir la imagen en tamaño ''Paint'' que más pequeña que su formulario y luego guardar en formato ''bmp''. Ahora intenta agregar esta imagen como fondo de tu formulario.


Otra forma muy simple de evitar los rediseños permanentes al agregar los controles es hacer que el control primario sea invisible antes de agregarle controles. Posteriormente, usted hace que el control principal (por ejemplo, un panel) sea visible y allí está sin todos los repintados. :-)

panelParent.visible = false; for(...) { // Add your controls here: panelParent.Controls.Add(...); } panelParent.visible = true;



Me doy cuenta de que este es un hilo viejo, pero lo encontré mientras buscaba información sobre el mismo problema, por lo que en caso de que sea útil para alguien en algún momento:

Mi situación: tengo una grilla de paneles de 13 x 12, que tienen una imagen de fondo configurada dinámicamente y cambiada regularmente, según las selecciones de los usuarios. Cada Panel también tiene un control de etiqueta de texto agregado. Para que el texto se superponga a la imagen de fondo, tiene que establecerse en Transparente (por cierto, mi experiencia fue que BackgroundImageLayout de Zoom, Stretch, Center tuvo poco o ningún efecto. BackColor establecido en transparente o blanco también tuvo poco efecto).

Cada extracción de la grilla de paneles (incluido el cambio de tamaño) tardaba aproximadamente un segundo, no está mal, pero es muy visible, y un problema de usabilidad en máquinas más lentas.

Mis imágenes no eran enormes, pero sí algo grandes.

Lo que encontré: al cambiar el tamaño de mi conjunto de imágenes al tamaño exacto del panel antes de configurar la imagen de fondo, el tiempo de dibujo disminuyó drásticamente, en algún momento alrededor de 0.1 segundos. Como mi programa cambia el tamaño de los paneles según el tamaño de la ventana, cambio el tamaño del conjunto de imágenes de forma dinámica en el evento de redimensionamiento de Windows antes de configurar el fondo de los 156 paneles.

En retrospectiva, es una optimización obvia ... cambiar el tamaño de 8 imágenes una vez en lugar de repetidas veces 156 veces.


Resolví el mismo problema usando PictureBox . Simplemente agregue PictureBox a su contenedor, elija "Dock it in parent container" (o Dock propiedad = Fill ) y configure su imagen. Se verá igual que BackGroundImage del control principal.