对于rc资源中常见的类型:BITMAP、CURSOR和ICON,可以用LoadBitmap、LoadCursor和LoadIcon将它们加载到内存中,或者统一使用LoadImage

API函数也可以。但是对于自定义类型的PNG、ZIP(在添加文件到资源中时会提示设定资源类型),则没有专门的函数来使用。LoadImage仅仅是支持BITMAP、CURSOR和ICON三种类型。

那应该如何将自定义类型的资源文件从rc资源加载到内存中或者导出呢?对于自定义类型的对象,可以使用FindResource、LoadResource、LockResource和SizeofResource等API函数来处理。大致的处理流程如下:

首先

先调用FindResource,根据资源ID和资源类型(注意:这个资源类型就是在资源中添加文件时提示输入的资源类型标识串,比如下面代码中的“PNG”和“ZIP”),找到资源信息块句柄;然后将句柄传给LoadResource去加载资源,将资源加载到全局内存中,注意此时不能直接操作返回的内存句柄;调用LockResource将资源数据锁住后再使用内存中的数据,进而可以进行资源的数据的拷贝或导出操作了;可以调用SizeofResource得到资源文件的大小。

然后

当然在事务处理完之后,要调用UnlockResource解锁,最后调用FreeResource将调用LoadResource申请的内存释放掉。

将PNG图片读出到CImage对象中

为了说明相关函数的使用方法,下面给出从rc资源加载到内存中或者导出的例子代码。

由于PNG图片可以做到很多透明效果,界面用PNG后效果非常好,所以现在很多软件都会使用到。PNG图片在高版本的VS中都使用CImage类来加载,相关代码如下所示:(代码中的lpszType为“PNG”)CImage* CImageUtility::LoadCImage(UINT nID, LPCTSTR lpszType, HINSTANCE hInstance)

{

CImage* pImage = NULL;

// 兼容bmp的加载

if (RT_BITMAP == lpszType)

{

pImage = new CImage();

pImage->LoadFromResource(hInstance, nID);

if (!pImage->IsNull())

{

return pImage;

}

else

{

delete pImage;

pImage = NULL;

return pImage;

}

}

CString strLog;

HRSRC hRsrc = ::FindResource(hInstance, MAKEINTRESOURCE(nID), lpszType);

ASSERT(hRsrc != NULL);

if (NULL == hRsrc)

{

return NULL;

}

DWORD dwSize = ::SizeofResource(hInstance, hRsrc);

LPBYTE lpRsrc = (LPBYTE)::LoadResource(hInstance, hRsrc);

ASSERT(lpRsrc != NULL);

if (NULL == hRsrc)

{

return NULL;

}

// 后面采用流加载的方式使用到了CreateStreamOnHGlobal,它需要使用HGLOBAL内存

HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, dwSize);

if (NULL == hMem)

{

::FreeResource(lpRsrc);

return NULL;

}

LPBYTE pMem = (LPBYTE)::GlobalLock(hMem);

if (NULL == pMem)

{

::GlobalUnlock(hMem);

::GlobalFree(hMem);

::FreeResource(lpRsrc);

return NULL;

}

memcpy(pMem, lpRsrc, dwSize);

IStream * pStream = NULL;

HRESULT hr = ::CreateStreamOnHGlobal(hMem, FALSE, &pStream);

if (pStream != NULL && hr == S_OK)

{

pImage = new CImage();

HRESULT hrs = pImage->Load(pStream);

pStream->Release();

// 释放资源

::GlobalUnlock(hMem);

::GlobalFree(hMem);

::FreeResource(lpRsrc);

if (hrs == S_OK)

{

// 处理图片中的透明效果

if (pImage->GetBPP() == 32)

{

for (int i = 0; i GetWidth(); i++)

{

for (int j = 0; j GetHeight(); j++)

{

unsigned char* pucColor = reinterpret_cast(pImage->GetPixelAddress(i, j));

pucColor[0] = pucColor[0] * pucColor[3] / 255;

pucColor[1] = pucColor[1] * pucColor[3] / 255;

pucColor[2] = pucColor[2] * pucColor[3] / 255;

}

}

}

return pImage;

}

else

{

delete pImage;

pImage = NULL;

return pImage;

}

}

else

{   // 释放资源

::GlobalUnlock(hMem);

::GlobalFree(hMem);

::FreeResource(lpRsrc);

return NULL;

}

}

将zip压缩文件导出到磁盘上

对于程序安装包来说,安装到目标安装路径的文件是要放到exe安装包中的,那怎样才能塞到安装包中呢?将相关的文件打包成zip文件,作为资源添加到资源列表中,启动安装的时候再从资源中取出来,释放到磁盘上在解压,然后执行文件的拷贝操作。从资源中导出文件的相关代码如下所示:void CProcessLogic::ExportResFile(CString strExportPath)

{

// 导出system.zip

CString strSysDir = strExportPath + _T("system.zip");

HRSRC hrSrcSys = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_ZIP_SYSDIR), _T("ZIP"));

HGLOBAL hGlobalSys = LoadResource(AfxGetResourceHandle(), hrSrcSys);

LPVOID lpGlobalSys = LockResource(hGlobalSys);

ret = 0;

if (ret = file.Open(strSysDir, CFile::modeCreate | CFile::modeWrite))

{

file.Write(lpGlobalSys, (UINT)SizeofResource(AfxGetResourceHandle(), hrSrcSys));

file.Close();

}

::UnlockResource(hGlobalSys);

::FreeResource(hGlobalSys);

}

至于怎么解压zip包,使用网上常用的unzip.cpp文件即可。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