图片都是以四方格储存的,如果要把他贴到背景图上,就会这样:
可是对于LoadImage()是不支持png这类带有透明通道的图片的,如果不用其他的库,如GDI+,怎么实现背景透明呢?
原理如下:
我们使用一个贴图来去掉黑色背景
左边是 要去背并且贴到背景上的前景图,右边黑边称之为屏蔽图,在透明过程会用到他。
- 将屏蔽图于背景图做 “AND” 运算,贴到目标DC中
- 将上一步处理后的图片和前景图做 “OR”运算,贴到目的地DC中。
为什么这两步就能产生透明呢,来阐述一下究竟发生了什么:
and运算是两数都为1,即为1,其他都是0:1&1=1; 1&0=0; 0&1=0; 0&0=0;
屏蔽图黑色部分与背景彩色部分and运算后都变成黑的。
屏蔽图白色部分和背景图彩色部分and后还是彩的。
第一步效果如下:
步骤2:or运算:0&0=0、0&1=1、1&0=1、1&1=1
效果如下:
代码如下:
void MyPaint(HDC hdc)
{
SelectObject(mdc, hbmp);
BitBlt(hdc, 0, 0, 600, 450, mdc, 0, 0, SRCCOPY); //显示背景图
SelectObject(mdc, bg);
BitBlt(hdc, 50, 50, 85, 99, mdc, 85, 0, SRCAND); //SRCAND为AND运算
BitBlt(hdc, 50, 50, 85, 99, mdc, 0, 0, SRCPAINT); //SRCPAINT为OR运算
}
BOOL InitInstance(HINSTANCE hinstance)
{
HWND hwnd;
HDC hdc;
if (!(hwnd = CreateWindowEx(NULL,
"WINCLASS1", //winclass.lpszClassName设置的字符,是类的别名。
"YouWindows", //窗口的名称
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //一些窗口属性
0, 0, //窗口位置
600, 450, //窗口宽高
NULL, //父窗口句柄
NULL, //附属窗口句柄
hinstance, //WinMain第一个实参,程序句柄。
NULL //null就可以了
)))
return false;
//上边是窗口函数,无关
hdc = GetDC(hwnd);
mdc = CreateCompatibleDC(hdc);
hbmp = (HBITMAP)LoadImage(NULL, "无标题.bmp", IMAGE_BITMAP, 600, 450, LR_LOADFROMFILE); //载入背景图
bg = (HBITMAP)LoadImage(NULL, "1333765851_1860.bmp", IMAGE_BITMAP, 170, 99, LR_LOADFROMFILE); //载入前景图和屏蔽图,他们是一张。
MyPaint(hdc);
ReleaseDC(hwnd, hdc);
return true;
}
注意!以上代码屏蔽图和前景图是一张,只是用了两个不同的位置载入而已。
BitBlt(hdc, 50, 50, 85, 99, mdc, 85, 0, SRCAND); //屏蔽图x轴85像素做AND运算
BitBlt(hdc, 50, 50, 85, 99, mdc, 0, 0, SRCPAINT); //前景图在x轴0像素开始做OR运算
效果如下: