MFC加载PNG图片并实现双缓冲

时间:2022-09-10 10:09:00

因为PNG包含Alpha通道,所以不同于BITMAP,在MFC中使用CImage类对其进行处理,通常使用load和draw成员函数。

所以标题的论述可以进一步解释为,使用CImage实现双缓冲。

通常的双缓冲方法为(首先将消息函数afx_msg BOOL OnEraseBkgnd(CDC* pDC)的函数体改为return TRUE):

CDC memDC;						
CBitmap bmp;				
bmp.CreateCompatibleBitmap(pDC,WINDOW_WIDTH,WINDOW_HEIGHT);
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(&bmp);

// 绘图代码

bmp.DeleteObject();
memDC.DeleteDC();

CImage可以通过Load成员函数加载图片,然后通过Draw成员函数将图片绘制到DC上。

Draw成员函数的原型为Bool Draw(HDC hDestDC, ...),它也需要获取指定DC,但是如果将图片一张一张绘制到DC上的话,就会产生闪烁。

因为双缓冲的思想就是--将图先绘制好,然后统一拷贝过去。

所以,解决方案就是将所有的图片都贴在同一个CImage对象上,然后统一再调用Draw成员函数绘制到DC上(如果除了图片还有其他绘制操作的话,此处DC应为memDC)。以下函数,是将图片全部先绘制到一张图片上:

void CRepairClientDlg::ShowImg(CImage &image, int x, int y)
{
	image.Draw(m_cScreen.GetDC(), x, y);// m_cSreen为一个CImage对象
	m_cScreen.ReleaseDC();
}

 

另:加载透明图片的函数如下:

void CRepairClientDlg::LoadImg(CImage &image, CString &strPath)
{
	image.Load(strPath);

	if (image.IsNull()) {
		MessageBox(_T("图片未加载成功!"));
		return;
	}

	// 判断是否需要透明显示,并做相应处理
	if (image.GetBPP() == 32) {
		for (int i = 0; i < image.GetWidth(); ++i) {
			for (int j = 0; j < image.GetHeight(); ++j) {
				byte *pByte = (byte *)image.GetPixelAddress(i, j);
				pByte[0] = pByte[0] * pByte[3] / 255;
				pByte[1] = pByte[1] * pByte[3] / 255;
				pByte[2] = pByte[2] * pByte[3] / 255;
			}
		}
	}
}