最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#雙緩沖技術(shù)實(shí)例詳解

 更新時(shí)間:2016年02月26日 09:33:40   作者:Alexander  
這篇文章主要介紹了C#雙緩沖技術(shù),結(jié)合實(shí)例形式較為詳細(xì)的分析了C#雙緩沖的功能,實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例分析了C#雙緩沖技術(shù)。分享給大家供大家參考,具體如下:

雙緩沖解決閃爍問題。

整理:

GDI+的雙緩沖問題

一直以來的誤區(qū):.net1.1 和 .net 2.0 在處理控件雙緩沖上是有區(qū)別的。
.net 1.1 中,使用:this.SetStyle(ControlStyles.DoubleBuffer, true);
.net 2.0中,使用:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
導(dǎo)致畫面閃爍的關(guān)鍵原因分析:

一、繪制窗口由于大小位置狀態(tài)改變進(jìn)行重繪操作時(shí)

繪圖窗口內(nèi)容或大小每改變一次,都要調(diào)用Paint事件進(jìn)行重繪操作,該操作會(huì)使畫面重新刷新一次以維持窗口正常顯示。刷新過程中會(huì)導(dǎo)致所有圖元重新繪制,而各個(gè)圖元的重繪操作并不會(huì)導(dǎo)致Paint事件發(fā)生,因此窗口的每一次刷新只會(huì)調(diào)用Paint事件一次。窗口刷新一次的過程中,每一個(gè)圖元的重繪都會(huì)立即顯示到窗口,因此整個(gè)窗口中,只要是圖元所在的位置,都在刷新,而刷新的時(shí)間是有差別的,閃爍現(xiàn)象自然會(huì)出現(xiàn)。

所以說,此時(shí)導(dǎo)致窗口閃爍現(xiàn)象的關(guān)鍵因素并不在于Paint事件調(diào)用的次數(shù)多少,而在于各個(gè)圖元的重繪。

根據(jù)以上分析可知,當(dāng)圖元數(shù)目不多時(shí),窗口刷新的位置也不多,窗口閃爍效果并不嚴(yán)重;當(dāng)圖元數(shù)目較多時(shí),繪圖窗口進(jìn)行重繪的圖元數(shù)量增加,繪圖窗口每一次刷新都會(huì)導(dǎo)致較多的圖元重新繪制,窗口的較多位置都在刷新,閃爍現(xiàn)象自然就會(huì)越來越嚴(yán)重。特別是圖元比較大繪制時(shí)間比較長(zhǎng)時(shí),閃爍問題會(huì)更加嚴(yán)重,因?yàn)闀r(shí)間延遲會(huì)更長(zhǎng)。

解決上述問題的關(guān)鍵在于:窗口刷新一次的過程中,讓所有圖元同時(shí)顯示到窗口。

二、進(jìn)行鼠標(biāo)跟蹤繪制操作或者對(duì)圖元進(jìn)行變形操作時(shí)

當(dāng)進(jìn)行鼠標(biāo)跟蹤繪制操作或者對(duì)圖元進(jìn)行變形操作時(shí),Paint事件會(huì)頻繁發(fā)生,這會(huì)使窗口的刷新次數(shù)大大增加。雖然窗口刷新一次的過程中所有圖元同時(shí)顯示到窗口,但也會(huì)有時(shí)間延遲,因?yàn)榇藭r(shí)窗口刷新的時(shí)間間隔遠(yuǎn)小于圖元每一次顯示到窗口所用的時(shí)間。因此閃爍現(xiàn)象并不能完全消除!

所以說,此時(shí)導(dǎo)致窗口閃爍現(xiàn)象的關(guān)鍵因素在于Paint事件發(fā)生的次數(shù)多少。

解決此問題的關(guān)鍵在于:設(shè)置窗體或控件的幾個(gè)關(guān)鍵屬性。

使用雙緩沖

解決雙緩沖的關(guān)鍵技術(shù):

1、設(shè)置顯示圖元控件的幾個(gè)屬性:  必須要設(shè)置,否則效果不是很明顯!

this.SetStyle(ControlStyles.OptimizedDoubleBuffer | 
          ControlStyles.ResizeRedraw |
          ControlStyles.AllPaintingInWmPaint, true);

2、窗口刷新一次的過程中,讓所有圖元同時(shí)顯示到窗口。

可以通過以下幾種方式實(shí)現(xiàn),這幾種方式都涉及到Graphics對(duì)象的創(chuàng)建方式。

具體實(shí)現(xiàn)

1、利用默認(rèn)雙緩沖

(1)在應(yīng)用程序中使用雙緩沖的最簡(jiǎn)便的方法是使用 .NET Framework 為窗體和控件提供的默認(rèn)雙緩沖。通過將 DoubleBuffered 屬性設(shè)置為 true。

this.DoubleBuffered=true;

(2)使用 SetStyle 方法可以為 Windows 窗體和所創(chuàng)作的 Windows 控件啟用默認(rèn)雙緩沖。

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

