转载自:http://hi.baidu.com/doubleuto/item/36738fa14e1753a828ce9dc0
一般的操作都是引入资源,这个是把资源导出。暂且学习下,没有找到合适的应用场景。
#ifndef __LOADRES_H__
#define __LOADRES_H__
BOOL FreeSource_1(LPCTSTR pszResName,LPCTSTR pszResType,LPCTSTR szFileName)
{
BOOL bRet = TRUE;
HINSTANCE hInst = GetModuleHandle(NULL);
//判断指定的资源是否存在
HRSRC hResInfo = FindResource(hInst,pszResName,pszResType);
if(hResInfo == NULL)
return FALSE;
HANDLE hFile = NULL;
DWORD dwWritten = 0;
//调入指定的资源到内存
HGLOBAL hResData = LoadResource(hInst,hResInfo);
LPVOID pvResData = LockResource(hResData);
DWORD dwResSize = SizeofResource(hInst,hResInfo);
//创建目标文件并保存数据至文件
hFile = CreateFile(
szFileName,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_HIDDEN, NULL
);
WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);
//释放有关内存资源
CloseHandle(hFile);
FreeResource(hResData);
return TRUE;
}
/*
调用代码为:
FreeSource(MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP, "C:\\TEMP1.BMP");
FreeSource(MAKEINTRESOURCE(IDR_JPG1), "JPG", "C:\\TEMP2.JPG");
FreeSource(MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP, "C:\\TEMP1.BMP");
FreeSource(MAKEINTRESOURCE(IDR_JPG1), "JPG", "C:\\TEMP2.JPG");
奇怪的是,上述代码对自定义类型的资源,如GIF、JPEG甚至EXE都能正确释放,但对于BMP类型的却无能为力。虽然保存到了磁盘上,却无法打开,提示为格式错误!
于是,我又自作聪明地使用流技术,把内存中的图像数据写回磁盘,代码如下:
*/
BOOL FreeSource_2(LPCTSTR pszResName,LPCTSTR pszResType,LPCTSTR szFileName)
{
BOOL bRet = TRUE;
HINSTANCE hInst = GetModuleHandle(NULL);
//判断指定的资源是否存在
HRSRC hResInfo = FindResource(hInst,pszResName,pszResType);
if(hResInfo == NULL)return FALSE;
HANDLE hFile = NULL;
DWORD dwWritten = 0;
//直接保存自定义资源,如JPG、GIF、EXE等
if(pszResType != RT_BITMAP)
{
//使用LoadResource调入指定的资源到内存
HGLOBAL hResData = LoadResource(hInst,hResInfo);
LPVOID pvResData = LockResource(hResData);
DWORD dwResSize = SizeofResource(hInst,hResInfo);
//创建目标文件并保存数据至文件
hFile = CreateFile(
szFileName,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_HIDDEN,
NULL
);
WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);
//释放有关内存资源
CloseHandle(hFile);
FreeResource(hResData);
}
else //使用流技术保存BITMAP位图
{
//使用LoadBitmap调入指定的位图资源
HBITMAP hBitmap = LoadBitmap(hInst, pszResName);
if(hBitmap == NULL)return FALSE;
//创建一个IPicture接口的实例
PICTDESC ps;
IPicture* pIPic=NULL;
ps.cbSizeofstruct = sizeof(PICTDESC);
ps.picType = PICTYPE_BITMAP;
ps.bmp.hbitmap = hBitmap;
ps.bmp.hpal = NULL;
if(OleCreatePictureIndirect(&ps, IID_IPicture, TRUE,(LPVOID*)&pIPic) != ERROR_SUCCESS)
{
DeleteObject(hBitmap);
return FALSE;
}
//将IPicture接口实例中的数据写入流接口中
LONG lSize = 0;
IStream* pIStm = NULL;
CreateStreamOnHGlobal(NULL,TRUE,&pIStm);
if(pIPic->SaveAsFile(pIStm,TRUE,&lSize) != ERROR_SUCCESS)
{
pIPic->Release();
DeleteObject(hBitmap);
return FALSE;
}
//保存流接口中的数据
LARGE_INTEGER li;
li.HighPart = 0;
li.LowPart = 0;
ULARGE_INTEGER uli;
uli.HighPart = 0;
uli.LowPart = 0;
pIStm->Seek(li, STREAM_SEEK_SET, &uli);
//创建目标文件并循环读取流中的数据保存至文件
char buffer[1024];
hFile = CreateFile(
szFileName,
GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_HIDDEN,
NULL);
DWORD dwRead = 1;
while(dwRead>0)
{
pIStm->Read(buffer, 1024, &dwRead);
if(dwRead > 0)
WriteFile(hFile, buffer, dwRead, &dwWritten, NULL);
}
//释放有关内存资源
CloseHandle(hFile);
DeleteObject(hBitmap);
pIPic->Release();
pIStm->Release();
}
return TRUE;
}
/*
果然不出所料,资源中所包含的位图被成功地保存到磁盘,并能被正确地打开了。于是我把代码给了朋友,算是完成了一个小任务。
今天下午,突然想起第一个函数写成的文件总比源文件少14个字节,使用流技术会不会自动补全啊,于是对比了一下图片文件,意外发现生成的目标文件竟然比源文件多出了2倍多的字节,我顿时惊呆了。这是为什么呢?
14字节!14字节?我脑海里反复想到这个数字,因为按照常理,第一个函数便能正确运行的啊。第二函数虽然运行成功了,但文件大小又有了出入。这中间一定有鬼。
肯定是VC开发环境对BITMAP、ICON之类的资源作了手脚。
14字节!——这不正是位图文件头的结构大小吗?哦,也许是VC对位图资源忽略了文件头。于是赶快实验,便写了第三个函数,代码如下:
*/
BOOL FreeSource_3(LPCTSTR pszResName,LPCTSTR pszResType,LPCTSTR szFileName)
{
BOOL bRet = TRUE;
HINSTANCE hInst = GetModuleHandle(NULL);
//判断指定的资源是否存在
HRSRC hResInfo = FindResource(hInst,pszResName,pszResType);
if(hResInfo == NULL)
return FALSE;
HANDLE hFile = NULL;
DWORD dwWritten = 0;
//调入指定的资源到内存
HGLOBAL hResData = LoadResource(hInst,hResInfo);
LPVOID pvResData = LockResource(hResData);
DWORD dwResSize = SizeofResource(hInst,hResInfo);
//创建目标文件并保存数据至文件
hFile = CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
if(pszResType == RT_BITMAP)
{
//获得位图信息头
BITMAPINFOHEADER bmpInfoHdr;
CopyMemory(&bmpInfoHdr, pvResData, sizeof(BITMAPINFOHEADER));
//获得位图颜色表中RGBQUAD结构的个数
long nColorEntries;
switch(bmpInfoHdr.biBitCount)
{
case 1:
nColorEntries = 2;
break;
case 4:
nColorEntries = 16;
break;
case 8:
nColorEntries = 256;
break;
default:
nColorEntries = 0;
}
//根据位图信息头创建位图文件头
BITMAPFILEHEADER bmpFileHdr;
bmpFileHdr.bfType = 0x4d42; // 'BM'
bmpFileHdr.bfSize = sizeof(BITMAPINFOHEADER) + dwResSize;
bmpFileHdr.bfReserved1 = bmpFileHdr.bfReserved2 = 0;
bmpFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorEntries;
//写入位图文件头
WriteFile(hFile, &bmpFileHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
}
WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);
//释放有关内存资源
CloseHandle(hFile);
FreeResource(hResData);
return TRUE;
};
#endif