今天跟大家伙儿聊聊我最近折腾的`TransparentBlt`,说起来这玩意儿,一开始我是真的一头雾水,各种参数看得我眼花缭乱。但是,硬着头皮啃下来,发现也没那么难,就是需要耐心和实践。
我接到个小任务,要在MFC程序里显示一张PNG图片,要求背景透明。这需求一听,感觉挺简单的,直接`BitBlt`不就完事?结果一跑,好家伙,PNG的透明部分直接变成黑色,瞬间懵逼。
赶紧上网查资料,这才知道,普通的`BitBlt`对透明色支持不得用`TransparentBlt`才行。找到这个函数,就像找到救星一样,赶紧研究。
- 我得加载PNG图片。用`CImage`类加载,这步没啥难度。
- 然后,创建兼容DC,把图片选进去。
- 就是`TransparentBlt`出场。
c++
CDC memDC;
*(pDC); // pDC是目标DC
CBitmap pOldBitmap = *(&m_image); // m_image是CImage对象
TransparentBlt(pDC->GetSafeHdc(), // 目标DC
10, 10, // 目标坐标
m_*(), // 目标宽度
m_*(), // 目标高度
*(), // 源DC
0, 0, // 源坐标
m_*(), // 源宽度
m_*(), // 源高度
RGB(255, 0, 255)); // 透明色,这里假设PNG的透明色是洋红色
这段代码跑起来,还是不行!背景还是黑的。我仔细检查一下,发现问题出在透明色的选择上。PNG图片的透明部分并不是纯粹的洋红色(RGB(255, 0, 255)),而是带有一些细微的颜色偏差。
解决透明色问题
这可咋办?难道要用PS把PNG图片的透明色改成纯洋红色?这也太麻烦! 后来我灵机一动,能不能用GetPixel函数获取图片某个像素的颜色,然后把这个颜色作为透明色传给TransparentBlt?
说干就干,我先获取图片左上角像素的颜色:
c++
COLORREF crTransparent = m_*(0, 0); // 获取左上角像素颜色
然后,把`TransparentBlt`的透明色参数改成`crTransparent`:
c++
TransparentBlt(pDC->GetSafeHdc(),
10, 10,
m_*(),
m_*(),
0, 0,
m_*(),
m_*(),
crTransparent); // 使用获取到的颜色作为透明色
再运行一下,Perfect!背景终于透明! 搞定收工!
`TransparentBlt`这玩意儿,关键在于搞清楚各个参数的含义,尤其是透明色的选择。如果图片透明色不固定,可以用`GetPixel`动态获取,这样就能灵活应对各种情况。