Windows 98/2000 以上提供 TransparentBlt(需連結 Msimg32.lib),參數包含目標/來源 DC、座標、尺寸與透明色。但 Win98 存在資源洩漏,建議僅在 Win2000+ 使用。
透明繪製分四步,利用單色掩碼位圖(1-bit)配合 SRCAND、SRCPAINT 等光柵運算碼:
BitBlt 複製至單色 DC → 透明區變白(1),非透明變黑(0)。SRCAND 將掩碼套用至來源圖 → 透明區變黑,其餘保留。SRCAND 將掩碼套用至目標 DC → 透明區保留背景,非透明區變黑。SRCPAINT (OR 運算) 將前景圖疊加至背景 → 完成透明合成。void TransparentBlt2(HDC hdcDest, int xDest, int yDest, int wDest, int hDest,
HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc,
UINT crTransparent) {
HDC hImageDC = CreateCompatibleDC(hdcDest), hMaskDC = CreateCompatibleDC(hdcDest);
HBITMAP hImageBMP = CreateCompatibleBitmap(hdcDest, wDest, hDest);
HBITMAP hMaskBMP = CreateBitmap(wDest, hDest, 1, 1, NULL);
HBITMAP hOldImg = (HBITMAP)SelectObject(hImageDC, hImageBMP);
HBITMAP hOldMsk = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);
// 縮放複製來源圖至暫存 DC
if (wDest == wSrc && hDest == hSrc)
BitBlt(hImageDC, 0, 0, wDest, hDest, hdcSrc, xSrc, ySrc, SRCCOPY);
else
StretchBlt(hImageDC, 0, 0, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, SRCCOPY);
// 1. 產生掩碼
SetBkColor(hImageDC, crTransparent);
BitBlt(hMaskDC, 0, 0, wDest, hDest, hImageDC, 0, 0, SRCCOPY);
// 2. 前景圖:透明區變黑
SetBkColor(hImageDC, RGB(0,0,0)); SetTextColor(hImageDC, RGB(255,255,255));
BitBlt(hImageDC, 0, 0, wDest, hDest, hMaskDC, 0, 0, SRCAND);
// 3. 背景:非透明區變黑
SetBkColor(hdcDest, RGB(255,255,255)); SetTextColor(hdcDest, RGB(0,0,0));
BitBlt(hdcDest, xDest, yDest, wDest, hDest, hMaskDC, 0, 0, SRCAND);
// 4. 合成
BitBlt(hdcDest, xDest, yDest, wDest, hDest, hImageDC, 0, 0, SRCPAINT);
// 清理
SelectObject(hImageDC, hOldImg); DeleteDC(hImageDC); DeleteObject(hImageBMP);
SelectObject(hMaskDC, hOldMsk); DeleteDC(hMaskDC); DeleteObject(hMaskBMP);
}
Christian Graus 的版本額外處理來源/目標尺寸不同的情況,建立縮放後的掩碼與圖像 DC,流程同理但更通用。實際專案建議直接呼叫系統 TransparentBlt,本文旨在說明底層原理。