C#繪圖雙緩衝技術總結

來源:互聯網
上載者:User
GDI+的雙緩衝問題終於搞定了, 真是鬆了一口氣!一直以來的誤區:.net1.1 和 .net 2.0 在處理控制項雙緩衝上是有區別的。.net 1.1 中,使用:this.SetStyle(ControlStyles.DoubleBuffer, true); .net 2.0中,使用:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);怪不說老是提示參數無效,一直也不知道是這個問題,呵呵 要知道,圖元無閃爍的實現和圖元的繪製方法沒有多少關係,只是繪製方法可以控製圖元的重新整理地區,使雙緩衝效能更優!  導致畫面閃爍的關鍵原因分析:       一、繪製視窗由於大小位置狀態改變進行重繪操作時     繪圖視窗內容或大小每改變一次,都要調用Paint事件進行重繪操作,該操作會使畫面重新重新整理一次以維持視窗正常顯示。重新整理過程中會導致所有圖元重新繪製,而各個圖元的重繪操作並不會導致Paint事件發生,因此視窗的每一次重新整理只會調用Paint事件一次。視窗重新整理一次的過程中,每一個圖元的重繪都會立即顯示到視窗,因此整個視窗中,只要是圖元所在的位置,都在重新整理,而重新整理的時間是有差別的,閃爍現象自然會出現。      所以說,此時導致視窗閃爍現象的關鍵因素並不在於Paint事件調用的次數多少,而在於各個圖元的重繪。     根據以上分析可知,當圖元數目不多時,視窗重新整理的位置也不多,視窗閃爍效果並不嚴重;當圖元數目較多時,繪圖視窗進行重繪的圖元數量增加,繪圖視窗每一次重新整理都會導致較多的圖元重新繪製,視窗的較多位置都在重新整理,閃爍現象自然就會越來越嚴重。特別是圖元比較大繪製時間比較長時,閃爍問題會更加嚴重,因為時間延遲會更長。     解決上述問題的關鍵在於: 視窗重新整理一次的過程中,讓所有圖元同時顯示到視窗。       二、進行滑鼠跟蹤繪製操作或者對圖元進行變形操作時     當進行滑鼠跟蹤繪製操作或者對圖元進行變形操作時,Paint事件會頻繁發生,這會使視窗的重新整理次數大大增加。雖然視窗重新整理一次的過程中所有圖元同時顯示到視窗,但也會有時間延遲,因為此時視窗重新整理的時間間隔遠小於圖元每一次顯示到視窗所用的時間。因此閃爍現象並不能完全消除!     所以說,此時導致視窗閃爍現象的關鍵因素在於Paint事件發生的次數多少。     解決此問題的關鍵在於: 設定表單或控制項的幾個關鍵屬性。     下面來介紹解決辦法的具體細節: 解決雙緩衝的關鍵技術:1、設定顯示圖元控制項的幾個屬性:  必須要設定,否則效果不是很明顯!this.SetStyle(ControlStyles.OptimizedDoubleBuffer |                       ControlStyles.ResizeRedraw |                     ControlStyles.AllPaintingInWmPaint, true);2、視窗重新整理一次的過程中,讓所有圖元同時顯示到視窗。    可以通過以下幾種方式實現,這幾種方式都涉及到Graphics對象的建立方式。 Graphics對象的建立方式: a、在記憶體上建立一塊和顯示控制項相同大小的畫布,在這塊畫布上建立Graphics對象。     接著所有的圖元都在這塊畫布上繪製,繪製完成以後再使用該畫布覆蓋顯示控制項的背景,從而達到“顯示一次僅重新整理一次”的效果!  實現代碼(在OnPaint方法中):  Rectangle rect = e.ClipRectangle;  Bitmap bufferimage = new Bitmap(this.Width, this.Height);
     Graphics g = Graphics.FromImage(bufferimage);  g.Clear(this.BackColor);
     g.SmoothingMode = SmoothingMode.HighQuality; //高品質
     g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素位移品質  foreach (IShape drawobject in doc.drawObjectList)
      {                 if (rect.IntersectsWith(drawobject.Rect))
                {
                    drawobject.Draw(g);
                    if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected
                        && this.CurrentOperator == Enum.Operator.Transfrom)//僅當編輯節點操作時顯示圖元熱點
                    {
                        drawobject.DrawTracker(g);
                    }
                }

       }    using (Graphics tg = e.Graphics)
            {
                tg.DrawImage(bufferimage, 0, 0);  //把畫布貼到畫面上
            } b、直接在記憶體上建立Graphics對象:     Rectangle rect = e.ClipRectangle;     BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;
            BufferedGraphics myBuffer = currentContext.Allocate(e.Graphics, e.ClipRectangle);
            Graphics g = myBuffer.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
            g.Clear(this.BackColor);
            foreach (IShape drawobject in doc.drawObjectList)
            {
                if (rect.IntersectsWith(drawobject.Rect))
                {
                    drawobject.Draw(g);
                    if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected
                        && this.CurrentOperator == Enum.Operator.Transfrom)//僅當編輯節點操作時顯示圖元熱點
                    {
                        drawobject.DrawTracker(g);
                    }
                }
            }    myBuffer.Render(e.Graphics);
           g.Dispose();
           myBuffer.Dispose();//釋放資源至此,雙緩衝問題解決,兩種方式的實現效果都一樣,但最後一種方式的佔有的記憶體很少,不會出現記憶體泄露!參考資料:1、http://dev.yesky.com/msdn/148/2596148.shtml2、GDI+圖形程式設計   [美]Mahesh Chand 著       電子工業出版社3、C#進階編程(第三版)

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。