How do I suspend painting for a control and its children?

前端 未结 10 1946
小鲜肉
小鲜肉 2020-11-22 01:34

I have a control which I have to make large modifications to. I\'d like to completely prevent it from redrawing while I do that - SuspendLayout and ResumeLayout aren\'t eno

相关标签:
10条回答
  • 2020-11-22 02:04

    Or just use Control.SuspendLayout() and Control.ResumeLayout().

    0 讨论(0)
  • 2020-11-22 02:05

    A nice solution without using interop:

    As always, simply enable DoubleBuffered=true on your CustomControl. Then, if you have any containers like FlowLayoutPanel or TableLayoutPanel, derive a class from each of these types and in the constructors, enable double buffering. Now, simply use your derived Containers instead of the Windows.Forms Containers.

    class TableLayoutPanel : System.Windows.Forms.TableLayoutPanel
    {
        public TableLayoutPanel()
        {
            DoubleBuffered = true;
        }
    }
    
    class FlowLayoutPanel : System.Windows.Forms.FlowLayoutPanel
    {
        public FlowLayoutPanel()
        {
            DoubleBuffered = true;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 02:08

    I know this is an old question, already answered, but here is my take on this; I refactored the suspension of updates into an IDisposable - that way I can enclose the statements I want to run in a using statement.

    class SuspendDrawingUpdate : IDisposable
    {
        private const int WM_SETREDRAW = 0x000B;
        private readonly Control _control;
        private readonly NativeWindow _window;
    
        public SuspendDrawingUpdate(Control control)
        {
            _control = control;
    
            var msgSuspendUpdate = Message.Create(_control.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);
    
            _window = NativeWindow.FromHandle(_control.Handle);
            _window.DefWndProc(ref msgSuspendUpdate);
        }
    
        public void Dispose()
        {
            var wparam = new IntPtr(1);  // Create a C "true" boolean as an IntPtr
            var msgResumeUpdate = Message.Create(_control.Handle, WM_SETREDRAW, wparam, IntPtr.Zero);
    
            _window.DefWndProc(ref msgResumeUpdate);
    
            _control.Invalidate();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 02:09

    The following is the same solution of ng5000 but doesn't use P/Invoke.

    public static class SuspendUpdate
    {
        private const int WM_SETREDRAW = 0x000B;
    
        public static void Suspend(Control control)
        {
            Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero,
                IntPtr.Zero);
    
            NativeWindow window = NativeWindow.FromHandle(control.Handle);
            window.DefWndProc(ref msgSuspendUpdate);
        }
    
        public static void Resume(Control control)
        {
            // Create a C "true" boolean as an IntPtr
            IntPtr wparam = new IntPtr(1);
            Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam,
                IntPtr.Zero);
    
            NativeWindow window = NativeWindow.FromHandle(control.Handle);
            window.DefWndProc(ref msgResumeUpdate);
    
            control.Invalidate();
        }
    }
    
    0 讨论(0)
提交回复
热议问题