TransparentBlt
TransparentBlt是一个Windows API函数,可在绘图时进行透明处理。它的函数声明如下:
BOOL TransparentBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, UINT crTransparent);
参数说明如下:
hdcDest:目标设备的句柄
nXDest:目标图像的左上角的x坐标
nYDest:目标图像的左上角的y坐标
nWidth:目标图像的宽度
nHeight:目标图像的高度
hdcSrc:源设备的句柄
nXSrc:源图像的左上角的x坐标
nYSrc:源图像的左上角的y坐标
crTransparent:指定透明颜色值
透明效果是通过指定crTransparent参数来实现的。在目标设备中,所有像素颜色与crTransparent参数指定的颜色相同的像素都不进行绘制,将变成透明的,这使得在绘制透明图像时非常方便。
HDC hdc = GetDC(hwnd); // 获取窗口设备的句柄
HDC hMemDC = CreateCompatibleDC(hdc); // 创建兼容的内存设备上下文
HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MYBITMAP)); // 加载位图资源
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); // 将位图对象选入内存设备上下文
// 调用TransparentBlt进行绘制,RGB(255, 0, 255)为透明颜色
TransparentBlt(hdc, 0, 0, 200, 200, hMemDC, 0, 0, RGB(255, 0, 255));
SelectObject(hMemDC, hOldBitmap); // 恢复上一个位图对象
DeleteObject(hBitmap); // 删除位图对象
DeleteDC(hMemDC); // 删除设备上下文
ReleaseDC(hwnd, hdc); // 释放设备上下文
根据我的经验,绘制的图形最好是BMP这种无损格式的位图,如果是jpg等有损压缩的图片,透明效果不会很好,因为压缩后的图片边缘变成这种模糊的像素颜色,而TransparentBlt只会保留这些模糊的像素颜色

Gdiplus
jpg、bmp格式的图片没有透明度信息,而png有,可以通过gdiplus实现绘制png图片,实现透明效果
GDI+是Windows平台上的一个高级绘图API,支持多种图像文件格式,包括PNG格式。下面是在GDI+中绘制PNG图像的基本步骤:
1.创建Gdiplus::Image对象,并使用图片文件的路径初始化该对象。
2.创建Gdiplus::Graphics对象,并使用绘图设备的句柄初始化该对象。
3.调用Gdiplus::Graphics对象的DrawImage函数,将Gdiplus::Image对象绘制到绘图设备上。
4.释放Gdiplus::Image和Gdiplus::Graphics对象。
#include <windows.h>
#include <gdiplus.h>
#pragma comment (lib,"Gdiplus.lib")
using namespace Gdiplus;
int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HDC hdc = ::GetDC(NULL);
Graphics graphics(hdc);
Image image(L"path to your png file");
graphics.DrawImage(&image, 0, 0);
::ReleaseDC(NULL, hdc);
GdiplusShutdown(gdiplusToken);
return 0;
}
在上面的示例代码中,首先调用GdiplusStartup函数初始化GDI+库,然后创建一个图形设备上下文(Graphics对象),并调用DrawImage函数将PNG图像绘制在屏幕上。最后调用GdiplusShutdown函数释放GDI+库所占用的资源。
需要注意的是,在使用GDI+库之前,需要在代码中包含头文件<gdiplus.h>,并在链接时将gdiplus.lib库文件添加到工程中。
半透明的公式
可以通过获取图像缓冲区像素,直接对像素进行透明和半透明操作
如果是图片a和屏幕b的像素,alpha是指定的透明度,混合后c的颜色RGB公式:
R(c)=(1-alpha)*R(b)+alpha*R(a)
G(c)=(1-alpha)*G(b)+alpha*G(a)
B(c)=(1-alpha)*B(b)+alpha*B(a)
将图片透明方式绘制到屏幕的伪代码如下
//获取透明度混合后的像素颜色
color get_transparent_color(color a,color b,float alpha){
color c
R(c)=(1-alpha)*R(b)+alpha*R(a)
G(c)=(1-alpha)*G(b)+alpha*G(a)
B(c)=(1-alpha)*B(b)+alpha*B(a)
return c
}
...
sbuffer = get_screen_buffer();//获取屏幕像素缓冲区
pbuffer = get_image_buffer();//获取图片像素指针
mbuffer = new color[sbuffer .size()];//混合后的像素空间
for(int i=0; i< sbuffer.sie();i++){//对于每个像素计算透明度混合后的颜色
mbuffer[i] = get_transparent_color(sbuffer[i],pbuffer[i],0.5);//透明度0.5
}
draw(mbuffer);//画透明混合后的图像
delete mbuffer[];