views:

2341

answers:

2

I have a Windows Form (C# .NET 3.5) with a number of buttons and other controls on it, all assigned to a topmost Panel which spans the whole Form. Eg the hierarchy is: Form -> Panel -> other Controls.

As soon as i assign a BackgroundImage to the Panel the Controls draw very slowly. I have the same effect if i use the Form's BackgroundImage property and set the Panel's BackgroundColor to "transparent". It appears as if the window with the background is drawn first, then each Control is added one-by-one each with a slight delay before the next is drawn. In other words you can actually follow the order in which each Control is drawn to the Form. Once all Controls have been drawn once this effect doesn't happen anymore but the responsiveness of the Form is still slow.

In Visual Studio's designer i get the same effect, especially noticeable when moving controls around. Sometimes the form's drawing stops completely for a second or two which makes working with BackgroundImage a total drag, both in Designer and the resulting application.

Of course i tried using DoubleBuffered = true and i also set it on all controls using reflection, to no effect.

Also here's the forms loading code because it's a bit unusual. It copies all Controls from another form onto the current form. This is done in order to be able to edit each screen's visual appearance seperately using the Designer while sharing a common form and common code basis. I have a hunch that it may be the cause of the slowdowns but it still doesn't explain why the slowdowns are already noticeable in the Designer.

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

As you can see SuspendLayout() and ResumeLayout() are used to avoid unnecessary redraw.

Still, the form is "slow as hell" once a BackgroundImage is used. I even tried converting it to PNG, JPG and BMP to see if that makes any difference. Also, the image is 1024x768 in size but smaller images have the same slowdown effect (although slightly less).

Any ideas/tips?

+5  A: 

SuspendLayout() and ResumeLayout() do not suspend drawing, only layout operations. Give this guy a shot:

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
}

Usage should be pretty self-explanatory, and the syntax is identical to SuspendLayout() and ResumeLayout(). These are extension methods that will show on any instance of Control.

Adam Robinson
it didn't help ... i also noticed that when popup menus overlay some of the button and force them to redraw, the redraw is particularly slow (eg you see the buttons border drawn, button filled with solid color, finally button draws it's picture, then follows the next button).
steffenj
This actually gave me a huge performance increase! I had about 60 labels on a single control, placed in a table layout panel. The columns was set to automatically resize, which took a lot of time to re-render. This trick seems to suspend the drawing, until the layout is complete, removing the annoying visible redraw.
TigerShark
A: 

For me this post solve problem: http://www.c-sharpcorner.com/Forums/ShowMessages.aspx?ThreadID=45434

"Make sure your backgroundcolor is not set to 'transparent'. Set to 'white' for better performance.

Also, do backgroundimagelayout to be either 'center' or 'streach' to increase performance. This will enable the double buffer on the form"