Fork me on GitHub

C#中利用双缓冲技术解决绘图闪屏问题

转载自:http://www.2cto.com/kf/201404/295500.html

 

  这段时间在做一个小型游戏,在界面显示的时候用到了一些图形。一开始涉及到的图形全都用控件的背景图片代替了。这样游戏运行的时候存在的一个很大的问题是游戏运行很慢。小组成员费尽周折,即将放弃,每一个成员都愁眉苦脸。我这心里也挺心酸的。。。

 
  好的废话不多说了。为了改善游戏的运行效果,把原来控件的方式全都改成绘图的方式,即用C#中DrawImage()方法进行绘图,可以改善游戏运行慢的问题。然后开始测试DrawImage()方法的使用。图片倒是出来了,而且也可以移动了,但是致命的问题出现了。就是图片在移动的时候(实质上是图片的重绘)出现了闪屏的问题。
 
  为了解决这个问题,在网上找了很多资料,参考了很多书,能解决闪屏问题的解决方法就是利用C#中提供的一种双缓冲技术。
 
  但是网上或书上没有一个能够通过一个简单的例子直接让我明白如何使用双缓冲技术的。花了好几个小时的时间,最终还是自己琢磨出来了。分享给大家。同时也把我的这个简单的测试小例子供大家学习,如何快速应用双缓冲技术解决问题。
 
1.首先建立一个工程,在窗口中添加一个按钮。当点击这个按钮式就开始显示图片的移动。
 
2.双缓冲我采用的方法是:
 
  先建立一个虚拟画布,并在Form1()的方法中加入
     SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);
 
复制代码
 1 private Graphics g;
 2 
 3         Bitmap bmp = new Bitmap(600, 600);//这里是创建一个画布
 4 
 5         Graphics g1;
 6 
 7         private int x=0;
 8 
 9         public Form1()
10 
11         {
12             SetStyle(ControlStyles.UserPaint, true);
13 
14             SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
15 
16             SetStyle(ControlStyles.DoubleBuffer, true);
17 
18             g1 = Graphics.FromImage(bmp);//这里是在画布上建立一个Graphics对,为了在画布上画图形
19 
20             InitializeComponent();
21         }
复制代码

 

然后通过单击按钮事件,在画布上显示图片并将画布显示到窗口
 
复制代码
 1 //button1的单击处理事件
 2 
 3 private void button1_Click(object sender, EventArgs e)
 4 
 5 {
 6 
 7    //g1.DrawEllipse(new Pen(System.Drawing.Color.Red), 10, 10, 100, 100);
 8 
 9    g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//这是在画布上绘制图形
10 
11    this.CreateGraphics().DrawImage(bmp, 0, 0);//这句是将图形显示到窗口上
12 
13    timer1.Enabled = true;
14 
15   // g.Dispose();
16 
17 }
复制代码

 

最后在通过timer控件使图片不断移动,代码如下:
 
复制代码
 1 private void timer1_Tick(object sender, EventArgs e)
 2 
 3 {
 4 
 5   x++;//这是一个全局变量,用来改变图片的横坐标
 6 
 7   g1.Clear(Form1.DefaultBackColor);//这是清除画布中前一个图片
 8 
 9   g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//重绘新的图片,此时位置较之前的地方横坐标加1了
10 
11   this.CreateGraphics().DrawImage(bmp, 0, 0);//再次显示到窗口上,没有闪动
12 
13 }
复制代码

 

 
下面给出完整的代码:
 
复制代码
  1 using System;
  2 
  3 using System.Collections.Generic;
  4 
  5 using System.ComponentModel;
  6 
  7 using System.Data;
  8 
  9 using System.Drawing;
 10 
 11 using System.Linq;
 12 
 13 using System.Text;
 14 
 15 using System.Windows.Forms;
 16 
 17  
 18 
 19 namespace ttest
 20 
 21 {
 22 
 23     public partial class Form1 : Form
 24 
 25     {
 26 
 27         private Graphics g;
 28 
 29         Bitmap bmp = new Bitmap(600, 600);//这里是创建一个画布
 30 
 31         Graphics g1;
 32 
 33         private int x=0;
 34 
 35         public Form1()
 36 
 37         {
 38 
 39             
 40 
 41             SetStyle(ControlStyles.UserPaint, true);
 42 
 43             SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
 44 
 45             SetStyle(ControlStyles.DoubleBuffer, true);
 46 
 47             g1 = Graphics.FromImage(bmp);
 48 
 49             
 50 
 51             InitializeComponent();
 52 
 53             
 54 
 55         }
 56 
 57  
 58 
 59         private void Form1_Load(object sender, EventArgs e)
 60 
 61         {
 62 
 63             
 64 
 65            // g1 = this.CreateGraphics();
 66 
 67             
 68 
 69         }
 70 
 71         //button1的单击处理事件
 72 
 73         private void button1_Click(object sender, EventArgs e)
 74 
 75         {
 76 
 77             
 78 
 79             //g1.DrawEllipse(new Pen(System.Drawing.Color.Red), 10, 10, 100, 100);
 80 
 81             g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//这是在画布上绘制图形
 82 
 83            this.CreateGraphics().DrawImage(bmp, 0, 0);//这句是将图形显示到窗口上
 84 
 85             timer1.Enabled = true;
 86 
 87            // g.Dispose();
 88 
 89         }
 90 
 91  
 92 
 93         private void timer1_Tick(object sender, EventArgs e)
 94 
 95         {
 96 
 97             
 98 
 99             x++;//这是一个全局变量,用来改变图片的横坐标
100 
101             g1.Clear(Form1.DefaultBackColor);//这是清除画布中前一个图片
102 
103             g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//重绘新的图片,此时位置较之前的地方横坐标加1了
104 
105             this.CreateGraphics().DrawImage(bmp, 0, 0);//再次显示到窗口上,没有闪动
106 
107         }
108 
109     }
  }
复制代码

 

 
posted @   江湖码客Mark  阅读(1774)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示