从Exe里面读取资源,给exe增加嵌入字体
来源:互联网 发布:破解linux系统root密码 编辑:程序博客网 时间:2024/06/06 05:01
把数据放到Exe文件里面有很多好处,理由也很多,比如:
- 隐藏数据,不想让用户看见。
- 数据太零散,小文件太多。
- 减少体积,提高加载速度等。
等等。这方面的例子也很多,就不细说了。我这里只说说将一类资源全部打包到一个压缩文件中,然后程序中读取的方法。
一个zip压缩包中,包含了大量的文件,并且还有多级目录,我们可以将整个资源全部提取出来,存入到一个内存文件(buffer)中。
从资源中提取数据到内存的方法很简单,代码如下:
bool LoadResToMemFile(unsigned int resid, const std::wstring res_type, MemFile* memfile)
{
bool ret = false;
HRSRC hResInfo = FindResource(m_hResource, MAKEINTRESOURCE(resid), res_type.c_str());
if (hResInfo)
{
HGLOBAL hResDat = LoadResource(m_hResource, hResInfo);
if (hResDat)
{
PVOID pResBuffer = LockResource(hResDat);
if (pResBuffer)
{
DWORD dwResBuffer = SizeofResource(m_hResource, hResInfo);
memfile->SetData(pResBuffer, dwResBuffer);
ret = true;
}
}
}
return ret;
}
在整个资源文件提取出来之后,需要将里面的每个文件都解析出来,并保存到一个映射表中,只有这样,才能保证在给出文件名称后,快速定位到该文件的内存。
这时需要定义好一个数据类型:
typedef std::pair<unsigned long, unsigned long> KResInfo;
typedef std::map<std::wstring, KResInfo> KResOffset;
KResInfo中的两个值,分别为偏移位置和文件长度。如果使用zip压缩的资源,使用下面的代码快速创建映射表:
m_pResPackData = unzOpen2((const char*)&m_memZipRes, &zip_funcs);
nRetCode = unzGoToFirstFile(m_pResPackData);
while (UNZ_OK == nRetCode)
{
char szCurrentFile[260];
unz_file_info fileInfo;
uLong dwSeekPos;
uLong dwSize;
nRetCode = unzGetCurrentFileInfo(
m_pResPackData,
&fileInfo,
szCurrentFile,
sizeof(szCurrentFile),
NULL,
0,
NULL,
0
);
if (nRetCode != UNZ_OK)
goto clean0;
dwSeekPos = unzGetOffset(m_pResPackData);
dwSize = fileInfo.uncompressed_size;
std::wstring filename = AnsiToUnicode(szCurrentFile, -1);
FormatFilePath(filename);
m_mapResOffset.insert(KResOffset::value_type(filename, KResInfo(dwSeekPos, dwSize)));
nRetCode = unzGoToNextFile(m_pResPackData);
}
unzClose(m_pResPackData);
映射表创建好之后,就可以快速的从里面取出一段文件的buffer内容了:
bool GetDataFromRes(
const std::wstring& filepath,
void** ppBuffer,
unsigned long& dwSize
)
{
bool retval = false;
KResOffset::iterator offset;
unsigned long dwOffset;
int nRetCode;
if (!ppBuffer)
return false;
std::wstring filename = filepath;
FormatFilePath(filename);
offset = m_mapResOffset.find(filename);
if (offset == m_mapResOffset.end())
return false;
dwOffset = offset->second.first;
dwSize = offset->second.second;
*ppBuffer = new unsigned char[dwSize + 4];
if (!*ppBuffer)
return false;
memset(*ppBuffer, 0, dwSize + 4);
nRetCode = unzSetOffset(m_pResPackData, dwOffset);
if (nRetCode == UNZ_OK)
{
nRetCode = unzOpenCurrentFile(m_pResPackData);
if (nRetCode == UNZ_OK)
{
nRetCode = unzReadCurrentFile(m_pResPackData, *ppBuffer, dwSize);
if (0 != nRetCode)
retval = true;
}
}
if (!retval)
{
if (ppBuffer)
{
if (*ppBuffer)
{
delete[] (*ppBuffer);
*ppBuffer = NULL;
}
}
}
return retval;
}
这个里面要注意的是,内存需要由外部释放。对于zip压缩程序来说,它里面使用的文件名全部是“/”,而windows里面文件名为“\”,因此需要做转换,这个转换函数就是:
void FormatFilePath(std::wstring & filepath)
{
int len = filepath.length();
for(int i=0; i<len; i++)
{
if (filepath[i] == L'/')
filepath[i] = L'\\';
}
}
好了,以上的代码就可以完成内嵌文件的释放,比如我们要完成一个内嵌字体,增加以下代码就可以了:
void LoadFontFile(const std::wstring & file)
{
std::wstring fullName = GetResourceRootPath() + L"/" + file;
if (GetFileAttributes(fullName.c_str()) != INVALID_FILE_ATTRIBUTES)
{
AddFontResourceExW(fullName.c_str(), FR_PRIVATE, 0);
}
else
{
void * buf = NULL;
unsigned long bufSize = 0;
if (GetRawDataFromRes(file, &buf, bufSize))
{
DWORD dw = 0;
HANDLE hFont = AddFontMemResourceEx(buf, bufSize, 0, &dw);
FreeRawData(buf);
}
}
}
- 从Exe里面读取资源,给exe增加嵌入字体
- C# 嵌入exe资源
- C#如何更新EXE中和嵌入资源
- 给C#程序加壳(C# 调用嵌入资源的EXE文件方法)
- 把资源打包在exe里面
- 获取exe和dll里面的资源
- VC从EXE中提取资源文件
- form窗口嵌入EXE
- [VS]dll嵌入exe
- 把exe里面的资源通通取出来
- 把exe里面的资源通通取出来
- VC 给控制台exe 增加版本信息,图标
- exe程序嵌入Winform窗体
- winform嵌入外部exe文件
- Dll嵌入到exe中
- winform 嵌入 外部 exe窗体
- 从res资源中运行exe,不用释放出来
- 从EXE文件中提取音乐、图片等资源
- 给TableView增加SearchBar
- Android教程:LayerDrawable层叠样式layer-list
- org.hibernate.MappingException: No Dialect mapping for JDBC type:
- UIMenuController的使用,对UILabel拷贝以及定制菜单
- 快速选择(quick_select) 算法分析
- 从Exe里面读取资源,给exe增加嵌入字体
- 在服务器上用Fiddler抓取HTTPS流量
- Azure最佳实践(一)
- HandlerThread,Handler,Thread使用方法
- String,CString,TCHAR*,char*之间区别和联系
- 少走弯路的10条忠告
- windows-IOCP模型总结
- 客户端执行Sql的方法
- [乐意黎原创] PHP文件包含语句 include、include_once、require、require_once的区别