通常位图(Bitmap)能够满足大多数体积小的情况了,但对于大的位图,
如果是要放到资源,实不敢恭维啊,程序体积一下子大了N多,看着也不爽
同样的图片,如果是PNG啊JPEG啊等其它格式,体积明显小了不是一般的多
那么为何不用它们呢?
微软提供了GDI+这玩意,貌似可以轻松地完成常用的格式图片,
不过它不提供类似LoadBitmap, LoadImage之类从资源读取的直接函数
虽然那Bitmap有成员函数FromResource(构造函数也可以)
但实际自己用用就知道了,不是通杀的
不过还好,微软提供了从IStream创建这一方法,
那么我们只要把资源(或者图片文件)的数据读到这IStream就完事了
下面的函数自己实现的,可以直接从资源里加载GDI+支持的图片格式
先看代码
//hInst为持有图片资源的实例句柄 //lpszResName为资源名 //lpszResType为资源类型 HBITMAP LoadPicture (HINSTANCE hInst , LPCTSTR lpszResName , LPCTSTR lpszResType ) { if (! lpszResName || ! lpszResType ){ return NULL ; } //先判断是不是位图,是直接用LoadBitmap API省事 if ((WORD )lpszResType == (WORD )RT_BITMAP ){ return LoadBitmap (hInst , lpszResName ); } //其它格式的通过查找资源方式 HRSRC hResInfo = FindResource (hInst , lpszResName , lpszResType ); if (! hResInfo ){ return NULL ; } HGLOBAL hResData = LoadResource (hInst , hResInfo ); if (! hResData ){ return NULL ; } LPVOID pSrc = LockResource (hResData ); if (! pSrc ){ return NULL ; } DWORD dwSize = SizeofResource (hInst , hResInfo ); if (! dwSize ){ return NULL ; } HGLOBAL hGlobal = GlobalAlloc (GMEM_MOVEABLE , dwSize ); if (! hGlobal ){ return NULL ; } LPVOID pData = GlobalLock (hGlobal ); if (! pData ){ return NULL ; } memcpy (pData , pSrc , dwSize ); GlobalUnlock (hGlobal ); IStream * pStream = NULL ; //一切搞定,创建这关键的IStream了 if (FAILED (CreateStreamOnHGlobal (hGlobal , TRUE , & pStream ))) return NULL ; if (pStream == NULL ) return NULL ; Gdiplus :: Bitmap * pBitmap = new Gdiplus :: Bitmap (pStream ); pStream -> Release (); HBITMAP hBitmap = NULL ; //获取HBITMAP pBitmap -> GetHBITMAP (NULL , & hBitmap ); delete pBitmap ; return hBitmap ; }
OK,就这么点
函数名长得跟LoadBitmap像吧,只不过多了一个图片类型参数
使用方法自然不用说了,既然返回的是HBITMAP,就跟平常时BitBlt什么的就OK了
或许你会问,为啥不直接用GDI+画?
这个……GDI+画图的效率不怎么地行啊,即使用上了传说中的DrawCachedBitmap等提速方法,
也还是没有传说中的BitBlt牛X
至于为啥没用到FreeResoure之类的API,微软这么说的
For 32-bit Windows applications, it is not necessary to free the resources loaded using function LoadResource
其它的看MSDN了呗
至于怎么调用应该不用说了吧?不过还是啰嗦一下吧
比如资源里有这么一个PNG
IDB_PNG PNG "working.png"
那么只要
HBITMAP hBitmap = LoadPicture(hInst, MAKEINTRESOURCE(IDB_PNG), TEXT("PNG"));
就这么简单!!!
如果想在纯C下用,那把它放到DLL里去吧,额D神~