Block "OnPaint" event while resizing
本文关键字:quot resizing while OnPaint Block event | 更新日期: 2023-09-27 17:58:37
我正在从缓冲区绘制控件。我的绘画代码是:
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事件。。
谢谢!=)
在类似情况下对我最有效的是这个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();
}
}
}
尝试在Form.ResizeBegin上实现一个事件处理程序,在该程序中,您将从控件中删除OnPaint处理程序。
然后您只需要在Form.ResizeEnd.中恢复它
您必须获得ResizeBegin和ResizeEnd事件。
里面的代码应该看起来像:
private void OnResizeEnd(object sender, EventArgs e)
{
Paint += OnPaint;
}
private void OnResizeBegin(object sender, EventArgs e)
{
Paint -= OnPaint;
}