因为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; } } } }