1

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! =)

  • http://msdn.microsoft.com/en-us/library/system.windows.forms.control.resizeredraw(v=vs.110).aspx – Sam Axe Apr 16 '14 at 23:29
  • I know but the problem is: When I resize, the surface.buffer and I think I am getting memory problems for this. So I think the solution will be cancel the OnPaint event while I am resizing the window. – Gonza Fernandez Yaique Apr 16 '14 at 23:37
  • @user3504823: That sounds like a hack, not a solution. Perhaps you are using the `Width` and `Height` of the window somewhere when you ought to be using the `Width` and `Height` of the bitmap/surface? – Ben Voigt Apr 17 '14 at 06:08
  • @BenVoigt the size of the surface is the same as the window. When I resize the window I have to resize the surface. – Gonza Fernandez Yaique Apr 18 '14 at 03:03

3 Answers3

0

Try to implement a event handler on Form.ResizeBegin, in which you will remove your OnPaint handler from your control.

Then you would just have to restore it in Form.ResizeEnd.

Kilazur
  • 3,089
  • 1
  • 22
  • 48
0

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();
        }
    }
}
Community
  • 1
  • 1
Avi Turner
  • 10,234
  • 7
  • 48
  • 75
  • Works pertectly! I love it!! But I changed parent.Refresh(); to parent.Update(); else I got error sometimes. Only a ask, how can I call those voids from my UserControl? I dont know how handle the Control inside him. I mean ResumeDrawing(what here?); Meanwhile I changed the var parent = ctrl.Parent to parent = ctrl and I call ResumeDrawing(this.Parent); Thank!! – Gonza Fernandez Yaique Apr 18 '14 at 05:14
0

You have to get the ResizeBegin and the ResizeEnd events.

The code in there should look like:

        private void OnResizeEnd(object sender, EventArgs e)
        {
            Paint += OnPaint;
        }

        private void OnResizeBegin(object sender, EventArgs e)
        {
            Paint -= OnPaint;
        }
Tomtom
  • 9,087
  • 7
  • 52
  • 95
  • This was also my instinct but those events are `Form` events. The question was about `Control` resizing – Avi Turner Apr 17 '14 at 07:51
  • If your Control is in a Form you can add Methods to your UserControl where you cann add or remove the Eventhandler through the form – Tomtom Apr 17 '14 at 07:59
  • I am not sure I understand how you plan on doing this. if you mean something like the example in this [thread](http://stackoverflow.com/questions/2577887/resizeend-equivalent-for-usercontrols), you will still be getting the events of the form being re sized, not the control. It is not necessarily the same event. He might want to allow the user to re size the control without re sizing the form – Avi Turner Apr 17 '14 at 08:11
  • @AviTurner sorry. I was bad explaining the problem. When I resize the form, my usercontrol has to be resized too. The user can't resize only the "UserControl" without resizing the form. But I will consider your example. Thank! =) – Gonza Fernandez Yaique Apr 18 '14 at 01:31
  • And @Tomtom I will take a look to these events. – Gonza Fernandez Yaique Apr 18 '14 at 01:32