前言
進入.NET時代,Windows的繪圖技術也從GDI升級到了GDI+,從名字就能知道GDI+是對以前傳統GDI繪圖技術的一次升級,不過在微軟幾乎把所有的新技術都冠之.NET的情況下,GDI+竟然不叫做GDI.NET,還真讓我感到有點意外了。
GDI+在一種與設備無關的環境下提供了一套統一的繪圖編程模型,極大的提高了Windows繪圖編程的方便性,我們再也不用創建什么各種各樣復雜的設備環境了,說實話,我現在想起來都頭疼。 題歸正傳,關于如何進行GDI+的基本編程,我不能過多的加以描述,假如有對此概念還不太清楚的朋友,建議先去了解一下相關的資料,我們在這里主要討論的是一種提高繪圖效率(主要是動畫效率)的雙緩沖技術在GDI+中的應用和實現。 實現目的 為了能清楚的對比應用雙緩沖技術前后的效果,我編寫了一段程序來進行測試。首先,我創建了一個普通的Windows application,在主Form中,我放置了一個定時器:timer1,然后將它的Interval屬性設置為10,然后在Form上放置兩個按紐,分別用來控制定時器的開啟和關閉,最后,我還放置了一個label控件,用來顯示繪圖的幀數。 測試程序 在timer1的timer1_Tick事件中,我寫下了如下的代碼(其中flag是一個bool型標志變量):DateTime t1 = DateTime.Now;Graphics g = this.CreateGraphics();if(flag){ brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), new PointF(700.0f, 300.0f), Color.Red, Color.Blue); flag = false;}else{ brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), new PointF(700.0f, 300.0f), Color.Blue, Color.Red); flag = true;}for(int j = 0; j < 60; j ++){ for(int i = 0; i < 60; i++) { g.FillEll
ipse(brush, i * 10, j * 10, 10, 10); }}DateTime t2 = DateTime.Now;TimeSpan sp = t2 - t1;float per = 1000 / sp.Milliseconds;this.label1.Text = "速度:" + per.ToString() + "幀/秒";
運行后,我點擊“開始”按紐,效果如下圖所示:
應用雙緩沖以前的效果圖(幀數:5幀/秒) 正如大家所看到的,我在程序中使用循環畫了幾百個圓形,然后在每次的定時器脈沖事件中使用不同方向的線性漸變來對它們進行填充,形成了一個動畫效果。不過不幸的是,程序運行起來閃爍很嚴重,幾乎每次刷新的時候都可以看到一條很明顯的掃描線從上慢慢的刷到下來完成整幅圖形的刷新動作。假如你不是要模擬老式雷達的區域掃描的話,這種速度不會滿足你的要求。###adv### 改進代碼 下面是我改進以后的代碼:DateTime t1 = DateTime.Now;Bitmap bmp = new Bitmap(600, 600);Graphics g = Graphics.FromImage(bmp);if(flag){ brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), new PointF(700.0f, 300.0f), Color.Red, Color.Blue); flag = false;}else{ brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), new PointF(700.0f, 300.0f), Color.Blue, Color.Red); flag = true;}for(int j = 0; j < 60; j ++){ for(int i = 0; i < 60; i++) { g.FillEllipse(brush, i * 10, j * 10, 10, 10); }}this.CreateGraphics().DrawImage(bmp, 0, 0);DateTime t2 = DateTime.Now;TimeSpan sp = t2 - t1;float per = 1000 / sp.Milliseconds;this.label1.Text = "速度:" + per.ToString() + "幀/秒";
運行后,我點擊“開始”按紐,效果如下圖所示:
應用雙緩沖以后的效果圖(幀數:9幀/秒)
經過改進后,畫面刷新速度大大加快,絕對看不到任何的“掃描線”,幀數也從5幀一下就提高到了9幀,幾乎是兩倍于前的速度。這究竟是什么原因呢?讓我來講述其中的道理。 因為圓是要一個一個畫上去,所以每畫一個圓,系統就要做一次圖形的繪制操作,圖形的重繪是很占用資源的,當需要重繪的圖形數量很多的時候,所造成的系統開銷就非凡大,造成我們看到的那種刷新緩慢的情況。那么如何來解決這個問題呢? 答案就是雙緩沖,何謂“雙緩沖”?它的基本原理就是:先在內存中開辟一塊虛擬畫布,然后將所有需要畫的圖形先畫在這塊“虛擬畫布”上,最后在一次性將整塊畫布畫到真正的窗體上。因為所有的單個圖形的繪制都不是真正的調用顯示系統來“畫”,所以不會占用顯示系統的開銷,極大的提高的繪圖效率。 實現雙緩沖的具體步驟 我再來具體解釋一下剛才實現雙緩沖的具體步驟: 1、在內存中建立一塊“虛擬畫布”:Bitmap bmp = new Bitmap(600, 600); 2、獲取這塊內存畫布的Graphics引用:Graphics g = Graphics.FromImage(bmp); 3、在這塊內存畫布上繪圖:g.FillEllipse(brush, i * 10, j * 10, 10, 10); 4、將內存畫布畫到窗口中this.CreateGraphics().DrawImage(bmp, 0, 0); 總結 怎么樣?是不是很簡單?但是正是這個簡單的操作大大提高了繪圖效率,所以假如你需要進行GDI+圖形編程,雙緩沖技術一定要把握,非凡是在進行大量圖形繪制刷新的情況下要盡量采用。