首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ GDI+ 雙緩沖仍閃爍根因分析:DC 兼容性與繪製順序修正

     編輯:程式設計綜合問答

現象:使用 GDI+ 實現雙緩沖(離屏 Bitmap → 內存 Graphics → 目標 DC),但畫面仍有明顯閃爍/抖動。

核心問題:DC 類型不匹配與繪製順序錯誤

  1. 直接在螢幕 DC 上創建 Graphics:Graphics g(hdc) 導致每幀直接寫入顯存,無雙緩沖效果。
  2. 缺少 WM_ERASEBKGND 抑制:系統背景擦除與自繪衝突產生閃爍。
  3. BitBlt 參數順序錯誤:目標 DC、源 DC 搞反。

標準雙緩沖正確流程

// 1. 响應 WM_PAINT
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// 2. 創建兼容內存 DC 與位圖
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP hBmp = CreateCompatibleBitmap(hdc, clientWidth, clientHeight);
HBITMAP hOldBmp = (HBITMAP)SelectObject(memDC, hBmp);

// 3. 使用 GDI+ 在內存 DC 繪圖
Graphics g(memDC); // 關鍵:綁定內存 DC
g.Clear(Color::White);
g.DrawImage(background, 0, 0);
g.DrawImage(sprite, x, y, srcX, srcY, w, h, UnitPixel);

// 4. 一次性拷貝到螢幕 DC
BitBlt(hdc, 0, 0, clientWidth, clientHeight, memDC, 0, 0, SRCCOPY);

// 5. 清理
SelectObject(memDC, hOldBmp);
DeleteObject(hBmp);
DeleteDC(memDC);
EndPaint(hwnd, &ps);

關鍵補充:抑制背景擦除

在窗口類註冊或 WM_ERASEBKGND 返回 TRUE:

case WM_ERASEBKGND:
    return TRUE; // 告訴系統:我已在 WM_PAINT 中處理背景,無需擦除

GDI+ 專用簡化類 (CPaintDC + CMemDC)

MFC/ATL 提供 CMemDC 自動管理雙緩沖,直接用 CMemDC dc(pDC) 即可。

總結

  • Graphics **必須綁定兼容內存 DC**,而非螢幕 DC。
  • 所有繪圖操作在內存 DC 完成,**最後一次 BitBlt** 上螢幕。
  • 處理 WM_ERASEBKGND 徹底消除系統擦除閃爍。

修正 DC 綁定與繪製順序,雙緩沖才能真正生效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved