Search code examples
c#winformsawesomium

Block "OnPaint" event while resizing


I am painting a control from a buffer. My code for painting is it:

    protected override void OnPaint(PaintEventArgs e)
    {
        if (surface != null)
        {
            using (Bitmap Pintar = new Bitmap(e.ClipRectangle.Width, e.ClipRectangle.Height))
            {

                BitmapData bmd = Pintar.LockBits(new Rectangle(0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);

                e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;

                int DtX = e.ClipRectangle.X;
                int DtY = e.ClipRectangle.Y;

                Console.WriteLine(DtX + " - " + bmd.Width + " || " + DtY + " - " + bmd.Height);
                unsafe
                {
                    byte* PunteroL = (byte*)bmd.Scan0;
                    byte* PunteroS = (byte*)(surface.Buffer + (DtX * 4 + surface.Width * DtY * 4));

                    for (int Y = 0; Y < bmd.Height; Y++)
                    {
                        byte* PunteroLT = (byte*)(PunteroL + (bmd.Width * Y * 4));
                        byte* PunteroST = (byte*)(PunteroS + (surface.Width * Y * 4));
                        for (int X = 0; X < bmd.Width; X++)
                        {
                            byte* PunteroLS = (byte*)(PunteroLT + (X * 4));
                            byte* PunteroSS = (byte*)(PunteroST + (X * 4));

                                PunteroLS[0] = PunteroSS[0];
                                PunteroLS[1] = PunteroSS[1];
                                PunteroLS[2] = PunteroSS[2];

                        }
                    }
                }

                Pintar.UnlockBits(bmd);
                e.Graphics.DrawImage(Pintar, DtX, DtY, Pintar.Width, Pintar.Height);
            }
        }
    }

The problem here is when I resize the window I got an error "Tryng access to protected memory" and this is because of pointers..

I wanna know if there is any way to leave (or block) the OnPaint event while the user is resizing the view..

Thank! =)


Solution

  • What worked best for me in a similar situation was the solution described in this SO thread.

    In an nutshell, it is suggested to add to your control the following import:

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
    
    private const int WM_SETREDRAW = 11;
    

    And the following methods:

    public static void SuspendDrawing( Control parent )
    {
        SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
    }
    
    public static void ResumeDrawing( Control parent )
    {
        SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
        parent.Refresh();
    }
    

    Then all you have to do is call SuspendDrawing before the re-size takes place and ResumeDrawing after.

    Update:

    Personally I prefer using it as an extension method, thus making it available for all controls I use without duplicating code or inheriting from base class...

    public static class MyExtensionClass
    {
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
    
        private const int WM_SETREDRAW = 11; 
    
        public static void SuspendDrawing(this Control ctrl )
        {
            var parent = ctrl.Parent;
            if(parent != null)
            {
                SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
            }
        }
    
        public static void ResumeDrawing(this Control ctrl )
        {
            var parent = ctrl.Parent;
            if(parent != null)
            {
                SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
                parent.Refresh();
            }
        }
    }