日韩性视频-久久久蜜桃-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 | 深夜福利久久 | 国产无遮挡又黄又爽免费网站 | 日本狠狠爱 | 强侵犯の奶水授乳羞羞漫虐 | 久久国产精品无码一级毛片 | 九一爱爱| 黄色片在线| 激情午夜婷婷 | 亚洲中文字幕一区二区在线观看 | 在线看b | 中字幕一区二区三区乱码 | 久久久国产高清 | 五月天黄色小说 | 污视频大全 | 美妇av | 大胸美女无遮挡 | 国产在线网址 | 久久影院一区二区 | 原来神马电影免费高清完整版动漫 | 欧美一级视频在线观看 | 加勒比成人在线 | 波多野42部无码喷潮在线 | 久久婷婷色 | 青草视频在线免费观看 | 精品三区视频 | 国产区视频| 特黄特色大片免费视频大全 | 久久视频精品在线 | 麻豆入口| 精品一区在线观看视频 | 成人免费网站 | 欧美中文视频 | 欧美性猛交xxxx乱大交蜜桃 | 日韩色图一区 | 在线观看av国产一区二区 | 免费精品视频一区二区三区 | 欧美成人黑人猛交 | 欧美xxx视频 | 天天拍天天射 | 欧美性狂猛xxxxxbbbbb | 中文字幕日韩人妻在线视频 | 欧美日韩一区二区在线视频 | 日本美女视频 | 久久视频黄色 | 尼姑福利影院 | 婷婷综合网 | 男人把女人捅爽 | a级在线免费观看 | 午夜精品久久久久久久久久 | 91视频看片 | 日韩色视频在线观看 | 免费黄色一区二区 | 蜜桃91麻豆精品一二三区 | 葵司免费一区二区三区四区五区 | 人人草网站 | 国产精品亚洲αv天堂无码 伊人性视频 | 亚洲69| 欧美成人一二三区 | 久久久91精品国产一区二区三区 | 亚洲视频1 | 91精品久久久久久久久久入口 | 国产av一区精品 | 91久久电影 | 亚洲乱码国产乱码精品精软件 | 91丝袜在线 | 在线免费观看中文字幕 | 久久国内免费视频 | 精品国产黄 | 久久成人乱码欧美精品一区二区 | 国产一级片av | 亚洲九九夜夜 | 国产九色91回来了 | 国产成人在线免费观看 | 国产一区二区视频在线免费观看 | 天天躁狠狠躁 | 日日摸日日碰 | 午夜黄色福利视频 | 国产专区欧美专区 | 日韩欧美国产一区二区 | 毛利兰被扒开腿做同人漫画 | 观看av| 亚洲制服在线观看 | 中文字幕 欧美 日韩 | 欧美 日韩 国产 成人 在线观看 | 久久嫩草视频 | 日本电车痴汉 | 一区二区男女 | 午夜一区二区三区四区 | 美女福利在线视频 | 91插插插插| 亚洲一级伦理 | 国产成人精品一区二区三区福利 | 成人午夜免费福利视频 | 久久久精品一区二区三区 |