當前位置:首頁 » 硬碟大全 » 雙緩存繪圖怎麼設置
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

雙緩存繪圖怎麼設置

發布時間: 2022-06-03 19:34:41

① GDI繪圖(雙緩沖)

不會,我學平面設計的~

② VB.net繪圖具體如何設置雙緩沖

Try this:

()
'Setthevalueofthedouble-bufferingstylebitstotrue.
Me.SetStyle(ControlStyles.DoubleBuffer_
OrControlStyles.UserPaint_
OrControlStyles.AllPaintingInWmPaint,_
True)
Me.UpdateStyles()
EndSub

③ 雙緩沖的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.Mole.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.Mole.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時,重新畫圖。

④ MFC在靜態文本上使用雙緩沖畫圖

void CRussia::DrawJiemian(CDC *pDC)//畫界面
{
int nOldDC=pDC->SaveDC();
//背景
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(cBkgound);
//畫分數、級別、速度
DrawScore(&memDC);//已實現
CDC memDC1;
memDC1.CreateCompatibleDC(pDC);
memDC1.SelectObject(cBlock);
//畫方塊
//m_RowCount,m_ColCount為格子行列數
//Russia[][]是存儲方塊的數組,為1表示當前位置有方塊
for(int i=0;i<m_RowCount;i++)
for(int j=0;j<m_ColCount;j++)
if(Russia[i][j]==1)
memDC.BitBlt(j*20+300,i*20+100,20,20,&memDC1,0,0,SRCCOPY);
//預覽方塊
//Will[4][4]是下一個方塊的數組,為1表示當前位置有方塊
for(int n=0;n<4;n++)
for(int m=0;m<4;m++)
if(Will[n][m]==1)
memDC.BitBlt(542+m*20,115+n*20,20,20,&memDC1,0,0,SRCCOPY);
pDC->BitBlt(0,0,800,600,&memDC,0,0,SRCCOPY);
pDC->RestoreDC(nOldDC);
}

⑤ swing雙緩沖怎麼使用

swing本身就實現了雙緩沖機制,每次刷新的都是緩沖區的圖像

⑥ 雙緩沖的8Graphics創建方式

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.Mole.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.Mole.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時,重新畫圖。
在圖形圖象處理編程過程中,雙緩沖是一種基本的技術。我們知道,如果窗體在響應WM_PAINT消息的時候要進行復雜的圖形處理,那麼窗體在重繪時由於過頻的刷新而引起閃爍現象。解決這一問題的有效方法就是雙緩沖技術。因為窗體在刷新時,總要有一個擦除原來圖象的過程OnEraseBkgnd,它利用背景色填充窗體繪圖區,然後在調用新的繪圖代碼進行重繪,這樣一擦一寫造成了圖象顏色的反差。當WM_PAINT的響應很頻繁的時候,這種反差也就越發明顯。於是我們就看到了閃爍現象。
我們會很自然的想到,避免背景色的填充是最直接的辦法。但是那樣的話,窗體上會變的一團糟。因為每次繪制圖象的時候都沒有將原來的圖象清除,造 成了圖象的殘留,於是窗體重繪時,畫面往往會變的亂七八糟。所以單純的禁止背景重繪是不夠的。我們還要進行重新繪圖,但要求速度很快,於是我們想到了使用 BitBlt函數。它可以支持圖形塊的復制,速度很快。我們可以先在內存中作圖,然後用此函數將做好的圖復制到前台,同時禁止背景刷新,這樣就消除了閃 爍。以上也就是雙緩沖繪圖的基本的思路。
首先給出實現的程序,然後再解釋,同樣是在OnDraw(CDC *pDC)中:
CDC MemDC; //首先定義一個顯示設備對象
CBitmap MemBitmap;//定義一個點陣圖對象
//隨後建立與屏幕顯示兼容的內存顯示設備
MemDC.CreateCompatibleDC(NULL);
//這時還不能繪圖,因為沒有地方畫 ^_^
//下面建立一個與屏幕顯示兼容的點陣圖,至於點陣圖的大小嘛,可以用窗口的大小,也可以自己定義(如:有滾動條時就要大於當前窗口的大小,在BitBlt時決定拷貝內存的哪部分到屏幕上)
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
//將點陣圖選入到內存顯示設備中
//只有選入了點陣圖的內存顯示設備才有地方繪圖,畫到指定的點陣圖上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
//先用背景色將點陣圖清除干凈,這里我用的是白色作為背景
//你也可以用自己應該用的顏色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//繪圖
MemDC.MoveTo(……);
MemDC.LineTo(……);
//將內存中的圖拷貝到屏幕上進行顯示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
//繪圖完成後的清理
//把前面的pOldBit選回來.在刪除MemBitmap之前要先從設備中移除它
MemDC.SelectObject(pOldBit);
MemBitmap.DeleteObject();
MemDC.DeleteDC();
雙緩沖(two way soft-closing)

⑦ 用MFC雙緩存畫圖,填充內存背景為白色。pDC接受最新的拷貝的圖像,第二次畫圖時第一次的怎麼保留

只能自己設法保存第一次畫圖的數據,在第二次畫圖時,先根據保存第一次畫圖的數據畫第一次的圖,然後再畫第二次需要畫的圖。