C#绘图双缓冲技术总结

来源:网络整理 责任编辑:栏目编辑 发表时间:2013-07-02 05:49 点击:

GDI+的双缓冲问题终于搞定了, 真是松了一口气!
一直以来的误区:.Net1.1 和 .Net 2.0 在处理控件双缓冲上是有区别的。
.Net 1.1 中,使用:this.SetStyle(ControlStyles.DoubleBuffer, true);
.Net 2.0中,使用:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
怪不说老是提示参数无效,一直也不知道是这个问题,呵呵
 
要知道,图元无闪烁的实现和图元的绘制方法没有多少关系,只是绘制方法可以控制图元的刷新区域,使双缓冲性能更优!
 
导致画面闪烁的关键原因分析:
      一、绘制窗口由于大小位置状态改变进行重绘操作时
     绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面重新刷新一次以维持窗口正常显示。刷新过程中会导致所有图元重新绘制,而各个图元的重绘操作并不会导致Paint事件发生,因此窗口的每一次刷新只会调用Paint事件一次。窗口刷新一次的过程中,每一个图元的重绘都会立即显示到窗口,因此整个窗口中,只要是图元所在的位置,都在刷新,而刷新的时间是有差别的,闪烁现象自然会出现。
     所以说,此时导致窗口闪烁现象的关键因素并不在于Paint事件调用的次数多少,而在于各个图元的重绘。
     根据以上分析可知,当图元数目不多时,窗口刷新的位置也不多,窗口闪烁效果并不严重;当图元数目较多时,绘图窗口进行重绘的图元数量增加,绘图窗口每一次刷新都会导致较多的图元重新绘制,窗口的较多位置都在刷新,闪烁现象自然就会越来越严重。特别是图元比较大绘制时间比较长时,闪烁问题会更加严重,因为时间延迟会更长。
     解决上述问题的关键在于:窗口刷新一次的过程中,让所有图元同时显示到窗口。
      二、进行鼠标跟踪绘制操作或者对图元进行变形操作时
     当进行鼠标跟踪绘制操作或者对图元进行变形操作时,Paint事件会频繁发生,这会使窗口的刷新次数大大增加。虽然窗口刷新一次的过程中所有图元同时显示到窗口,但也会有时间延迟,因为此时窗口刷新的时间间隔远小于图元每一次显示到窗口所用的时间。因此闪烁现象并不能完全消除!
     所以说,此时导致窗口闪烁现象的关键因素在于Paint事件发生的次数多少。
     解决此问题的关键在于:设置窗体或控件的几个关键属性。
 
 

--------------------------------------------------------------------------------

 下面来介绍解决办法的具体细节:
--------------------------------------------------------------------------------

解决双缓冲的关键技术:
1、设置显示图元控件的几个属性:  必须要设置,否则效果不是很明显!
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |   
                    ControlStyles.ResizeRedraw |
                    ControlStyles.AllPaintingInWmPaint, true);
2、窗口刷新一次的过程中,让所有图元同时显示到窗口。
    可以通过以下几种方式实现,这几种方式都涉及到Graphics对象的创建方式。
Graphics对象的创建方式:
 a、在内存上创建一块和显示控件相同大小的画布,在这块画布上创建Graphics对象。
     接着所有的图元都在这块画布上绘制,绘制完成以后再使用该画布覆盖显示控件的背景,从而达到“显示一次仅刷新一次”的效果!
  实现代码(在OnPaint方法中):
  Rectangle rect = e.ClipRectangle;
  Bitmap bufferimage = new Bitmap(this.Width, this.Height);
     Graphics g = Graphics.FromImage(bufferimage);
  g.Clear(this.BackColor);
     g.SmoothingMode = SmoothingMode.HighQuality; //高质量
     g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移质量
  foreach (IShape drawobject in doc.drawObjectList)
      {
                 if (rect.IntersectsWith(drawobject.Rect))
                {
                    drawobject.Draw(g);
&nb

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • 用C#制作屏幕捕获程序
    • .NET程序员项目开发必知必会—Dev环境中的集成测试用例执行时上
    • 遍历ArrayList易犯错误
    • C#对XML操作:一个处理XML文件的类(1)
    • .NET简谈反射(动态调用)
    • 使用C#编写LED样式时钟控件
    • DataList嵌套问题 如何删除内层子DataList的记录
    • 怎样用C#实现完整文档打印功能
    • .NET简谈自定义事务资源管理器
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1