2、手工設(shè)置雙緩沖

.netframework提供了一個(gè)類BufferedGraphicsContext負(fù)責(zé)單獨(dú)分配和管理圖形緩沖區(qū)。每個(gè)應(yīng)用程序域都有自己的默認(rèn) BufferedGraphicsContext 實(shí)例來管理此應(yīng)用程序的所有默認(rèn)雙緩沖。大多數(shù)情況下,每個(gè)應(yīng)用程序只有一個(gè)應(yīng)用程序域,所以每個(gè)應(yīng)用程序通常只有一個(gè)默認(rèn) BufferedGraphicsContext。默認(rèn) BufferedGraphicsContext 實(shí)例由 BufferedGraphicsManager 類管理。通過管理BufferedGraphicsContext實(shí)現(xiàn)雙緩沖的步驟如下:

(1)獲得對(duì) BufferedGraphicsContext 類的實(shí)例的引用。

(2)通過調(diào)用 BufferedGraphicsContext.Allocate 方法創(chuàng)建 BufferedGraphics 類的實(shí)例。

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

(4)當(dāng)完成所有圖形緩沖區(qū)中的繪制操作時(shí),可調(diào)用 BufferedGraphics.Render 方法將緩沖區(qū)的內(nèi)容呈現(xiàn)到與該緩沖區(qū)關(guān)聯(lián)的繪圖圖面或者指定的繪圖圖面。

(5)完成呈現(xiàn)圖形之后,對(duì) BufferedGraphics 實(shí)例調(diào)用釋放系統(tǒng)資源的 Dispose 方法。

完整的例子,在一個(gè)400*400的矩形框內(nèi)繪制10000個(gè)隨機(jī)生成的小圓。

BufferedGraphicsContext current = BufferedGraphicsManager.Current; //(1)
BufferedGraphics bg;
bg = current.Allocate(this.CreateGraphics(),this.DisplayRectangle); //(2)
Graphics g = bg.Graphics;//(3)
//隨機(jī) 寬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、自己開辟一個(gè)緩沖區(qū)(如一個(gè)不顯示的Bitmap對(duì)象),在其中繪制完成后,再一次性顯示。

完整代碼如下:

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)); 

另外一個(gè)例子,差不多

Graphics對(duì)象的創(chuàng)建方式:

a、在內(nèi)存上創(chuàng)建一塊和顯示控件相同大小的畫布,在這塊畫布上創(chuàng)建Graphics對(duì)象。

接著所有的圖元都在這塊畫布上繪制,繪制完成以后再使用該畫布覆蓋顯示控件的背景,從而達(dá)到“顯示一次僅刷新一次”的效果!

實(shí)現(xiàn)代碼(在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; //高質(zhì)量
g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移質(zhì)量
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)//僅當(dāng)編輯節(jié)點(diǎn)操作時(shí)顯示圖元熱點(diǎn)
      {
        drawobject.DrawTracker(g);
      }
    }
}
using (Graphics tg = e.Graphics)
{
    tg.DrawImage(bufferimage, 0, 0);//把畫布貼到畫面上
}

b、直接在內(nèi)存上創(chuàng)建Graphics對(duì)象:

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)//僅當(dāng)編輯節(jié)點(diǎn)操作時(shí)顯示圖元熱點(diǎn)
      {
        drawobject.DrawTracker(g);
      }
    }
}
myBuffer.Render(e.Graphics);
g.Dispose();
myBuffer.Dispose();//釋放資源

至此,雙緩沖問題解決,兩種方式的實(shí)現(xiàn)效果都一樣,但最后一種方式的占有的內(nèi)存很少,不會(huì)出現(xiàn)內(nèi)存泄露!

接下來是對(duì)acdsee拖動(dòng)圖片效果的實(shí)現(xiàn)。開始不懂雙緩沖,以為雙緩沖可以解決這個(gè)問題,結(jié)果發(fā)現(xiàn)使用了雙緩沖沒啥效果,請(qǐng)教了高人,然后修改了些代碼,完成這個(gè)效果。

圖片是在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);//圖片移動(dòng)后顯示的底色
      g.SmoothingMode = SmoothingMode.HighQuality; //高質(zhì)量
      g.PixelOffsetMode = PixelOffsetMode.HighQuality; //高像素偏移質(zhì)量
      g.DrawImageUnscaled(currentMap, new System.Drawing.Point(e.Location.X - mousedrag.X, e.Location.Y - mousedrag.Y));//在g中移動(dòng)圖片,原圖在(0,0)畫的,所以直接用new System.Drawing.Point(e.Location.X - mousedrag.X, e.Location.Y - mousedrag.Y)就好。
      g.Dispose();
      pictureBox1.Image = img;//img是在鼠標(biāo)這個(gè)位置時(shí)生成被移動(dòng)后的暫時(shí)的圖片
  }
}
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;
  }
}

