Re: [問題] 所謂在MemDC裡畫(更新)
※ 引述《steven70101 (老人)》之銘言:
: 遇到的問題: (題意請描述清楚)
: 最近再要時間內製作俄羅斯方塊
: 目前已經大致弄好
: 但是卻卡在一個多重貼圖閃爍的問題
: 由於是完全不懂的新手 上網查資料大至知道是要使用雙緩衝
: 或是先畫在memDC裡
: 目前已經修正到閃爍問題改善許多
: 但是方塊本身以及旁邊的計量表有時還是會閃爍
: 還找不到原因改善...
: 問題是 何謂畫在memdc裡呢
: 網路上講的整個都很抽象 偏偏又都沒實際例子
: 唯一有的也都是MFC 偏偏我是用WIN32 API
: 希望得到的正確結果:
: 希望有大大能提出具體例子好讓我了解
: 程式跑出來的錯誤結果:
: 開發平台: (例: VC++ or gcc/g++ or Dev-C++, Windows or Linux)
: 有問題的code: (請善用置底文標色功能)
: http://codepad.org/ACZcWR5v
: 補充說明:
假設你想要 Resize 視窗,則會導致視窗重新繪圖,會出現以下流程
進入 WM_PAINT 訊息 -> 裡面的 BeginPaint() 函數觸發 WM_ERASEBKGND 訊息
-> 此訊息預設的處理動作: 用白色把視窗內容填滿 -> 執行你指定的繪圖動作
又假設你的繪圖動作是,在對話方塊內畫一個矩形,且使用預設的黑色。
則螢幕畫面會不斷地,先是整個視窗變白,再畫黑矩形,因為「白黑白黑白黑」速度太快
,畫面就感覺很閃了。
版友說的,跟你提的雙緩衝,就是改變上面的流程
重繪發生 -> 禁止顯示器上的對話方塊變白 -> 在記憶體內建立跟對話方塊同大
的矩形 -> 把該記憶體清除為白色 -> 畫好黑色矩形 -> 將該記憶體內容貼到
顯示器 (BitBlt)
首先就是這樣:
case WM_ERASEBKGND:
return 0;
break;
直接 return 就可以禁止。
接著當然就是處理 WM_PAINT,在裡面建立一塊記憶體,把東西畫好,再用 BitBlt 讓
顯示器反應新畫面。
大致的函數調用順序如下
hdc = BeginPaint(...);
HDC hdcMem = CreateCompatibleDC(hhdc);
HBITMAP bmpMem = CreateCompatibleBitmap(hdc, 客戶區寬度, 客戶區高度);
SelectObject(hdcMem, bmpMem);
FillRect(hdcMem, &rectClient, (HBRUSH) GetStockObject(BLACK_BRUSH));
Rectangle(hdcMem, 0, 20, 客戶區寬度, 120);
BitBlt(hdc, 0, 0, 客戶區寬度, 客戶區高度, hdcMem, 0, 0, SRCCOPY);
原本 Rectangle(...) 繪圖函數,只要傳 hdc 就能把圖畫好,
但現在要畫在記憶體,所以用 hdcMem 取代。
而 hdcMem 被畫完後,結果會存在記憶體,直到你明確調用 BitBlt() 時,才會把結果
反應到螢幕上的對話方塊。
那 FillRect(...) 的目的,就是不管原本 hdcMem 存了什麼內容,都先用黑色塗滿,
也就是對應原本的 WM_ERASEBKGND 觸發的動作。
hdcMem 在使用 CreateCompatibleDC(hdc) 建立出來時,不會跟客戶區一樣大,而是
只有 1x1 大小。因此用 CreateCompatibleBitmap(...) 做出跟客戶區一樣大的
bmpMem,再用 SelectObject(hdcMem, bmpMem); 讓 hdcMem 的大小可以放大。
完整原理我是不懂,背起來就對,反正 GDI 本來就是很龐大的機制。
程式碼。用 VC 2008 的 Win32 視窗程式範本改寫,修改了 WndProc() 內容,跟增加一個
叫 CBrush 的類別。完整程式碼在網址:http://codepad.org/RyUazucp
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.140.25
→
11/27 19:20, , 1F
11/27 19:20, 1F
推
11/27 19:33, , 2F
11/27 19:33, 2F
推
11/27 20:00, , 3F
11/27 20:00, 3F
推
11/27 20:01, , 4F
11/27 20:01, 4F
推
11/27 20:15, , 5F
11/27 20:15, 5F
→
11/27 20:39, , 6F
11/27 20:39, 6F
推
11/27 20:49, , 7F
11/27 20:49, 7F
推
11/28 00:15, , 8F
11/28 00:15, 8F
推
11/28 00:21, , 9F
11/28 00:21, 9F
→
11/28 12:44, , 10F
11/28 12:44, 10F
推
11/29 13:06, , 11F
11/29 13:06, 11F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 3 篇):