调整大小时阻止“OnPaint”事件

时间:2014-04-16 22:58:18

标签: c# winforms awesomium

我正在从缓冲区绘制一个控件。我的绘画代码是:

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

这里的问题是当我调整窗口大小时出现错误“尝试访问受保护的内存”这是因为指针..

我想知道在用户调整视图大小时是否有任何方法可以离开(或阻止)OnPaint事件..

感谢! =)

3 个答案:

答案 0 :(得分:0)

尝试在Form.ResizeBegin上实现一个事件处理程序,在其中您将从控件中删除OnPaint处理程序。

然后你只需要在Form.ResizeEnd中恢复它。

答案 1 :(得分:0)

在类似情况下对我最有效的是this SO帖子中描述的解决方案。

简而言之,建议将以下导入添加到您的控件中:

[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( Control parent )
{
    SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
}

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

然后你要做的就是在重新调整大小之前调用SuspendDrawing,然后调用ResumeDrawing

<强>更新

我个人更喜欢使用它作为扩展方法,因此它可用于我使用的所有控件,而无需复制代码或从基类继承......

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

答案 2 :(得分:0)

您必须获取ResizeBegin和ResizeEnd事件。

那里的代码应该如下:

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

        private void OnResizeBegin(object sender, EventArgs e)
        {
            Paint -= OnPaint;
        }