測試C#GDI+雙緩衝高效繪圖--BufferedGraphicsContext

龙骑科技發表於2024-05-28

奧斯卡好的b、

測試C#GDI+雙緩衝高效繪圖
```
        #region C#GDI+雙緩衝高效繪圖
        #region temp
        //Rectangle rectangle = e.ClipRectangle;//取出次窗體或者畫布的有效區的矩形區域
        //BufferedGraphicsContext GraphicsContext = BufferedGraphicsManager.Current;//獲取程式住緩衝區域的BufferedGraphicsContext(雙快取類,此類用於提供雙緩衝的功能)物件
        //BufferedGraphics myBuffer = GraphicsContext.Allocate(e.Graphics, e.ClipRectangle);//獲取緩衝區
        // Graphics g = myBuffer.Graphics;

        //指定在呈現期間畫素偏移的方式。
        //g.PixelOffsetMode = PixelOffsetMode.HighQuality;//高質量低速度呈現
        //指定是否將平滑處理(消除鋸齒)應用於直線、曲線和已填充區域的邊緣。
        //g.SmoothingMode = SmoothingMode.HighQuality;// 指定高質量、低速度呈現。
        //g.Clear(BackColor);//或者使用invalidate方法==有效區的擦除
        //Pen bluePen2 = new Pen(Color.Blue);
        //LineDrawRoutine(g, bluePen2);
        //myBuffer.Render(e.Graphics);  //將圖形緩衝區的內容寫入指定的 Graphics 物件。
        //g.Dispose();
        //myBuffer.Dispose();


        //其實在C#裡如果是在Form中繪圖的話直接把Form的DoubleBuffered = true就可以了(利用winfrom窗體的預設雙緩衝)
        //把所有的繪圖放在一個picturebox裡面繪製,
        //不要直接再在form裡面繪
        //SetStyle(ControlStyles.UserPaint, true);
        //SetStyle(ControlStyles.ResizeRedraw, true);
        //SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        //SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        //SetStyle(ControlStyles.Selectable, true);

        // 如果你在Form中繪圖的話,不論是不是採用的雙快取,都會看到圖片在更新的時候都會不斷地閃爍,解決方法就是在這個窗體的建構函式中增加以下三行程式碼:
        //請在建構函式里面底下加上如下幾行:
        //SetStyle(ControlStyles.UserPaint, true);
        //SetStyle(ControlStyles.AllPaintingInWmPaint, true);   //   禁止擦除背景.
        //SetStyle(ControlStyles.DoubleBuffer, true);   //   雙緩衝
        //引數說明:
        //UserPaint
        //如果為true,控制元件將自行繪製,而不是透過作業系統來繪製。此樣式僅適用於派生自 Control的類。
        //AllPaintingInWmPaint
        //如果為true,控制元件將忽略 WM_ERASEBKGND視窗訊息以減少閃爍。僅當UserPaint 位設定為true時,才應當應用該樣式。
        //DoubleBuffer
        //如果為true,則繪製在緩衝區中進行,完成後將結果輸出到螢幕上。雙重緩衝區可防止由控制元件重繪引起的閃爍。要完全啟用雙重緩衝,還必須將UserPaint和AllPaintingInWmPaint樣式位設定為   true。   
        #endregion


        #region MyRegion
        //在建構函式中加如下程式碼
        //程式碼一:
        //SetStyle(ControlStyles.UserPaint, true);
        //SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
        //SetStyle(ControlStyles.DoubleBuffer, true); // 雙緩衝
        //或程式碼二:
        //this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
        //this.UpdateStyles();
        #endregion

        #region MyRegion
        //.netframework提供了一個類BufferedGraphicsContext負責單獨分配和管理圖形緩衝區。每個應用程式域都有自己的預設 BufferedGraphicsContext 例項來管理此應用程式的所有預設雙緩衝。大多數情況下,每個應用程式只有一個應用程式域,所以每個應用程式通常只有一個預設 BufferedGraphicsContext。預設 BufferedGraphicsContext 例項由 BufferedGraphicsManager 類管理。透過管理BufferedGraphicsContext實現雙緩衝的步驟如下:
        //(1)獲得對 BufferedGraphicsContext 類的例項的引用。
        //(2)透過呼叫 BufferedGraphicsContext.Allocate 方法建立 BufferedGraphics 類的例項。
        //(3)透過設定 BufferedGraphics.Graphics 屬性將圖形繪製到圖形緩衝區。
        //(4)當完成所有圖形緩衝區中的繪製操作時,可呼叫 BufferedGraphics.Render 方法將緩衝區的內容呈現到與該緩衝區關聯的繪圖圖面或者指定的繪圖圖面。
        //(5)完成呈現圖形之後,對 BufferedGraphics 例項呼叫釋放系統資源的 Dispose 方法。
        //BufferedGraphicsContext current01 = BufferedGraphicsManager.Current; //(1)初始化BufferedGraphicsContext 類的新例項
        //BufferedGraphics bg01 = current01.Allocate(this.CreateGraphics(), this.DisplayRectangle); //(2) 使用指定的Graphics 的畫素格式,建立指定大小的圖形緩衝區。
        //Graphics g01 = bg.Graphics;//(3)透過設定 BufferedGraphics.Graphics 屬性將圖形繪製到圖形緩衝區
        ////隨機 寬400 高400
        //System.Random rnd = new Random();

        //int x, y, w, h, r, i;
        //for (i = 0; i < 10000; i++)
        //{
        //    x = rnd.Next(400);
        //    y = rnd.Next(400);
        //    r = rnd.Next(20);
        //    w = rnd.Next(10);
        //    h = rnd.Next(10);
        //    g.DrawEllipse(Pens.Blue, x, y, w, h);
        //}

        //bg.Render();//(4)當完成所有圖形緩衝區中的繪製操作時,可呼叫 BufferedGraphics.Render 方法將緩衝區的內容呈現到與該緩衝區關聯的繪圖圖面或者指定的繪圖圖面。
        ////bg.Render(this.CreateGraphics());
        //bg.Dispose();//(5)完成呈現圖形之後,對 BufferedGraphics 例項呼叫釋放系統資源的 Dispose 方法。
        #endregion

        public void TestBufferedGraphics01()
        {
            //完整的例子,在一個200 * 200的矩形框內繪製10000個隨機生成的小圓
            BufferedGraphicsContext current = BufferedGraphicsManager.Current; //(1)初始化BufferedGraphicsContext 類的新例項
            //BufferedGraphics bg = current.Allocate(this.CreateGraphics(), this.DisplayRectangle); //(2)使用指定的Graphics 的畫素格式,建立指定大小的圖形緩衝區。
            using (BufferedGraphics bg = current.Allocate(this.pbx01.CreateGraphics(), this.pbx01.DisplayRectangle))  //(2)使用指定的Graphics 的畫素格式,建立指定大小的圖形緩衝區。
            {
                //隨機 寬400 高400
                using (Graphics g = bg.Graphics)//(3)透過設定 BufferedGraphics.Graphics 屬性將圖形繪製到圖形緩衝區
                {
                    System.Random rnd = new Random();
                    int x, y, w, h, r, i;
                    for (i = 0; i < 10000; i++)
                    {
                        x = rnd.Next(200);
                        y = rnd.Next(200);
                        r = rnd.Next(20);
                        w = rnd.Next(10);
                        h = rnd.Next(10);
                        g.DrawEllipse(Pens.Blue, x, y, w, h);
                    }
                    bg.Render();
                    //bg.Render(this.pbx01.CreateGraphics());//(4)當完成所有圖形緩衝區中的繪製操作時,可呼叫 BufferedGraphics.Render 方法將緩衝區的內容呈現到與該緩衝區關聯的繪圖圖面或者指定的繪圖圖面。
                    //bg.Render(this.CreateGraphics());
                    bg.Dispose();//(5)完成呈現圖形之後,對 BufferedGraphics 例項呼叫釋放系統資源的 Dispose 方法。
                }
            }
        }

        public void TestBufferedGraphics02()
        {
            //開闢一個緩衝區(如一個不顯示的Bitmap物件),在其中繪製完成後,再一次性顯示
            using (Bitmap bt = new Bitmap(200, 200))
            {
                using (Graphics bg = Graphics.FromImage(bt))
                {
                    System.Random rnd = new Random();
                    int x, y, w, h, r, i;
                    for (i = 0; i < 10000; i++)
                    {
                        x = rnd.Next(200);
                        y = rnd.Next(200);
                        r = rnd.Next(20);
                        w = rnd.Next(10);
                        h = rnd.Next(10);
                        bg.DrawEllipse(Pens.Blue, x, y, w, h);
                    }
                    //this.CreateGraphics().DrawImage(bt, new PointF(0, 0));
                    this.pbx01.CreateGraphics().DrawImage(bt, new PointF(0, 0));
                }
            }
        }
        #endregion
```

相關文章