在 绘图 或 绘 制控件 过 程中最 让 人郁 闷 的便是 复杂绘 制的 闪烁问题 。 如果您 为该问题 所困 扰 ,那 么 您 应该 注意以下几点: 1 , 使用 缓 冲: 比如要向 Graphics 对 象 g 上 绘 制 图 形, 你可以在内存中使用一 张图 片作 为缓 冲,先将 图 形 绘 制到 该图 片上, 绘 制完成后再将 该图 片 绘 制到 g 上。 Bitmapbuffer= new Bitmap( this . Width , this . Height); using (GraphicsbufferGrfx=Graphics . FromImage(buffer)) { // 绘 制到bufferGrfx 上 } // 把缓冲图片绘制到 g 上 RectanglesrcRect= this . bounds; RectangledestRect=srcRect; g . DrawImage(buffer , destRect , srcRect , GraphicsUnit . Pixel); 不用担心两次 绘 制会 带 来效率上的 损 失, 其速度与直接 绘 制到 g 上几乎一 样 快。 2 , base . OnPaint(e); 如果所有的 绘 制操作都由自己来完成,那 么 在覆盖 OnPaint 方法 时 , 请 不要 使用 base . OnPaint(e); 3 , e . ClipRectangle 运用剪 辑 区域, 这 很重要 , 很 简单 地,比如 图 形区域只有很小一个部分需要更新你就没有必要更新全部 图 形区域。 具体 说 来就是,只有那些和剪 辑 区域相交 ( 或被剪 辑 区域包含 ) 的区域才需要 绘 制。 注意这里是e.ClipRectangle而不是g.Clip,g.Clip表示的是该画布的绘图区域,其和e.ClipRectangle(本次描画的剪辑区域)没有本质联系。 // 假 设 Block 对 象是程序的最小 绘 制 单 元 foreach (Blockbk in this . Blocks) { if ( e . ClipRectangle . IntersectsWith(bk . Bounds)) { //drawbk; } } 4 , Refrush() , Invalidate() , Update() 不要 轻 易使用Refrush 来刷新 图 形。 在刷新之前, 请 先确定要刷新的区域,如果要刷新的区域只是 图 形区域的一部分,您 应该 使用Invalidate() 来使 该 区域无效 ,然后使用Update 来更新 这 个无效区域便可。 5 , SetStyle(); 其 实 在以上几点之前, 应该 在控件的构造器 ( 或其他初始化方法 ) 中 设 置控件 样 式: This . SetStyle(ControlStyles . OptimizedDoubleBuffer , true ); this . SetStyle(ControlStyles . AllPaintingInWmPaint , true ); 这 里的 ControlStyles 有好几个枚 举 ,具体 设 置那些 值 ,以及它 们 之 间 的相互 关 系, 请 参考 MSDN 说 明文档。 6 , DoubleBuffered 有好几 种标 准控件是内置双 缓 冲的,比如Form , PictureBox 等, 您可以将它 们 的DoubleBuffered 设 置 为 true 。 来减少 闪烁 。 ( 当然不要寄希望于 仅仅设 置 该 属性便万事大吉了, 不然以上 5 点不是白 说 了 )