說說思路,在鼠標(biāo)點(diǎn)下時(shí)創(chuàng)建一個(gè)bitmap,currentMap,用它來存放當(dāng)前圖像。鼠標(biāo)移動(dòng)時(shí),根據(jù)鼠標(biāo)位置畫圖,最后,鼠標(biāo)up時(shí),重新畫圖。

更多關(guān)于C#相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《C#面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《C#常見控件用法教程》及《C#數(shù)據(jù)結(jié)構(gòu)與算法教程

希望本文所述對(duì)大家C#程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • 基于WPF平臺(tái)使用純C#實(shí)現(xiàn)動(dòng)態(tài)處理json字符串

    基于WPF平臺(tái)使用純C#實(shí)現(xiàn)動(dòng)態(tài)處理json字符串

    在當(dāng)今的軟件開發(fā)領(lǐng)域,數(shù)據(jù)的交換與存儲(chǔ)變得愈發(fā)頻繁,JSON作為一種輕量級(jí)的數(shù)據(jù)交換格式,在 WPF平臺(tái)開發(fā)的桌面應(yīng)用里,我們常常需要與各種數(shù)據(jù)源交互,動(dòng)態(tài)處理JSON字符串就成為了一項(xiàng)必備技能,本文將深入探討如何在 WPF 平臺(tái)上,僅使用純C#代碼實(shí)現(xiàn)對(duì)JSON字符串的動(dòng)態(tài)處理
    2025-01-01
  • C#操作xml文件之Linq To Xml詳解

    C#操作xml文件之Linq To Xml詳解

    Linq To Xml,不看其他,單純的看名字都能感覺到,其可以使用靈活且強(qiáng)大的Linq語法,同時(shí)也可以使用lambda以及Xpath定位。本文將利用C#實(shí)現(xiàn)操作Linq To Xml,感興趣的可以了解一下
    2022-11-11
  • C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能(客戶端)

    C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能(客戶端)

    這篇文章主要為大家詳細(xì)介紹了C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能,客戶端方向,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C# 中this關(guān)鍵字的主要作用

    C# 中this關(guān)鍵字的主要作用

    this 關(guān)鍵字在C#中主要用于引用當(dāng)前對(duì)象,區(qū)分字段與局部變量,調(diào)用其他構(gòu)造函數(shù)以及傳遞當(dāng)前對(duì)象給其他方法或構(gòu)造函數(shù),本文重點(diǎn)介紹C# this關(guān)鍵字的作用,感興趣的朋友一起看看吧
    2024-02-02
  • 基于NPOI用C#開發(fā)的Excel以及表格設(shè)置

    基于NPOI用C#開發(fā)的Excel以及表格設(shè)置

    這篇文章主要為大家詳細(xì)介紹了基于NPOI用C#開發(fā)的Excel以及表格設(shè)置,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • c#中token的使用方法實(shí)例

    c#中token的使用方法實(shí)例

    本文主要介紹了c#中token的使用方法實(shí)例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出任一Word圖表的通用呈現(xiàn)方法

    C#實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出任一Word圖表的通用呈現(xiàn)方法

    應(yīng)人才測(cè)評(píng)產(chǎn)品的需求,導(dǎo)出測(cè)評(píng)報(bào)告是其中一個(gè)重要的環(huán)節(jié),報(bào)告的文件類型也多種多樣,其中WORD輸出也扮演了一個(gè)重要的角色,本文給大家介紹了C#實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出任一Word圖表的通用呈現(xiàn)方法及一些體會(huì),需要的朋友可以參考下
    2023-10-10
  • c#動(dòng)態(tài)改變webservice的url訪問地址

    c#動(dòng)態(tài)改變webservice的url訪問地址

    這篇文章主要介紹了c#動(dòng)態(tài)改變webservice的url訪問地址,需要的朋友可以參考下
    2014-03-03
  • C#事件實(shí)例詳解

    C#事件實(shí)例詳解

    這篇文章主要介紹了C#事件實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C#控制臺(tái)基礎(chǔ) list<>初始化的兩種方法

    C#控制臺(tái)基礎(chǔ) list<>初始化的兩種方法

    這篇文章主要介紹了C#控制臺(tái)基礎(chǔ) list<>初始化的兩種方法,需要的朋友可以參考下
    2016-12-12

最新評(píng)論

铜川市| 常宁市| 越西县| 东丽区| 苗栗县| 阿图什市| 扎兰屯市| 南平市| 徐闻县| 依安县| 绥化市| 伊春市| 乐安县| 乐安县| 乌兰县| 墨竹工卡县| 青州市| 全南县| 喀喇沁旗| 阿拉善右旗| 浦城县| 麟游县| 十堰市| 绩溪县| 山阴县| 浦县| 太仆寺旗| 庆云县| 张北县| 库车县| 金寨县| 三河市| 文化| 梧州市| 邵阳市| 万宁市| 卓尼县| 闵行区| 揭西县| 文山县| 方正县|