使用Double-Buffer來實現無閃爍動態折線圖

由於這片例子是借鑑於別人的基礎上寫的,我只是在上面加上了動態畫折線圖這部分,因爲原理很簡單,當時也只是爲了給網友一個例子。沒想到,還有很多人做這個,那麼我就把這部分的代碼貼出來,分享給大家。

 

大致代碼如下:

//--------------------------- A Demo using Double-Buffer in GDI+ -------------------------------

//----------------------------------------------------------------------------------------------

//---File:          frmGraphView

//---Description:   A demo using double-buffer in GDI+

//---Author:        Knight

//---Date:          Jul.3, 2006

//----------------------------------------------------------------------------------------------

//---------------------------{A Demo using Double-Buffer in GDI+}-------------------------------

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

 

namespace GraphView

{

    using System.Threading;

 

    /// <summary>

    /// Summary description for Form1.

    /// </summary>

    public class frmGraphView : System.Windows.Forms.Form

    {

        private System.Windows.Forms.PictureBox picGraph;

        /// <summary>

        /// Required designer variable.

        /// </summary>

        private System.ComponentModel.Container components = null;

 

        private clsDrawThread myDrawThread = null;

        private Thread thdDraw = null;

        public frmGraphView()

        {

            //

            // Required for Windows Form Designer support

            //

            InitializeComponent();

 

            //

            // TODO: Add any constructor code after InitializeComponent call

            //

        }

 

        /// <summary>

        /// Clean up any resources being used.

        /// </summary>

        protected override void Dispose( bool disposing )

        {

            if( disposing )

            {

                if (components != null)

                {

                    components.Dispose();

                }

            }

            base.Dispose( disposing );

        }

 

        #region Windows Form Designer generated code

        /// <summary>

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary>

        private void InitializeComponent()

        {

            this.picGraph = new System.Windows.Forms.PictureBox();

            this.SuspendLayout();

            //

            // picGraph

            //

            this.picGraph.BackColor = System.Drawing.Color.Black;

            this.picGraph.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;

            this.picGraph.Dock = System.Windows.Forms.DockStyle.Fill;

            this.picGraph.Location = new System.Drawing.Point(0, 0);

            this.picGraph.Name = "picGraph";

            this.picGraph.Size = new System.Drawing.Size(498, 375);

            this.picGraph.TabIndex = 0;

            this.picGraph.TabStop = false;

            this.picGraph.Paint += new System.Windows.Forms.PaintEventHandler(this.picGraph_Paint);

            //

            // frmGraphView

            //

            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

            this.ClientSize = new System.Drawing.Size(498, 375);

            this.Controls.Add(this.picGraph);

            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;

            this.MaximizeBox = false;

            this.Name = "frmGraphView";

            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;

            this.Text = "Graph View";

            this.Closing += new System.ComponentModel.CancelEventHandler(this.frmGraphView_Closing);

            this.Load += new System.EventHandler(this.frmGraphView_Load);

            this.ResumeLayout(false);

 

        }

        #endregion

 

        /// <summary>

        /// The main entry point for the application.

        /// </summary>

        [STAThread]

        static void Main()

        {

            Application.Run(new frmGraphView());

        }

 

        private void frmGraphView_Load(object sender, System.EventArgs e)

        {

            // Create thread class

            myDrawThread = new clsDrawThread( this, new DrawHandler( RefreshPictureBox ),

                picGraph.ClientSize.Width, picGraph.ClientSize.Height );

 

            // Start sub thread to draw

            thdDraw = new Thread( new ThreadStart( myDrawThread.DrawGraph ) );

            thdDraw.Start();

        }

 

 

        private void RefreshPictureBox()

        {

            // Refresh picturebox

            picGraph.Invalidate( picGraph.Region );

        }

 

        private void frmGraphView_Closing(object sender, System.ComponentModel.CancelEventArgs e)

        {

            // Close thread

            myDrawThread.IsStop = true;

            thdDraw.Join( 1 );

        }

 

        private void picGraph_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

        {

            // Draw image

            e.Graphics.DrawImage( myDrawThread.DrawImage,

                picGraph.ClientRectangle,

                picGraph.ClientRectangle,

                GraphicsUnit.Pixel );

        }

    }

 

    public delegate void DrawHandler();

    public class clsDrawThread

    {

        private Bitmap bitGraph = null;

        private bool blnStop = false;

        private int nStartY = -1;

        private int nEndY = -1;

        private Random ranPoint = null;

 

        private int nWidth = 0;

        private int nHeight = 0;

        private Form frmParent;

        private DrawHandler pHandler = null;

 

        /// <summary>

        /// Constructor

        /// </summary>

        /// <param name="pParent"></param>

        /// <param name="Handler"></param>

        /// <param name="Width"></param>

        /// <param name="Height"></param>

        public clsDrawThread( Form pParent, DrawHandler Handler, int Width, int Height )

        {

            // Init class member

            nWidth = Width;

            nHeight = Height;

 

            frmParent = pParent;//Parent form

            pHandler = Handler;//Call back delegate

 

            // Create double buffer

            bitGraph = new Bitmap( nWidth, nHeight );

 

            ranPoint = new Random( nHeight );//Create random

        }

 

        public bool IsStop

        {

            set{ blnStop = value;}

        }

 

        public Image DrawImage

        {

            get{ return bitGraph;}

        }

 

        /// <summary>

        /// Sub thread entry function

        /// </summary>

        public void DrawGraph()

        {

            while( !blnStop )

            {

                Thread.Sleep( 400 );

               

                if( blnStop ) break;

 

                //Redraw bitmap

                RedrawImage();

 

                //Refresh pictorebox

                try

                {

                    frmParent.Invoke( pHandler );

                }

                catch{ break;}

            }

        }

 

        /// <summary>

        /// Re-draw image

        /// </summary>

        private void RedrawImage()

        {

            const int CLIP_WIDTH = 10;

            Bitmap bitNew = new Bitmap( nWidth, nHeight );

            Graphics gImage = Graphics.FromImage( bitNew );

 

            // Use black color to fill the entire rectangle

            gImage.FillRectangle( new SolidBrush( Color.Black ),

                new Rectangle( new Point( 0, 0),

                new Size( nWidth, nHeight ) ) );

 

            // Copy image from source image

            gImage.DrawImage( bitGraph,

                new Rectangle( 0,0, nWidth - CLIP_WIDTH, nHeight ),

                new Rectangle( CLIP_WIDTH,0, nWidth - CLIP_WIDTH, nHeight ),

                GraphicsUnit.Pixel );

               

            // Draw new clip image

            if( nStartY < 0 )

                nStartY = ranPoint.Next() % nHeight;

            else

                nStartY = nEndY;

            nEndY = ranPoint.Next() % nHeight;

 

            // Draw new line

            gImage.DrawLine( new Pen( Color.Red, 1.5f ),

                new Point( nWidth - CLIP_WIDTH, nStartY ),

                new Point( nWidth - 1, nEndY ) );

 

            // Set new image and release old image

            Bitmap bitOld = bitGraph;

            bitGraph = bitNew;

            bitOld.Dispose();

        }

 

    }

}

      

       參考原文:

       http://www.codeproject.com/cs/media/flickerFreeDrawing.asp

 
發佈了87 篇原創文章 · 獲贊 9 · 訪問量 100萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章