mfc雙緩存
A. MFC雙緩沖區問題
不要刷背景
使用雙緩沖,先在內存緩沖繪圖然後再BltBit到窗口。
B. MFC里 我在OnLButtonDown和OnMouseMove里編寫的繪畫步驟怎麼加雙緩存
內存DC的雙緩沖,是為了讓每次刷新的時候(即觸發OnDraw/OnPaint時)快速重繪。在滑鼠消息中的實際繪圖,是用不到雙緩沖的。
另外一方面,滑鼠消息繪圖,如果希望在重繪時生效,在繪制屏幕DC的同時,應該同步繪制內存DC,這樣在重繪時就不需要更新內存DC,直接雙緩沖生效。你需要的可能是這個吧,就是在滑鼠消息裡面,確定繪圖生效後(應該是OnLButtonUp),同時在內存DC繪制一遍即可。
C. 請問MFC中用雙緩存技術如何解決圖形重繪問題 請給個稍微詳細的步驟(不需詳細代碼) 謝謝!
這個需要用多線程,如果單線程的話,無法返回雙緩存技術。
一個線程A在一個緩沖區中創建內存點陣圖時,另外一個線程B將另一個緩沖區b中的內存點陣圖顯示當屏幕上。
這個你要設計多線程編程,兩個線程同步,內存點陣圖的創建工作。你只要有mfc基礎,不難做。這里內存點陣圖如果大的話,編程語言無法動態申請到更大內存,建議採用全局屬性的緩沖區。因為全局是靜態存儲的,你可以申請更大的空間。一種折中的方案是內存文件,但這個方式效率有點兒低。
D. 用MFC雙緩存畫圖,填充內存背景為白色。pDC接受最新的拷貝的圖像,第二次畫圖時第一次的怎麼保留
關鍵在於你每次繪制新的圖像時都把內存背景設置為白色了吧?如果這樣第一次的繪圖肯定就沒了。
第一種方法是就用一個內存DC一直在上面繪圖,只第一次刷背景,那就別把memdc聲明成局部變數,聲明成成員變數。
要不就把每次接收的圖像保存起來,每次畫圖的時候都依次畫保存起來的圖像。
根據你的需要選擇吧。
E. 50分求教MFC對話框中雙緩沖繪圖避免閃爍的問題
樓上回答的仍然是Win32API實現的雙緩沖,我來給個用MFC實現的。例子可能特殊了一點,不過應該能看明白。雙緩沖當然需要一個緩沖C,如果你要畫的東西總需要固定的背景(比如圖片)的話,可能還需要一個背景DC:
在窗口類的聲明中,即頭文件中:
CDC m_dcMem,m_dcBack; //緩沖DC和背景DC
在窗口類的實現,即CPP文件中:
在OnInitDialog或者OnCreate里初始化兩個DC,以下的m_nWidth和m_nHeight之類的變數肯定要換成你自己的:
m_dcMem.CreateCompatibleDC(GetDC());
m_dcBack.CreateCompatibleDC(GetDC());
CBitmap tmp,tmpp;
tmp.CreateCompatibleBitmap(GetDC(), m_nWidth, m_nHeight);
tmpp.CreateCompatibleBitmap(GetDC(), m_nWidth, m_nHeight);
m_dcBack.SelectObject(&tmp);
m_dcMem.SelectObject(&tmpp);
tmp.DeleteObject();
tmpp.DeleteObject();
然後每次先把背景DC畫到緩沖DC上:
m_dcMem.BitBlt(0, 0, m_nWidth, m_nHeight, &m_dcBack, 0, 0, SRCCOPY);
然後再畫自己的東西
m_dcMem.XXXXXX
(如果不需要背景DC,則直接把內容畫到緩沖DC上)
最後記得在OnPaint里將緩沖DC畫到實際的窗口上:
GetDC()->BitBlt(m_nLeft, m_nTop, m_nWidth, m_nHeight, &m_dcMem, 0, 0, SRCCOPY);
F. MFC緩存隊列長度
不一定這個長度估不出來的
用MFC實現的基於隊列和棧的迷宮搜索。
MFC繪圖使用雙緩沖,迷宮搜索方式有深度優先(數據結構是棧) 和 寬度優先(數據結構是隊列),地圖文件用txt存儲,可以打開或保存地圖文件。
G. MFC在靜態文本上使用雙緩沖畫圖
雙緩沖想必是你是知道的了。你從CStatic類派生一個自己的靜態文本框類CXXStatic,重載OnDrawItem,那個結構體里lpDrawItemStruct(名字好像是這樣的)有個結構體里有個CDC的句柄m_hdc(好像是這樣的),用這個句柄就是靜態控制項的繪圖句柄,這樣使用這個句柄:
CDC dc;
dc.Attach(m_hdc);
//然後就和普通dc一樣用了...
CDC memDC;
memDC.Craete...
CBitmap memBmp;
memBmp.Create...
memDC.SelectObject(&memBmp);
memDC....//畫圖
dc.bitblt(....);//貼上點陣圖
可以禁用對CStaitci::OnDrawItem的調用,應該要設置靜態控制項為OwnerDraw屬性吧,記不清了
如果框架沒有自動發送消息給CXXStatic,就自己重載對話框的OnDrawItem,在這裡面給靜態控制項發送WM_DRAWITEM(好像是這個名字,記不清拉)。
大概就是這樣的了,和自繪按鈕是一樣的伎倆。。。。
H. MFC中雙緩存後為什麼會黑屏
主要實現代碼如下:
CDC MemDC; //首先定義一個內存顯示設備對象
CBitmap MemBitmap;//定義一個點陣圖對象
MemDC.CreateCompatibleDC(NULL); //創建兼容設備dc
MemBitmap.CreateCompatibleBitmap(pDC,W,H);
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
MemDC.FillSolidRect(0,0,W,H,RGB(255,255,255));//填充初始顏色
cimg.DrawToHDC(MemDC.GetSafeHdc(),CRect(0,0,W,H));//繪圖到內存顯示設備
pDC->BitBlt(rect.left,rect.top,W,H,&MemDC,0,0,SRCCOPY); //繪圖到真實顯示設備
主要思路就是先創建一個虛擬dc和一張虛擬點陣圖,用於將圖像輸出到虛擬設備上,內容在虛擬設備揮好後再輸出到真實dc上顯示出來,這樣在要輸出的時候才輸出,提高了繪圖效率。在這種方式下,所有需要顯示的函數都可以先會在內存虛擬dc上,虛擬dc可以作為一個全局的變數或者類的成員變數存在,方便調用。
另外還需重載背景刷新函數OnEraseBkgnd(view類的函數),其的主要作用是刷新背景,刷新次數頻繁了就出現了閃爍,因此在需要的時候調用這個函數,其他時候直接return ture即可。
其實基本思路還是暫停MFC自帶的刷新機制,控制圖像的刷新,在你想要刷新的時候刷新即可。
2
另外有個參考資料如下,不懂實際操作時候可以參考。
內存DC和內存點陣圖
實驗目的:
學會使用內存DC解決重畫問題
實驗內容:
當Windows系統需要重畫窗口時,會向窗口發送一條WM_PAINT消息,應用程序需要在WM_PAINT消息響應函數(或View類中的OnDraw)中重畫整個窗口(即重新顯示窗口中的信息)。
可以把所有繪圖的工作放到OnDraw、OnPaint等函數中作,但這樣作可能會出現三個缺點:速度慢、屏幕閃爍、不方便。
所以,對於需要較復雜繪圖的程序,一般方法是在內存中保存窗口內容的一個拷貝(內存DC)來實現重畫。每次收到WM_PAINT消息時,將內存DC的內容復制到屏幕上。
重建一個工程,在View類的頭文件中向View類添加成員變數:指向內存DC的指針和指向內存點陣圖的指針
CDC* m_pMemDC;
CBitmap* m_pBitmap;
在View類的構造函數中添加代碼創建CDC和CBitmap對象
m_pMemDC=new CDC();
m_pBitmap=new CBitmap();
在View類的析構函數中添加代碼銷毀CDC和CBitmap對象
delete m_pMemDC;
delete m_pBitmap;
用Class Wizard為View類添加一個WM_CREATE消息處理函數OnCreate(LPCREATESTRUCT lpCreateStruct),在處理函數中添加代碼創建內存DC和點陣圖
//得到屏幕尺寸
int maxX=GetSystemMetrics(SM_CXSCREEN);
int maxY=GetSystemMetrics(SM_CYSCREEN);
//創建內存DC和點陣圖
CDC* pDC=GetDC();
m_pMemDC->CreateCompatibleDC(pDC);
m_pBitmap->CreateCompatibleBitmap(pDC,maxX,maxY);
m_pMemDC->SelectObject(m_pBitmap);
ReleaseDC(pDC);
//初始化內存DC為全白
CBrush brush;
brush.CreateStockObject(WHITE_BRUSH);
CBrush* poldbrush=m_pMemDC->SelectObject(&brush);
m_pMemDC->PatBlt(0,0,maxX,maxY,PATCOPY);
3
m_pMemDC->SelectObject(poldbrush);
在OnDraw中添加重畫代碼
CRect rect;
GetClientRect(rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),m_pMemDC,0,0,SRCCOPY);
用Class Wizard為View類添加一個WM_LBUTTONDOWN消息處理函數,用於響應滑鼠左鍵單擊消息。
在該滑鼠消息處理函數中,添加繪圖代碼
m_pMemDC->TextOut(point.x,point.y,"Test");
Invalidate(FALSE);
編譯運行程序,在滑鼠左鍵點擊的地方都會顯示出「Test」。最小化窗口,再恢復窗口,可以發現前面顯示的「Test」仍然保留。
Invalidate函數刷新整個窗口,如果每次繪圖修改的區域較小,可以使用InvalidateRect函數代替Invalidate函數以加快顯示速度。例如滑鼠消息處理函數中的繪圖代碼可以改為如下代碼:
CString str="Test";
CRect rect(point.x,point.y,point.x,point.y);
m_pMemDC->DrawText(str,&rect,DT_CALCRECT|DT_LEFT); //得到要繪制的文本在屏幕上的尺寸
m_pMemDC->DrawText(str,&rect,DT_LEFT);
InvalidateRect(rect,FALSE); //只刷新需要繪制文本的區域
如果繪圖次數很頻繁,點陣圖很大,用這種方法可以明顯改善繪圖性能。
Invalidate(TRUE)先清除DC再重畫,Invalidate(FALSE)直接在原圖上畫,性能更好,兩者可以視情況選用。
I. MFC用了雙緩存,但是快速刷新還是會閃爍
在MFC中, 有個坑爹的東西, 就是背景刷新, 跟前景刷新不是同步的.
所以你用了雙緩存, 也還是會閃, 因為它永遠是先繪制背景, 然後再繪制前景.
解決辦法有二:
是處理OnEraseBkg相關的消息, 不繪制背景.
直接調用DC繪制, 不要調用Invalidate去刷新. 當然OnPaint中也要處理繪制, 這樣在刷新的時候不至於繪制的東西變化. 直接繪制的好處是繪製得再快都不擔心閃了.
J. MFC雙緩沖貼圖問題
每秒顯示一次不用在緩沖區里畫圖吧,把更新的區域動態設置為你的方塊下落的那個區域就可以了,不要每次都更新整個窗體,自己寫端代碼畫個動態的矩形,每次更新這個矩形就夠了,我做數據採集也沒有用到雙緩沖畫圖,這方面也不是很了解,給你個參考吧