解决双缓冲的关键技术:

1、设置显示图元控件的几个属性:必须要设置,否则效果不是很明显!
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);

2、窗口刷新一次的过程中,让所有图元同时显示到窗口。可以通过以下几种方式实现,这几种方式都涉及到Graphics对象的创建方式。

a、在内存上创建一块和显示控件相同大小的画布,在这块画布上创建Graphics对象。接着所有的图元都在这块画布上绘制,绘制完成以后再使用该画布覆盖显示控件的背景,从而达到“显示一次仅刷新一次”的效果!实现代码(在OnPaint方法中):

  1. Rectangle rect = e.ClipRectangle;
  2. Bitmap bufferimage = new Bitmap(this.Width, this.Height);
  3. Graphics g = Graphics.FromImage(bufferimage);
  4. g.Clear(this.BackColor);
  5. g.SmoothingMode = SmoothingMode.HighQuality; //高质量
  6. g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
  7. foreach (IShape drawobject in doc.drawObjectList)
  8. {
  9.     if (rect.IntersectsWith(drawobject.Rect))
  10.     {
  11.         drawobject.Draw(g);
  12.         if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected && this.CurrentOperator == Enum.Operator.Transfrom) //仅当编辑节点操作时显示图元热点
  13.         {
  14.                 drawobject.DrawTracker(g);
  15.         }
  16.     }
  17. }
  18. using (Graphics tg = e.Graphics)
  19.     {
  20.         tg.DrawImage(bufferimage, 0, 0);  //把画布贴到画面上
  21.     }

b、直接在内存上创建Graphics对象:

  1. Rectangle rect = e.ClipRectangle;
  2. BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;
  3. BufferedGraphics myBuffer = currentContext.Allocate(e.Graphics, e.ClipRectangle);
  4. Graphics g = myBuffer.Graphics;
  5. g.SmoothingMode = SmoothingMode.HighQuality;
  6. g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
  7. g.Clear(this.BackColor);
  8. foreach (IShape drawobject in doc.drawObjectList)
  9. {
  10.     if (rect.IntersectsWith(drawobject.Rect))
  11.     {
  12.         drawobject.Draw(g);
  13.         if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected && this.CurrentOperator == Enum.Operator.Transfrom)//仅当编辑节点操作时显示图元热点
  14.         {
  15.             drawobject.DrawTracker(g);
  16.         }
  17.     }
  18. }
  19. myBuffer.Render(e.Graphics);
  20. g.Dispose();
  21. myBuffer.Dispose();//释放资源

至此,双缓冲问题解决,两种方式的实现效果都一样,但最后一种方式的占有的内存很少,不会出现内存泄露!