通常位图(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神~