TransparentBlt (Win98/2000+)
BOOL TransparentBlt(
HDC hdcDest, int xDest, int yDest, int wDest, int hDest,
HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc,
UINT crTransparent // 透明色 COLORREF
);
Msimg32.lib,載入 Msimg32.dll。目標:將來源位圖中「透明色」像素**不繪製**,保留目標 DC 原有像素。
利用 **單色遮罩位圖** (1-bit per pixel) 配合 ROP 碼組合實現。
HBITMAP hMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL); // 1 plane, 1 bit/pixel
HDC hMaskDC = CreateCompatibleDC(hdcSrc);
SelectObject(hMaskDC, hMask);
SetBkColor(hdcSrc, crTransparent); // 透明色 → 背景色
BitBlt(hMaskDC, 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
// 結果:來源中透明色像素 → 遮罩變白 (1),非透明色 → 遮罩變黑 (0)
SetBkColor(hdcSrc, RGB(0,0,0));
SetTextColor(hdcSrc, RGB(255,255,255));
BitBlt(hdcSrc, 0, 0, nWidth, nHeight, hMaskDC, 0, 0, SRCAND);
// 結果:遮罩白(1)處保留來源像素,遮罩黑(0)處來源變黑 (0)
// 透明區域在來源 DC 變為純黑
SetBkColor(hdcDest, RGB(255,255,255));
SetTextColor(hdcDest, RGB(0,0,0));
BitBlt(hdcDest, xDest, yDest, nWidth, nHeight, hMaskDC, 0, 0, SRCAND);
// 結果:遮罩白(1)處目標變黑 (準備接收來源),遮罩黑(0)處目標保留原像素
BitBlt(hdcDest, xDest, yDest, nWidth, nHeight, hdcSrc, 0, 0, SRCPAINT);
// 結果:來源黑(0)不影響目標,來源非黑像素覆蓋目標黑區 → 完成透明合成
DeleteObject(hMask), DeleteDC(hMaskDC)。
void DrawTransparentBitmap(CDC* pDestDC, CBitmap* pSrcBmp, CPoint ptDest, COLORREF crTransparent) {
BITMAP bm; pSrcBmp->GetBitmap(&bm);
CDC srcDC, maskDC;
srcDC.CreateCompatibleDC(pDestDC);
maskDC.CreateCompatibleDC(pDestDC);
CBitmap* pOldSrc = srcDC.SelectObject(pSrcBmp);
CBitmap maskBmp; maskBmp.CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
CBitmap* pOldMask = maskDC.SelectObject(&maskBmp);
// 1. 生成遮罩
srcDC.SetBkColor(crTransparent);
maskDC.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &srcDC, 0, 0, SRCCOPY);
// 2. 來源 AND 遮罩 → 透明區變黑
srcDC.SetBkColor(RGB(0,0,0)); srcDC.SetTextColor(RGB(255,255,255));
srcDC.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &maskDC, 0, 0, SRCAND);
// 3. 目標 AND 遮罩 → 透明區變黑 (準備接收)
pDestDC->SetBkColor(RGB(255,255,255)); pDestDC->SetTextColor(RGB(0,0,0));
pDestDC->BitBlt(ptDest.x, ptDest.y, bm.bmWidth, bm.bmHeight, &maskDC, 0, 0, SRCAND);
// 4. 來源 OR 目標 → 完成
pDestDC->BitBlt(ptDest.x, ptDest.y, bm.bmWidth, bm.bmHeight, &srcDC, 0, 0, SRCPAINT);
srcDC.SelectObject(pOldSrc);
maskDC.SelectObject(pOldMask);
}
| 操作 | ROP | 邏輯 | 遮罩=1 (非透明) | 遮罩=0 (透明) |
|---|---|---|---|---|
| 生成遮罩 | SRCCOPY | D = S | S=透明色→D=1(白) | S≠透明色→D=0(黑) | — |
| 來源預處理 | SRCAND | D = S & M | 保留 S | S=0 (黑) |
| 目標預處理 | SRCAND | D = D & M | D=0 (黑) 準備接收 | 保留 D |
| 最終合成 | SRCPAINT | D = S | D | S 覆蓋 D | D 不變 |
BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; // 全域不透明度 255, 使用逐像素 Alpha
AlphaBlend(hdcDest, x, y, w, h, hdcSrc, 0, 0, w, h, bf);
// 需 32-bit DIB Section (biBitCount=32, biCompression=BI_RGB),Alpha 通道預乘或非預乘依 bf.AlphaFormat
優點:支援半透明、漸變邊緣、陰影效果。缺點:需 32-bit 位圖、Win2000+、效能略低於遮罩法。