到了mfc裡面由於有了封裝所有的hdc被隱藏在對象中做為隱藏參數傳遞(就是DC類的this啦~~)所以我們的關鍵話題就轉變為了怎樣得到想要的DC類而已這個過程其實大同小異的在消息響應的過程中WM_PAINT被轉變為OnDraw()OnPaint()一系列函數來響應這些函數一般都有個參數CDC *pDC傳入進來因此在這些函數裡面我們就只需要直接畫圖就可以了和以前sdk的方式一樣
但是WM_PAINT消息響應的頻度太高了比如最小化最大化移動窗體覆蓋等等都引起重繪經常的這樣畫圖很是消耗性能在有些場合比如隨機作圖的場合每一次就改變還導致了程序的無法實現怎麼解決後一種問題呢
ms在msdn的例子裡面交給我們document/view的經典解決辦法將圖形的數據存儲在document類裡面view類只是根據這些數據繪圖比如你要畫個圓只是將圓心和半徑存在document裡面view類根據這個裡面的數據在屏幕上面重新繪制那麼我們只需要隨機產生一次數據就可以了
這樣還是存在性能的問題於是我們開始考慮另外的解決方法我們知道將內存中的圖片原樣輸出到屏幕是很快的這也是我們在dos時代經常做的事情能不能在windows也重新利用呢?答案就是內存緩沖繪圖我們今天的主題
我們還是回到DC上來既然DC是繪圖對象我們也就可以自己來在內存裡面造一個讓它等於我們想要的圖圖(CBitmap)可以存儲在document類裡面每一次刷新屏幕都只是將這個圖輸出到屏幕上面每一次作圖都是在內存裡面繪制保存在document的圖裡面必要時還可以將圖輸出到外存保存這樣既保證了速度也解決了隨機的問題在復雜作圖的情況下對內存的開銷也不大(總是一副圖片的大小)這是一個很好的解決辦法現在讓我們來實現它們
我們在document類裡面保存一個圖片
CBitmap m_bmpBuf;//這裡面保存了我們做的圖存在於內存中
在view類裡面我們需要將這個圖拷貝到屏幕上去
位於OnDraw(CDC *pDC)函數中
CDC dcMem;//以下是輸出位圖的標准操作
CBitmap *pOldBitmap = NULL;
dcMemCreateCompatibleDC(NULL);
pOldBitmap = dcMemSelectObject(&pDoc>m_bmpBuf);
BITMAP bmpinfo;
pDoc>m_bmpBufGetBitmap(&bmpinfo);
pDC>BitBlt(bmpinfobmWidthbmpinfobmHeight&dcMemSRCCOPY);
dcMemSelectObject(pOldBitmap);
dcMemDeleteDC();
在我們需要畫圖的函數裡面我們完成繪圖工作
CBmpDrawDoc *pDoc = GetDocument(); //得到document中的bitmap對象
CDC *pDC = GetDC();
CDC dcMem;
dcMemCreateCompatibleDC(NULL);//這裡我們就在內存中虛擬建造了DC
pDoc>m_bmpBufDeleteObject();
pDoc>m_bmpBufCreateCompatibleBitmap(pDC);//依附DC創建bitmapCBitmap *pOldBitmap = dcMemSelectObject(&pDoc>m_bmpBuf);//我們調入了我們bitmap目標
dcMemFillSolidRect(RGB());//這些時繪圖操作隨便你^_^
dcMemTextOut(Helloworld!);
dcMemRectangle();
dcMemFillSolidRect(RGB());
pDC>BitBlt(&dcMemSRCCOPY);//第一次拷貝到屏幕
dcMemSelectObject(pOldBitmap);
dcMemDeleteDC();
全部的過程就是這樣很簡單吧以此為例子還可以實現個緩沖或者多個緩沖等等視具體情況而定當然在緩沖區還可以實現很多高級的圖形操作比如透明合成等等取決於具體的算法需要對內存直接操作(其實就是當年dos怎麼做現在還怎麼做)
再來解釋一下前面說的為什麼不能用全局變量保存DC問題其實DC也是用句柄來標識的所以也具有句柄的不確定性就是只能隨用隨取不同時間兩次取得的是不同的(使用過文件句柄地話應該很容易理解的)那麼我們用全局變量保存的DC就沒什麼意義了下次使用只是什麼也畫不出來(這一點的理解可以這樣DC需要占用一定的內存那麼在頻繁的頁面調度中位置難免改變於是用來標志指針的句柄也就不同了)
[] []
From:http://tw.wingwit.com/Article/program/Delphi/201311/24798.html