在 Windows 中,TransparentBlt 是一种用于创建透明位图复制的函数。它可以让我们在复制位图时,去除原来图片中的某些部分,使其透明化。本文将围绕 TransparentBlt,为大家详细介绍如何在 Windows 中创建透明的位图复制。
一、TransparentBlt 的参数
在使用 TransparentBlt 函数之前,我们需要先了解它的参数。TransparentBlt 函数一共有 7 个参数,分别是:
1. hdcDest:目标设备上下文句柄,即复制图像的目标位置。
2. xoriginDest 和 yoriginDest:目标复制区的坐标,表示将图像复制到目标设备上的哪个位置。
3. wDest 和 hDest:目标复制区的宽度和高度,表示将图像在目标设备上要复制的区域大小。
4. hdcSrc:源设备上下文句柄,即要复制的源图像。
5. xoriginSrc 和 yoriginSrc:源图像的坐标,表示从源图像的哪个位置开始复制。
6. wSrc 和 hSrc:源图像的宽度和高度,表示要复制的源图像大小。
7. crTransparent:指定透明的颜色值,即在复制图片时哪些部分要去除成透明,如不需要去除颜色部分,可以指定为 0。
了解这些参数后,我们就可以开始使用 TransparentBlt 函数进行位图复制,并创建透明化效果。
二、创建透明的位图复制
在创建透明的位图复制时,我们需要先准备好两张位图。一张原图,一张目标图。
- 1. 准备原图
我们先来看一下如何准备原图。实现原图的透明化,我们需要把要透明化的颜色转化为 Windows 中的透明颜色,在图片复制时,以该颜色将源图透明化。Windows 中常用的透明颜色是 0x00FFFFFF,它代表的是 ARGB 中的白色。如果我们需要透明化的颜色不是白色,可以通过代码动态获取。
下面是获取一个具有透明背景的位图的示例:
```C++
// 定义位图信息头结构体
BITMAPINFO bmpInfo = {0};
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = nBmpWidth;
bmpInfo.bmiHeader.biHeight = -nBmpHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
// 加载位图
HDC hdc = GetDC(NULL);
HBITMAP hBmp = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, (void**)&m_pBits, NULL, NULL);
SelectObject(m_hDC, hBmp);
// 设置透明颜色为白色
m_colorTrans = RGB(255, 255, 255);
for (int i = 0; i < nBmpWidth * nBmpHeight; ++i)
{
if (*(DWORD*)&m_pBits[i] == m_colorTrans)
{
m_pBits[i] = 0;
}
}
ReleaseDC(NULL, hdc);
```
这个代码中,我们先定义了一个位图信息头结构体,使用 CreateDIBSection 函数加载位图并在 m_pBits 中存储像素点数据,接着我们将需要透明化的颜色通过函数 RGB 转化为透明颜色 0x00FFFFFF。我们通过遍历 m_pBits 来找到需要透明化的颜色,将它的数值置为 0。
- 2. 准备目标图
接着,我们来看一下如何准备目标图。弄清楚目标图的大小和位置,以及准备好目标图所在的设备上下文 hdcDest。
```C++
// 创建位图
HDC hdcScreen = ::GetDC(NULL);
m_hBmpTarget = CreateCompatibleBitmap(hdcScreen, nTargetWidth, nTargetHeight);
// 准备设备上下文
m_hDCMem = CreateCompatibleDC(hdcScreen);
SelectObject(m_hDCMem, m_hBmpTarget);
// 指定目标图在屏幕上的位置
m_x = nTargetX;
m_y = nTargetY;
m_w = nTargetWidth;
m_h = nTargetHeight;
// 释放 hdcScreen
::ReleaseDC(NULL, hdcScreen);
```
创建位图的过程中,我们调用了 CreateCompatibleBitmap 函数来创建一个纯色矩形的位图,接着获得它的设备上下文从而得到 hdcDest。
同时,我们需要指定目标图在屏幕上的位置,即 m_x、m_y,以及目标图的宽高,即 m_w、m_h。这些参数可以在传递给 TransparentBlt 函数时使用。
- 3. 复制图像
现在我们已经准备好了两张位图,可以开始进行透明的位图复制了。我们使用 TransparentBlt 函数实现复制,调用方式如下:
```C++
TransparentBlt(hdcDest, xoriginDest, yoriginDest, wDest, hDest, hdcSrc, xoriginSrc, yoriginSrc, crTransparent);
```
其中的 hdcDest 表示目标设备上下文的句柄,即目标图的设备上下文;xoriginDest 和 yoriginDest 表示目标复制区的坐标,即目标图的位置;wDest 和 hDest 表示目标复制区的宽度和高度;hdcSrc 表示源设备上下文的句柄,即我们需要复制的原图的设备上下文;xoriginSrc 和 yoriginSrc 表示源图像的起始坐标,即我们需要复制的原图的起始坐标;crTransparent 表示需要透明化的颜色,我们前面已经将需要透明化的颜色设置成了白色。
下面是具体的代码实现:
```C++
bool CTransparentDlg::TransparentCopy(HDC hdcTarget, HDC hdcSrc, int x, int y, int w, int h, COLORREF colorTrans)
{
// 创建临时 DC
HDC hdcMem = CreateCompatibleDC(hdcTarget);
if (hdcMem == NULL)
{
return false;
}
// 创建临时位图
HBITMAP hBmpTmp = CreateCompatibleBitmap(hdcTarget, w, h);
if (hBmpTmp == NULL)
{
DeleteDC(hdcMem);
return false;
}
// 选择位图句柄
HBITMAP hBmpOld = (HBITMAP)SelectObject(hdcMem, hBmpTmp);
// 复制图片
BitBlt(hdcMem, 0, 0, w, h, hdcSrc, x, y, SRCCOPY);
// 将需要透明化的部分置成透明,使用 SetBkColor 实现
COLORREF oldColor = SetBkColor(hdcMem, colorTrans);
BitBlt(hdcTarget, m_x, m_y, m_w, m_h, hdcMem, 0, 0, SRCAND);
// 将图片复制到目标位置,使用 SRCPAINT 实现
SetBkColor(hdcMem, RGB(255, 255, 255));
BitBlt(hdcTarget, m_x, m_y, m_w, m_h, hdcMem, 0, 0, SRCPAINT);
// 恢复之前的画笔、位图句柄等
SetBkColor(hdcMem, oldColor);
SelectObject(hdcMem, hBmpOld);
DeleteObject(hBmpTmp);
DeleteDC(hdcMem);
return true;
}
```
这个函数中,我们先创建了一个临时的设备上下文 hdcMem,接着创建了一个与 hdcMem 兼容的临时位图 hBmpTmp,并将其句柄与 hdcMem 关联起来。然后使用 BitBlt 函数将需要复制的原图复制到临时位图中。
需要进行透明化的部分,我们使用 SetBkColor 函数将透明部分填充成需要透明化的颜色,然后再用 BitBlt 函数将透明部分置为透明(RGB(0, 0, 0))。
接着,我们将复制好的位图复制到目标位置,这里我们先使用 SETAND 实现透明部分的清除,再使用 SRCPAINT 实现复制。
最后,我们恢复画笔、位图句柄等,并返回复制是否成功的结果。
三、总结
在 Windows 中,使用 TransparentBlt 函数可以帮助我们在位图复制时实现透明化的效果。我们需要先确定好原图和目标图的大小和位置,并设置需要透明化的颜色,然后使用 BitBlt 函数将原图复制到临时位图中,使用 SetBkColor 函数将需要透明化的部分置成透明,最后将复制好的位图复制到目标位置,创建透明的位图复制。