功能:
通过资源加载,和通过本地文件加载;
加载图片包括ico, bmp, png
方法(I) 使用Image,从资源加载
/****************************************************************************************************
//从GDI加载图片的方法(包括.bmp,.ico,.png)
* @param [inout] pImage 图片指针
* @param [in] lpType 资源类型,例如:IDI_ICON1,IDB_BMP1,IDB_PNG1
* @param [in] lpTyp 资源类型,例如:RT_BITMAP,RT_ICON,"PNG"(注意PNG图片没有系统定义)
****************************************************************************************************/
BOOL LoadImageFromResource(Image **pImage, DWORD dwResID, LPCSTR lpType)
{
HGLOBAL hGlobal = NULL;
HRSRC hSource = NULL;
LPVOID lpVoid = NULL;
DWORD dwSize = 0;
BOOL bRet = FALSE;
//1..获取当前资源模块的句柄(均可)
//HMODULE hInstance = AfxGetInstanceHandle();
//HINSTANCE hInstance = GetModuleHandle(NULL);
HINSTANCE hInstance = AfxGetResourceHandle();
if (NULL == hInstance)
{
return FALSE;
}
//2..确定指定模块中指定类型和名称的资源所在位置
//返回值:返回值为指向被指定资源信息块的句柄,为了获得这些资源,应将这个句柄传递给LoadResource函数.
hSource = FindResource(hInstance, MAKEINTRESOURCE(dwResID), lpType);
//hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_PNG1), "PNG");
//hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1), RT_ICON);
//hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
if (NULL == hSource)
{
INT N = GetLastError();
return FALSE;
}
//3..装载指定资源到全局存储器
//参数1:处理包含资源的可执行文件的模块句柄,若hModule为NULL,系统从当前过程中的模块中装载资源
//参数2:表示被装载资源的句柄,它必须由函数FindResource或FindResourceEx创建.
//返回值:运行成功返回相关资源的数据的句柄,返回类型是向后兼容的HGLOBAL型,而不是因为函数返回一个全局存储块句柄,不要传递这个句柄给函数GlobalLock或GlobalFree.
hGlobal = LoadResource(hInstance, hSource);
if (NULL == hGlobal)
{
return FALSE;
}
//4..锁定内存中的指定资源,说白了就是返回资源在内存中的地址,不须解锁操作
//参数表示被装载资源的句柄,由LoadResource()返回
lpVoid = LockResource(hGlobal);
if (NULL == lpVoid)
{
goto _Cleanup;
}
//5..返回指定资源的大小(参数1资源文件模块的句柄,参数2必须由FindResource或FindResourceEx来创建)
dwSize = SizeofResource(hInstance, hSource);
if (0 == dwResID)
{
goto _Cleanup;
}
//6..全局堆分配(GMEM_MOVEABLE:分配可移动的内存;可使用函数GlobalLock将返回句柄转换为一个指针)
HGLOBAL hGlobal2 = GlobalAlloc(GHND, dwSize);
if (NULL == hGlobal2)
{
goto _Cleanup;
}
//7..锁定内存中指定的内存块,并返回一个地址值,令其指向内存块的起始处
//除非用GlobalUnlock()函数将内存块解锁,否则地址会一直保持有效
LPVOID lpData = GlobalLock(hGlobal2);
//8..拷贝数据
memcpy_s(lpData, dwSize, (void *)hGlobal, dwSize);
//9..从指定内存创建流对象
//参数1是由GlobalAlloc分配的内存句柄;
//参数2表示参数1所指定的内存在该流对象被释放后是否也自动释放,如果该参数设为FALSE,那么调用者必须显式的释放hGlobal,如果为TRUE,则hGlobal最终会自动释放.
IStream* pStream = NULL;
if (S_OK != CreateStreamOnHGlobal(hGlobal2, TRUE, &pStream))
{
GlobalFree(hGlobal2);
goto _Cleanup;
}
//10..从指定的数据流创建Image
*pImage = Gdiplus::Image::FromStream(pStream, FALSE);
pStream->Release();
//11..解除锁定的内存块
//实际上是将内存对象的锁定计数器减一,用GlobalLock锁定的内存,一定要用GlobalUnlock解锁.
GlobalUnlock(hGlobal2);
//12..释放通过GlobalLock函数分配的内存(CreateStreamOnHGlobal中设为TRUE将自动释放hGlobal2)
//GlobalFree(hGlobal2);
bRet = TRUE;
//int nBackWidth = (*pImage)->GetWidth();
//int nBackHeight = (*pImage)->GetHeight();
_Cleanup:
//解锁由LockResource()锁定的资源
UnlockResource(hGlobal);
//释放通过LoadResource函数分配的资源
FreeResource(hGlobal);
//开始绘图(需要放到OnEraseBkgnd()里实现)
//CClientDC dc(this);
//Graphics graphics(dc.m_hDC);//通过设备描述表句柄实例化一个 gdi+ Graphics 类成员
//graphics.DrawImage(pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight());
return bRet;
}
方法(II) 使用CImage,从资源加载
/****************************************************************************************************
* 从GDI加载图片的法方
* @param [inout] pImage 图片指针
* @param [in] lpType 资源类型,例如:IDI_ICON1,IDB_BMP1,IDB_PNG1
* @param [in] lpTyp 资源类型,例如:RT_BITMAP,RT_ICON,"PNG"(注意PNG图片没有系统定义)
//注意: 调用处需要先CImage *pImage = new CImage
****************************************************************************************************/
BOOL LoadImageFromResource(CImage *pImage, DWORD dwResID, LPCSTR lpType)
{
HGLOBAL hGlobal = NULL;
HRSRC hSource = NULL;
LPVOID lpVoid = NULL;
DWORD dwSize = 0;
BOOL bRet = FALSE;
//1..获取当前资源模块的句柄(均可)
//HMODULE hInstance = AfxGetInstanceHandle();
//HINSTANCE hInstance = GetModuleHandle(NULL);
HINSTANCE hInstance = ::AfxGetResourceHandle();
if (NULL == hInstance)
{
return FALSE;
}
//2..确定指定模块中指定类型和名称的资源所在位置
//返回值:返回值为指向被指定资源信息块的句柄,为了获得这些资源,应将这个句柄传递给LoadResource函数.
hSource = FindResource(hInstance, MAKEINTRESOURCE(dwResID), lpType);
//hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1), RT_ICON);
//hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
if (NULL == hSource)
{
return FALSE;
}
//3..装载指定资源到全局存储器
//参数1:处理包含资源的可执行文件的模块句柄,若hModule为NULL,系统从当前过程中的模块中装载资源
//参数2:表示被装载资源的句柄,它必须由函数FindResource或FindResourceEx创建.
//返回值:运行成功返回相关资源的数据的句柄,返回类型是向后兼容的HGLOBAL型,而不是因为函数返回一个全局存储块句柄,不要传递这个句柄给函数GlobalLock或GlobalFree.
hGlobal = LoadResource(hInstance, hSource);
if (NULL == hGlobal)
{
return FALSE;
}
//4..锁定内存中的指定资源,说白了就是返回资源在内存中的地址,不须解锁操作
//参数表示被装载资源的句柄,由LoadResource()返回
lpVoid = LockResource(hGlobal);
if (NULL == lpVoid)
{
goto _Cleanup;
}
//5..返回指定资源的大小(参数1资源文件模块的句柄,参数2必须由FindResource或FindResourceEx来创建)
dwSize = SizeofResource(hInstance, hSource);
if (0 == dwResID)
{
goto _Cleanup;
}
//6..全局堆分配(GMEM_MOVEABLE:分配可移动的内存;可使用函数GlobalLock将返回句柄转换为一个指针)
HGLOBAL hGlobal2 = GlobalAlloc(GHND, dwSize);
if (NULL == hGlobal2)
{
goto _Cleanup;
}
//7..锁定内存中指定的内存块,并返回一个地址值,令其指向内存块的起始处
//除非用GlobalUnlock()函数将内存块解锁,否则地址会一直保持有效
LPVOID lpData = GlobalLock(hGlobal2);
//8..拷贝数据
memcpy_s(lpData, dwSize, (void *)hGlobal, dwSize);
//9..从指定内存创建流对象
//参数1是由GlobalAlloc分配的内存句柄;
//参数2表示参数1所指定的内存在该流对象被释放后是否也自动释放,如果该参数设为FALSE,那么调用者必须显式的释放hGlobal,如果为TRUE,则hGlobal最终会自动释放.
IStream* pStream = NULL;
if (S_OK != CreateStreamOnHGlobal(hGlobal2, TRUE, &pStream))
{
GlobalFree(hGlobal2);
goto _Cleanup;
}
//10..从指定的数据流创建Image
pImage->Load(pStream);
pStream->Release();
//11..解除锁定的内存块
//实际上是将内存对象的锁定计数器减一,用GlobalLock锁定的内存,一定要用GlobalUnlock解锁.
GlobalUnlock(hGlobal2);
//12..释放通过GlobalLock函数分配的内存(CreateStreamOnHGlobal中设为TRUE将自动释放hGlobal2)
//GlobalFree(hGlobal2);
bRet = TRUE;
//int nBackWidth = pImage->GetWidth();
//int nBackHeight = pImage->GetHeight();
_Cleanup:
//解锁由LockResource()锁定的资源
UnlockResource(hGlobal);
//释放通过LoadResource函数分配的资源
FreeResource(hGlobal);
return bRet;
}
方法(III) 使用Image,从本地文件加载
//从本地文件加载
BOOL LoadImageFromFile(Image **pImage, LPCSTR lpFile)
{
CFile f;
CFileException e;
if (!f.Open(lpFile, CFile::modeRead, &e))
{
return FALSE;
}
//分配全局内存
DWORD dwSize = (DWORD)f.GetLength();
HGLOBAL hMemBmp = GlobalAlloc(GHND, dwSize);
if (NULL == hMemBmp)
{
return FALSE;
}
//锁定指定内存
LPVOID pBmp = GlobalLock(hMemBmp);
f.SeekToBegin();
f.Read(pBmp, dwSize);
//从指定内存创建流对象
IStream* pStmBmp = NULL;
if (S_OK == CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp))
{
//从指定的数据流创建Image
*pImage = Image::FromStream(pStmBmp, FALSE);
pStmBmp->Release();
}
//释放全局内存
GlobalFree(hMemBmp);
//开始绘图(需要放到OnEraseBkgnd()里实现)
//CClientDC dc(this);
//Graphics graphics(dc.m_hDC);//通过设备描述表句柄实例化一个 gdi+ Graphics 类成员
//graphics.DrawImage(pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight());
return TRUE;
}
//从本地文件加载
BOOL LoadImageFromFile_V2(Image **pImage, LPCSTR lpFile)
{
//从指定的数据流创建Image
CT2CW wFile(lpFile);
*pImage = Image::FromFile(wFile, FALSE);
//开始绘图(需要放到OnEraseBkgnd()里实现)
//CClientDC dc(this);
//Graphics graphics(dc.m_hDC);//通过设备描述表句柄实例化一个 gdi+ Graphics 类成员
//graphics.DrawImage(pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight());
return TRUE;
}
方法(IV) 视同Ciamge,从本地文件加载
//从本地文件加载
BOOL LoadImageFromFile(CImage *pImage, LPCSTR lpFile)
{
CFile f;
CFileException e;
if (!f.Open(lpFile, CFile::modeRead, &e))
{
return FALSE;
}
//分配全局内存
DWORD dwSize = (DWORD)f.GetLength();
HGLOBAL hMemBmp = GlobalAlloc(GHND, dwSize);
if (NULL == hMemBmp)
{
return FALSE;
}
//锁定指定内存
LPVOID pBmp = GlobalLock(hMemBmp);
f.SeekToBegin();
f.Read(pBmp, dwSize);
//从指定内存创建流对象
IStream* pStmBmp = NULL;
if (S_OK == CreateStreamOnHGlobal(hMemBmp, FALSE, &pStmBmp))
{
//从指定的数据流创建Image
pImage->Load(lpFile);
pStmBmp->Release();
}
//释放全局内存
GlobalFree(hMemBmp);
//开始绘图(需要放到OnEraseBkgnd()里实现)
//CClientDC dc(this);
//Graphics graphics(dc.m_hDC);//通过设备描述表句柄实例化一个 gdi+ Graphics 类成员
//graphics.DrawImage(pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight());
return TRUE;
}
//从本地文件加载,使用CImage类
BOOL LoadImageFromFile_V2(CImage *pImage, LPCSTR lpFile)
{
pImage->Load(lpFile);
return TRUE;
}