日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#绘图双缓冲

發布時間:2025/7/14 C# 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#绘图双缓冲 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C#繪圖雙緩沖

?

?

C#雙緩沖解釋:

簡單說就是當我們在進行畫圖操作時,系統并不是直接把內容呈現到屏幕上,而是先在內存中保存,然后一次性把結果輸出來,如果沒用雙緩沖的話,你會發現在畫圖過程中屏幕會閃的很厲害,因為后臺一直在刷新,而如果等用戶畫完之后再輸出就不會出現這種情況,具體的做法,其實也就是先創建一個位圖對象,然后把內容保存在里面,最后把圖呈現出來。

?

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對象的創建方式。

具體實現

1、? 利用默認雙緩沖
(1)在應用程序中使用雙緩沖的最簡便的方法是使用 .NET Framework 為窗體和控件提供的默認雙緩沖。通過將 DoubleBuffered 屬性設置為 true。
????? this.DoubleBuffered=true;
(2)使用 SetStyle 方法可以為 Windows 窗體和所創作的 Windows 控件啟用默認雙緩沖。
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
2、? 手工設置雙緩沖
.netframework提供了一個類BufferedGraphicsContext負責單獨分配和管理圖形緩沖區。每個應用程序域都有自己的默認 BufferedGraphicsContext 實例來管理此應用程序的所有默認雙緩沖。大多數情況下,每個應用程序只有一個應用程序域,所以每個應用程序通常只有一個默認 BufferedGraphicsContext。默認 BufferedGraphicsContext 實例由 BufferedGraphicsManager 類管理。通過管理BufferedGraphicsContext實現雙緩沖的步驟如下:

(1)獲得對 BufferedGraphicsContext 類的實例的引用。

(2)通過調用 BufferedGraphicsContext.Allocate 方法創建 BufferedGraphics 類的實例。

(3)通過設置 BufferedGraphics.Graphics 屬性將圖形繪制到圖形緩沖區。

(4)當完成所有圖形緩沖區中的繪制操作時,可調用 BufferedGraphics.Render 方法將緩沖區的內容呈現到與該緩沖區關聯的繪圖圖面或者指定的繪圖圖面。

(5)完成呈現圖形之后,對 BufferedGraphics 實例調用釋放系統資源的 Dispose 方法。

完整的例子,在一個400*400的矩形框內繪制10000個隨機生成的小圓。


?????????? BufferedGraphicsContext current = BufferedGraphicsManager.Current; //(1)

?????????? BufferedGraphics bg;

?????????? bg = current.Allocate(this.CreateGraphics(),this.DisplayRectangle); //(2)

?????????? Graphics g = bg.Graphics;//(3)

?????????? //隨機 寬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)

?????????? //bg.Render(this.CreateGraphics());

?????????? bg.Dispose();//(5)

3、?? 自己開辟一個緩沖區(如一個不顯示的Bitmap對象),在其中繪制完成后,再一次性顯示。

完整代碼如下:


?????????? Bitmap bt = new Bitmap(400, 400);

?????????? 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(400);

?????????????? y = rnd.Next(400);

?????????????? 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 Point(0, 0));?
?

另外一個例子,差不多
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();//釋放資源 至此,雙緩沖問題解決,兩種方式的實現效果都一樣,但最后一種方式的占有的內存很少,不會出現內存泄露!



接下來是對acdsee拖動圖片效果的實現。開始不懂雙緩沖,以為雙緩沖可以解決這個問題,結果發現使用了雙緩沖沒啥效果,請教了高人,然后修改了些代碼,完成這個效果。
圖片是在pictureBox1里。
??????? Bitmap currentMap;
??????? bool first = true;
??????? private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
??????? {
??????????? if (zoom == 0)
??????????? {
??????????????? if (e.Button == MouseButtons.Left) //dragging
??????????????????? mousedrag = e.Location;
??????????????? Image myImage = myMap.GetMap();
??????????????? currentMap = new Bitmap(myImage);
??????????????? first = false;
??????????? }???
??????? }

