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

Posted on 2014-04-24 20:50  我编程我快乐  阅读(3743)  评论(9编辑  收藏  举报

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

  好的废话不多说了。为了改善游戏的运行效果,把原来控件的方式全都改成绘图的方式,即用C#中DrawImage()方法进行绘图,可以改善游戏运行慢的问题。然后开始测试DrawImage()方法的使用。图片倒是出来了,而且也可以移动了,但是致命的问题出现了。就是图片在移动的时候(实质上是图片的重绘)出现了闪屏的问题。

  为了解决这个问题,在网上找了很多资料,参考了很多书,能解决闪屏问题的解决方法就是利用C#中提供的一种双缓冲技术。

  但是网上或书上没有一个能够通过一个简单的例子直接让我明白如何使用双缓冲技术的。花了好几个小时的时间,最终还是自己琢磨出来了。分享给大家。同时也把我的这个简单的测试小例子供大家学习,如何快速应用双缓冲技术解决问题。

1.首先建立一个工程,在窗口中添加一个按钮。当点击这个按钮式就开始显示图片的移动。

2.双缓冲我采用的方法是:

  先建立一个虚拟画布,并在Form1()的方法中加入

     SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint,
true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);

  

private Graphics g;
        Bitmap bmp = new Bitmap(600, 600);//这里是创建一个画布
        Graphics g1;
        private int x=0;
        public Form1()
        {
            
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);
            g1 = Graphics.FromImage(bmp);//这里是在画布上建立一个Graphics对象,为了在画布上画图形
            
            
            InitializeComponent();
            
        }

 

然后通过单击按钮事件,在画布上显示图片并将画布显示到窗口

//button1的单击处理事件
        private void button1_Click(object sender, EventArgs e)
        {
            
            //g1.DrawEllipse(new Pen(System.Drawing.Color.Red), 10, 10, 100, 100);
            g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//这是在画布上绘制图形
           this.CreateGraphics().DrawImage(bmp, 0, 0);//这句是将图形显示到窗口上
            timer1.Enabled = true;
           // g.Dispose();
        }

最后在通过timer控件使图片不断移动,代码如下:

private void timer1_Tick(object sender, EventArgs e)
        {
            
            x++;//这是一个全局变量,用来改变图片的横坐标
            g1.Clear(Form1.DefaultBackColor);//这是清除画布中前一个图片
            g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//重绘新的图片,此时位置较之前的地方横坐标加1了
            this.CreateGraphics().DrawImage(bmp, 0, 0);//再次显示到窗口上,没有闪动
        }

如没有加SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);代码,将会出现屏幕闪动。

下面给出完整的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ttest
{
    public partial class Form1 : Form
    {
        private Graphics g;
        Bitmap bmp = new Bitmap(600, 600);//这里是创建一个画布
        Graphics g1;
        private int x=0;
        public Form1()
        {
            
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);
            g1 = Graphics.FromImage(bmp);
            
            InitializeComponent();
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
           // g1 = this.CreateGraphics();
            
        }
        //button1的单击处理事件
        private void button1_Click(object sender, EventArgs e)
        {
            
            //g1.DrawEllipse(new Pen(System.Drawing.Color.Red), 10, 10, 100, 100);
            g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//这是在画布上绘制图形
           this.CreateGraphics().DrawImage(bmp, 0, 0);//这句是将图形显示到窗口上
            timer1.Enabled = true;
           // g.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            
            x++;//这是一个全局变量,用来改变图片的横坐标
            g1.Clear(Form1.DefaultBackColor);//这是清除画布中前一个图片
            g1.DrawImage(Image.FromFile("E:/down.png"), x, 10);//重绘新的图片,此时位置较之前的地方横坐标加1了
            this.CreateGraphics().DrawImage(bmp, 0, 0);//再次显示到窗口上,没有闪动
        }

        

       
    }
}

弄了一下午,终于解决闪屏问题了。。。

Copyright © 2024 我编程我快乐
Powered by .NET 9.0 on Kubernetes