VC++图形化界面开发过程中,会需要用到很多的图片文件,部分人可能会直接通过向导直接把图像添加到项目中进行编译,这种方式加载会增加exe文件体积;部分有人可能会编写一个资源dll文件,把所有图片资源编译到dll中,通过加载dll来加载所需要的图片资源,这种方式缺点是每次修改图片,资源文件都需要重新编译一次;部分人会想到用压缩包文件,这样每次修改图片,只需要重新打包压缩包文件即可。在这里,我介绍的是第3种方式:
基于CZipImplement类扩展了一个接口:
//获取压缩文件数据
BOOL Zip_GetPackData(
LPCTSTR lpszZipFileFullPath, // zip压缩包文件名称
LPCTSTR lpszZipFileName, // zip压缩包内文件相对路径
char** ppBuffer, // 返回文件数据缓存
int& mSize) // 返回缓存大小
{
//参数错误
if ((lpszZipFileName == "") || (lpszZipFileFullPath == ""))
{
//路径异常返回
return FALSE ;
}
CFileFind fileFind;
if (!fileFind.FindFile(lpszZipFileFullPath))
{
//压缩失败(未发现压缩文件)
return FALSE;
}
//打开ZIP文件
m_zipHandle = OpenZip(lpszZipFileFullPath, 0/*加密密码*/); // 请采用zip传统加密方式
if(m_zipHandle == 0)
{
//打开Zip文件失败
return FALSE;
}
ZIPENTRY ze;
int i;
if ( ZR_OK == FindZipItem(m_zipHandle, lpszZipFileName, true, &i, &ze) )
{
if ( NULL == *ppBuffer )
*ppBuffer = new char[ze.unc_size];
UnzipItem(m_zipHandle, i, *ppBuffer, ze.unc_size);
mSize = ze.unc_size;
CloseZip(m_zipHandle);
return TRUE;
}
CloseZip(m_zipHandle);
return FALSE;
}
获取到压缩包内文件数据以后,我们只需要将其转换成所需要的Gdiplus::Image*图片即可:
Gdiplus::Image* GetZipPackageImage(
LPCTSTR lpszZipPackFileName,
LPCTSTR lpszFileName)
{
CZipImplement ZipImplement;
char* buffer = NULL;
int iSize = 0;
if ( ZipImplement.Zip_GetPackData(lpszZipPackFileName, lpszFileName, &buffer, iSize) )
{
IStream *stream = NULL;
HGLOBAL global = ::GlobalAlloc( GMEM_MOVEABLE, iSize );
if( global == NULL )
{
delete[] buffer;
buffer = NULL;
return NULL;
}
void *dest = ::GlobalLock( global );
if( dest == NULL )
{
delete[] buffer;
buffer = NULL;
return NULL;
}
memcpy( dest, buffer, iSize );
::GlobalUnlock( global );
if( ::CreateStreamOnHGlobal( global, TRUE, &stream ) != S_OK )
{
::GlobalFree( global );
delete[] buffer;
buffer = NULL;
return NULL;
}
Gdiplus::Bitmap *image = Gdiplus::Bitmap::FromStream( stream );
stream->Release();
delete[] buffer;
buffer = NULL;
return image;
}
delete[] buffer;
buffer = NULL;
return NULL;
}