2007 年 8 月

C#绘图双缓冲技术

解决双缓冲的关键技术:

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();//释放资源

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

评论

被卖硬盘的骗了?

今晚身体不爽,回来吃过饭后就窝在床上迷糊,正在睡梦中,被手机短信闹起,以为是GF的,迷迷糊糊摸起来一看,是一初中同学,现复旦高才生(文科男),1说:买的120的移动硬盘怎么只有111?,我暗笑,木理他,结果过一小会又来了一条看上去惨兮兮的:好像是被骗了…

睡意被他彻底折腾没了。。。怒。。。@>@,就没正经回他,(*^__^*)

他:买的120的移动硬盘怎么只有111?
他:好像是被骗了…
我:就这样的。
他:什么就这样?
我:硬盘就这样。
他:不能差9G,太夸张了吧?
我:很正常,:)
他:…损失不小…
我:你要是前几年还在用软盘的时候发现1.44MB的软盘只能存1.38MB的东西,估计也会这么说,:-p
他:…

评论 (3)