??????? private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
??????? {
??????????? if (zoom == 0&&!first)
??????????? {
??????????????????? Image img = new Bitmap(Size.Width, Size.Height);
??????????????????? Graphics g = Graphics.FromImage(img);
??????????????????? g.Clear(Color.Transparent);//圖片移動后顯示的底色
??????????????????? g.SmoothingMode = SmoothingMode.HighQuality; //高質量
??????????????????? g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移質量
??????????????????? g.DrawImageUnscaled(currentMap, new System.Drawing.Point(e.Location.X - mousedrag.X, e.Location.Y - mousedrag.Y));//在g中移動圖片,原圖在(0,0)畫的,所以直接用new System.Drawing.Point(e.Location.X - mousedrag.X, e.Location.Y - mousedrag.Y)就好。
??????????????????? g.Dispose();
??????????????????? pictureBox1.Image = img;//img是在鼠標這個位置時生成被移動后的暫時的圖片
??????????? }
??????? }

??????? private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
??????? {
??????????? if (zoom == 0)
??????????? {
??????????????? System.Drawing.Point pnt = new System.Drawing.Point(Width / 2 + (mousedrag.X - e.Location.X),
??????????????????????????????????????????????????????????????????????????????? Height / 2 + (mousedrag.Y - e.Location.Y));
???????????????? myMap.Center = myMap.ImageToWorld(pnt);
??????????????? pictureBox1.Image = myMap.GetMap();
??????????????? first = true;
??????????? }
??????? }

說說思路,在鼠標點下時創建一個bitmap,currentMap,用它來存放當前圖像。鼠標移動時,根據鼠標位置畫圖,最后,鼠標up時,重新畫圖。

轉載于:https://www.cnblogs.com/wyh167/archive/2012/10/26/2741498.html

總結

以上是生活随笔為你收集整理的C#绘图双缓冲的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男人的天堂黄色 | 精品夜夜澡人妻无码av | av福利片| 国产精品区二区三区日本 | 日日爱影视| 福利视频在线导航 | 日韩美女免费视频 | 韩国19主播内部福利vip | 国产21页 | 色婷婷久 | 午夜插插 | 精品人妻无码一区二区三 | 伊人影片 | 色妻av | 亚洲精品中字 | 偷拍欧美亚洲 | 综合婷婷 | 99热最新网址 | 伊人亚洲天堂 | 白白色2012年最新视频 | www性| 浪潮av网站 | 精品久久久久久亚洲综合网站 | www.96av| 黄色免费网站在线观看 | 国产原创一区 | 日韩夫妻性生活 | 欧美一区二区三区婷婷 | 老司机午夜免费精品视频 | 国产精品国产三级国产三级人妇 | 中文字幕日韩三级 | 国产精品久久久999 www日本高清视频 | 日日夜夜伊人 | 国产成人精品一二三区 | 黄色福利视频网站 | 婷婷精品视频 | 69精品在线 | 日本中文字幕一区 | 日本裸体视频 | 黄黄视频在线观看 | 日本少妇毛茸茸高潮 | 成人看的视频 | 男操女视频在线观看 | av老司机在线观看 | 精东av在线 | 色乱码一区二区三区在线男奴 | 另类小说亚洲色图 | 欧美在线观看视频一区二区 | 鲁丝av | 熟女少妇在线视频播放 | 黄色片免费网站 | 国产外围在线 | 亚洲精品女人 | 男女做激情爱呻吟口述全过程 | 无码gogo大胆啪啪艺术 | 国产成人免费看 | 国产农村熟妇videos | www国产亚洲精品久久麻豆 | 国产第一页第二页 | 国产自产精品 | 亚洲国产中文在线 | 久草热在线 | 玖玖免费| 日韩美女做爰高潮免费 | 日本91网站| 国产精在线 | 四虎在线影视 | 91久久久国产精品 | 天天操天天干天天操 | 国产农村妇女aaaaa视频 | 亚洲av区无码字幕中文色 | 香蕉视频免费在线播放 | 国产精品久久亚洲7777 | 1769国产精品视频 | 欧美福利一区二区三区 | 天天综合视频 | 2021国产精品视频 | 欧美在线中文字幕 | 成人精品免费看 | 日韩在线小视频 | 成人动漫av| 又黄又骚又爽 | 99久久99久久精品国产片果冻 | 五号特工组之偷天换月 | 国产精品黄色av | 三级在线看中文字幕完整版 | 黄色网址av| 国产做爰免费观看视频 | 综合久久久久久久 | 无码人妻丰满熟妇区96 | 日韩精品一区二区三区免费视频 | 张柏芝亚洲一区二区三区 | 99久久久无码国产 | 欧美v亚洲 | 色戒在线免费 | 中文字幕人成人乱码亚洲电影 | 天天激情 | 国产在线免费av | 中文字幕制服诱惑 |