天天看點

C#中在某些控件内實作雙緩沖繪圖的一些問題

自己在用到雙緩沖繪圖時候在網上搜尋了很多方法,有直接設定,有自己開辟記憶體方法。到現在為止,我的了解是,如果你要在一個新視窗中直接繪圖的話,可以用直接設定雙緩沖的方法來搞定。但如果你要在某個控件(以panel舉例)内部繪圖,其雙緩沖的設定方法最好是在記憶體當中開辟虛拟記憶體,在記憶體中繪制好後再在視窗當中顯示出來。道理是這個道理,思路大家都知道,但在實作的時候會遇到一些問題。我将自己的遇到一些問題分享出來,免得大家再走彎路。

先貼上一段代碼,建立一個窗體,裡面隻放進去一個控件panel1。在窗體畫圖事件裡面寫繪圖代碼。

private void Form1_Paint(object sender, PaintEventArgs e)
        {

            Bitmap bmp = new Bitmap(panel1.ClientRectangle.Width,panel1.ClientRectangle.Height);
            Graphics grid = Graphics.FromImage(bmp);
            int PX = panel1.Location.X;//panel1的X坐标
            int PY = panel1.Location.Y;//panel1的Y坐标          
            Graphics g1 = e.Graphics;
            Graphics g2 = this.CreateGraphics();
            Graphics g3 = e.Graphics;
            Graphics g4 = this.CreateGraphics();
            g1.DrawLine(new Pen(Color.FromArgb(0x00, 0x00, 0xff)), panel1.Location.X, panel1.Location.Y, 0, 0);//藍色的筆畫從窗體左上角到panel的左上角的線
            g2.DrawLine(new Pen(Color.FromArgb(0xff, 0x00, 0x00)), 50, 50, 100, 100);//畫一段紅線           
            grid.DrawLine(new Pen(Color.FromArgb(0x00, 0xff, 0x00)), 0, 0, panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);//在記憶體中用綠色的筆畫panel的對角線
            g3.DrawImage(bmp,PX, PY);在窗體中顯示出來
        }
           

這段代碼是可以實作的,結果如下所示

C#中在某些控件内實作雙緩沖繪圖的一些問題

如果對上面的圖做一修改,則結果會發生改變,改動後代碼如下,

private void Form1_Paint(object sender, PaintEventArgs e)
        {

            Bitmap bmp = new Bitmap(panel1.ClientRectangle.Width,panel1.ClientRectangle.Height);
            Graphics grid = Graphics.FromImage(bmp);
            int PX = panel1.Location.X;
            int PY = panel1.Location.Y;          
            Graphics g1 = e.Graphics;
            Graphics g2 = this.CreateGraphics();
            Graphics g3 = e.Graphics;
            Graphics g4 = this.CreateGraphics();
            g1.DrawLine(new Pen(Color.FromArgb(0x00, 0x00, 0xff)), panel1.Location.X, panel1.Location.Y, 0, 0);//藍色的筆畫從窗體左上角到panel的左上角的線
            g2.DrawLine(new Pen(Color.FromArgb(0xff, 0x00, 0x00)), 50, 50, 100, 100);//畫一段紅線           
            grid.DrawLine(new Pen(Color.FromArgb(0x00, 0xff, 0x00)), 0, 0, panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);//在記憶體中用綠色的筆畫panel的對角線
            g4.DrawImage(bmp, PX, PY);在窗體中顯示出來
        }
           

把最後一句的Graphics對象變為g4,結果如下:

C#中在某些控件内實作雙緩沖繪圖的一些問題

雙緩沖功能并未實作,這說明Graphics對象的建立方式也會影響到結果的實作。

再對代碼修改,将

Graphics g4 = this.CreateGraphics();改為
           
Graphics g4 = panel1.CreateGraphics();
           

再來觀察結果

C#中在某些控件内實作雙緩沖繪圖的一些問題

綠色的線顯示了一段,但并沒有按我們的預期顯示在panel1内部的=的對角線上,這說明雙緩沖功能實作了,但線的坐标不對,要更改坐标。

private void Form1_Paint(object sender, PaintEventArgs e)
        {

            Bitmap bmp = new Bitmap(panel1.ClientRectangle.Width,panel1.ClientRectangle.Height);
            Graphics grid = Graphics.FromImage(bmp);
            int PX = panel1.Location.X;
            int PY = panel1.Location.Y;          
            Graphics g1 = e.Graphics;
            Graphics g2 = this.CreateGraphics();
            Graphics g3 = e.Graphics;
            Graphics g4 = panel1.CreateGraphics();
            g1.DrawLine(new Pen(Color.FromArgb(0x00, 0x00, 0xff)), panel1.Location.X, panel1.Location.Y, 0, 0);//藍色的筆畫從窗體左上角到panel的左上角的線
            g2.DrawLine(new Pen(Color.FromArgb(0xff, 0x00, 0x00)), 50, 50, 100, 100);//畫一段紅線           
            grid.DrawLine(new Pen(Color.FromArgb(0x00, 0xff, 0x00)), 0, 0, panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);//在記憶體中用綠色的筆畫panel的對角線
            g4.DrawImage(bmp, 0, 0);在窗體中顯示出來
        }
           
C#中在某些控件内實作雙緩沖繪圖的一些問題

總結,容器内部實作雙緩沖的關鍵地方有兩個,一個是建立Graphics的方法,一個是DrawLine方法和DrawImage方法的坐标選擇要比對。其中建立圖形對象的方法會關聯影響到DrawLine方法和DrawImage方法的的坐标選擇,其中有一個通常要注意的是,在C#容器内部的線條或者點坐标值通常都是以該容器的左上角為原點的參考值,已經不再以窗體的左上角為原點,其實我們隻要厘清楚建立的圖形對象是在窗體内還是容器内,坐标值就好選擇了。另外,使用C#自帶的雙緩沖類BufferedGraphics實作雙緩沖還沒搞明白,不亂說了,以免誤導像我一樣的小白。