1:本文是使用的是 Gdi 的cImage 加载png
2:首先加载函数如下:
bool CPNGDialogRegionDlg::LoadImageFromResource( CImage* pImage, UINT nResID, LPCWSTR lpTyp )
{
if (pImage == NULL) return false;
pImage->Destroy();
// 查找资源
HRSRC hRsrc = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(nResID), lpTyp);
if (hRsrc == NULL) return false;
// 加载资源
HGLOBAL hImgData = ::LoadResource(AfxGetResourceHandle(), hRsrc);
if (hImgData == NULL)
{
::FreeResource(hImgData);
return false;
}
// 锁定内存中的指定资源
LPVOID lpVoid = ::LockResource(hImgData);
LPSTREAM pStream = NULL;
DWORD dwSize = ::SizeofResource(AfxGetResourceHandle(), hRsrc);
HGLOBAL hNew = ::GlobalAlloc(GHND, dwSize);
LPBYTE lpByte = (LPBYTE)::GlobalLock(hNew);
::memcpy(lpByte, lpVoid, dwSize);
// 解除内存中的指定资源
::GlobalUnlock(hNew);
// 从指定内存创建流对象
HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &pStream);
if ( ht != S_OK )
{
GlobalFree(hNew);
}
else
{
// 加载图片
pImage->Load(pStream);
GlobalFree(hNew);
}
// 释放资源
::FreeResource(hImgData);
// 像素转换,由于CImage 中没有对alpha 进行处理
for( int row = 0; row < pImage->GetWidth(); row++ )
{
for( int col = 0; col < pImage->GetHeight(); col++ )
{
UCHAR* cr = (UCHAR*) pImage->GetPixelAddress(row, col);
cr[0] = cr[0] * cr[3] / 255;
cr[1] = cr[1] * cr[3] / 255;
cr[2] = cr[2] * cr[3] / 255;
}
}
return true;
}
3:根据png 裁剪掉透明的区域
void CPNGDialogRegionDlg::CreateRgnByImage( CImage* pImage, CRgn &rgn )
{
rgn.CreateRectRgn(0, 0, 0, 0);
CRgn tempRgn;
for (UINT h = 0; h < (UINT)pImage->GetHeight(); ++ h)
{
UINT w = 0;
while(w < (UINT)m_ImageBg.GetWidth())
{
UINT leftX = w;
while (w < (UINT)m_ImageBg.GetWidth() )
{
UCHAR* cr = (UCHAR*) pImage->GetPixelAddress(w, h);
if( cr[3] != 0 )
break;
leftX = w;
w++;
}
while (w < (UINT)m_ImageBg.GetWidth() )
{
UCHAR* cr = (UCHAR*) pImage->GetPixelAddress(w, h);
if( cr[3] == 0 )
break;
w++;
}
tempRgn.CreateRectRgn(leftX, h, w - 1, h + 1);
rgn.CombineRgn(&rgn, &tempRgn, RGN_OR);
tempRgn.DeleteObject();
}
}
}
4:在CPNGDialogRegionDlg::OnInitDialog() 函数中:
// TODO: 在此添加额外的初始化代码
int width = 1024;
int height= 768;
CRgn rgn;
//CreateRgnByImage( IDB_BITMAP_BACKGROUND, rgn, width, height );
LoadImageFromResource(&m_ImageBg, IDB_PNG_BACKGROUND, _TEXT("RCPNG"));
width = m_ImageBg.GetWidth();
height = m_ImageBg.GetHeight();
CreateRgnByImage( &m_ImageBg, rgn );
CRect rc;
GetWindowRect(&rc);
int nScreenWidth = GetSystemMetrics( SM_CXFULLSCREEN );
int nScreenHeight = GetSystemMetrics( SM_CYFULLSCREEN );
if( nScreenWidth > width )
rc.left = (nScreenWidth-width)/2;
if( nScreenHeight > height )
rc.top = (nScreenHeight-height)/2;
rc.right = rc.left + width;
rc.bottom = rc.top + height;
MoveWindow(&rc);
SetWindowRgn(rgn, TRUE);
4:在OnEraseBkgnd(CDC* pDC) 是显示,并且背景透明模式
BOOL CPNGDialogRegionDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_ImageBg.AlphaBlend(pDC->GetSafeHdc(),0,0);
pDC->SetBkMode( TRANSPARENT );
//return CDialog::OnEraseBkgnd(pDC);
return TRUE;
}
按上面的4个步骤即可用png 做不规则的窗体了