使用BitBlt實現點陣圖背景透明
我們先看一下 BitBlt 這個函式的原型:
BOOL BitBlt(int x, int y, int nWidth,nHeight, CDC* PsrcDC, int xSrc, int ySrc, DWORD dwRop);
引數介紹:
int x 表示繪製點陣圖目標左上角x座標;
int y 表示繪製點陣圖目標左上角y座標;
int nWidth 表示繪製點陣圖目標的區域寬度;
int nHeight 表示繪製點陣圖目標的區域高度;
CDC* pSrcDC 表示儲存源點陣圖的裝置描述表;
int xSrc 表示源點陣圖的左上角x座標;
int ySrc 表示源點陣圖的左上角y座標;
DWORD dwRop 表示柵格運算標誌;
dwRop的取值與值的描述如下表所示:
值 |
描述 |
BLACKNESS |
用調色盤中索引為0的顏色(預設是黑色)填充目標矩形。 |
CAPTUREBLT |
用調色盤中索引為0的顏色(預設是黑色)填充目標矩形。 |
DSTINVERT |
將目標矩形反色。 |
MERGECOPY |
將源矩形中的顏色與當前目標裝置環境選中的畫刷通過邏輯與操作進行混合。 |
MERGEPAINT |
將源矩形的顏色反色後與目標矩形的顏色通過邏輯或操作進行混合。 |
NOMIRRORBITMAP |
防止點陣圖映象翻轉。 |
NOTSRCCOPY |
源矩形反色複製到目標矩形。 |
NOTSRCERASE |
將源矩形與目標矩形的顏色通過邏輯或操作混合後,再反色。 |
PATCOPY |
將目標裝置環境選中的畫刷複製到目標點陣圖。 |
PATINVERT |
將目標裝置環境選中的畫刷與目標矩形中的顏色進行邏輯異或操作,複製到目標點陣圖。 |
PATPAINT |
將目標裝置環境選中的畫刷與源矩形中的顏色的反色進行邏輯或操作,其結果再與目標矩形的顏色進行邏輯或操作。 |
SRCAND |
將源矩形與目標矩形的顏色進行邏輯與操作。 |
SRCCOPY |
直接將源矩形拷貝到目標矩形,最常用的繪製點陣圖屬性。 |
SRCERASE |
將目標矩形的反色與源矩形的顏色進行邏輯與操作。 |
SRCINVERT |
將源矩形的顏色與目標矩形進行邏輯異或操作。 |
SRCPAINT |
將源矩形的顏色與目標矩形進行邏輯或操作。 |
WHITENESS |
用調色盤中索引為1的顏色(預設是白色)填充目標矩形。 |
下面是整個實現過程:
1) 建立一張大小與需要繪製圖像相同的點陣圖作為“掩碼”點陣圖(maskBmp);
2) 將新建立的“掩碼”點陣圖儲存至掩碼點陣圖的裝置描述表(maskDC)中;
3) 把記憶體裝置描述表(memDC)的背景設定成“透明色”(SetBkColor(RGB(?, ?, ?))),即不需要顯示的顏色;
4) 複製貼上點陣圖到“掩碼”點陣圖的裝置描述表中,這個時候“掩碼”點陣圖裝置描述表中存放的點陣圖與點陣圖裝置描述表中的點陣圖一樣 (maskDC.BitBlt(……)) ,此時會進行掩碼運算,體現掩碼特性,即:與設定的背景設相同的為體現出白色,不同的體現出黑色。(下面會詳細說明過程)。
5) 將記憶體DC裡的圖片與實際視窗背景顏色(設為白色)做邏輯異或(關鍵詞:SRCINVERT)操作並在實際視窗中呈像;
6)將掩碼DC的圖與實際視窗背景顏色做邏輯與(關鍵字:SRCAND)操作,並在視窗中呈像;
7)重複第五步。
下面進行演示:
首先我們要貼上的圖片是如下的一張圖(即黑色背景紅色方塊):
我們要將它的背景透明,然後顯示在視窗上。
說明:
圖片寬度定義為 const int BMPWIDTH = 182,
高度定義為 const int BMPHEIGHT =172;
第一步:建立一張掩碼圖,程式碼如下:
CBitmap maskBmp;
maskBmp.CreateBitmap(BMPWIDTH, BMPHEIGHT, 1, 1,NULL);
CreateBitmap函式說明:
引數1 nWidth: 指定點陣圖寬度、單位為畫素。
引數2 nHeight: 指定點陣圖高度、單位為畫素。
引數3 CPlanes: 指定該裝置使用的顏色位面數目。
引數4 CBitsPerPel: 指定用來區分單個畫素點顏色的位數(位元數目)。
引數5 LpvBits: 指向顏色資料陣列指標。這些顏色資料用來設定矩形區域內畫素的顏色。矩形區域中的每一掃描線必須是雙位元組的整數倍(不足部分以0填充)。如果該引數為NULL,將不對新生成的點陣圖進行初始化。
第二步:將建立的掩碼點陣圖選進掩碼點陣圖的裝置描述表中
如下:
CDC maskDC; <span style="white-space:pre"> </span> //定義掩碼DC
maskDC.CreateCompatibleDC(NULL); <span style="white-space:pre"> </span>//初始化裝置DC
CBitmap *oldMaskBmp = maskDC.SelectObject(&maskBmp); //將掩碼點陣圖存入,並返回舊的點陣圖
第三步:將記憶體裝置描述表的背景色設定為透明色(即要實現透明的背景色,如本例子為黑色)
CBitmap bmpSquare; <span style="white-space:pre"> </span>//定義一個CBitmap物件儲存將要繪製的圖(ID為IDC_SQUARE)
bmpSquare.LoadBitmap(IDC_SQUARE); //載入點陣圖
CDC memDC; <span style="white-space:pre"> </span>//建立記憶體DC
memDC.CreateCompatibleDC(NULL); //初始化DC
CBitmap *oldMemBmp = memDC.SelectObject(&bmpSquare); //將點陣圖存入記憶體DC中,並返回舊的點陣圖
memDC.SetBkColor(RGB(0,0,0)); <span style="white-space:pre"> </span> //將記憶體DC的背景色設定為黑色
第四步:將記憶體DC的點陣圖在掩碼DC中呈像
maskDC.BitBlt(0, 0, BMPWIDTH, BMPHEIGHT, &memDC, 0,0, SRCCOPY);
說明:
memDC中圖為(黑色底紅色方塊): + memDC背景色(全黑): = 掩碼計算後(白色底黑色方塊):.
現在maskDC中的圖即為 :.... (白底黑方塊)
第五步:將記憶體DC裡的圖片與實際視窗背景顏色(設為白色)做邏輯異或(關鍵詞:SRCINVERT)操作並在實際視窗中呈像;如下:
CPanitDC dc(this); //視窗DC
dc.BitBlt(0, 0, BMPWIDTH, BMPHEIGHT, &memDC, 0, 0,SRCINVERT);
說明:
memDC中圖為(黑色底紅色方塊): + 視窗背景色(全白): = 異或操作後(白底藍綠色方塊): .
邏輯說明:
memDC背景(黑)其RGB為: 0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0
視窗背景(白)為: 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1
異或操作(相同為0不同為1): 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1(白色)
------------------------------------------------------------------------------------------------------------------------------
memDC方塊(紅)為: 1 1 1 1 1 1 1 1,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0
視窗背景(白)為: 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1
異或操作結果: 0 0 0 0 0 0 0 0,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1(藍綠色)
第六步:將掩碼DC的圖與實際視窗背景顏色做邏輯與(關鍵字:SRCAND)操作,並在視窗中呈像;如下:
dc.BitBlt(0, 0, BMPWIDTH, BMPHEIGHT, &maskDC, 0, 0,SRCAND);
說明:
maskDC中圖為(白底黑方塊): + 視窗背景色(白底藍綠色方塊): = 異或操作後(白底黑方塊): .
此時在繪圖區域的背景圖為........ (白色背景黑色方塊)
邏輯說明:
maskDC背景(白)其RGB為: 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1
視窗背景(白)為: 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1
與操作(1,1為1,其他為0): 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1(白色)
---------------------------------------------------------------------------------------------------------------------------
maskDC方塊(黑)為: 0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0
視窗背景(藍綠)為: 0 0 0 0 0 0 0 0,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1
邏輯與操作結果: 0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0(黑色)
第七步:也是最後一步,重複第五步,也就是將記憶體DC裡的圖片與實際視窗背景顏色(設為白色)做邏輯異或(關鍵詞:SRCINVERT)操作並在實際視窗中呈像;如下:
dc.BitBlt(0, 0, BMPWIDTH, BMPHEIGHT, &memDC, 0, 0,SRCINVERT);
說明:
memDC中圖為(黑底紅方塊): + 視窗背景色(白底黑方塊): = 異或操作後(白底紅方塊): .
邏輯說明:
memDC背景(黑)其RGB為: 0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0
視窗背景(白)為: 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1
異或操作(相同為0不同為1): 1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1,1 1 1 1 1 1 1 1(白色)
-------------------------------------------------------------------------------------------------------------------------------
memDC方塊(紅)為: 1 1 1 1 1 1 1 1,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0
視窗背景(黑)為: 0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0
異或操作結果: 1 1 1 1 1 1 1 1,0 0 0 0 0 0 0 0,0 0 0 0 0 0 0 0(紅色)
此時的方塊背景色白色即與整個視窗背景色相同,也就是說我們實現了透明顯示點陣圖哈。
最後,別忘記把改釋放的資源釋放!
如:
maskDC.SelectObject(oldMaskBmp);
memDC.SelectObject(oldMemBmp);
memDC.DeleteDC();