本文出自悠然品鉴小悠,转载请注明出处:http://www.youranshare.com/codeorg/sid/139.html
程序中需要一个提取并显示指定文件图标的需求,今天下午也就研究了一下相关的东西,之前一直只能提取出32x32大小的图标文件,画质真心不好,于是就Google了一下老外们的方法研究了一下,最终找到了提取256x265大图标的方法,于是自己就封装了一个类,这里给大家分享一下.
下面的内容会用到一个CLSID的东西,这里先简单的科普一下CLSID的知识:
CLSID是指windows系统对于不同的应用程序,文件类型,OLE对象,特殊文件夹以及各种系统组件分配一个唯一表示它的ID代码,用于对其身份的标示和与其他对象进行区分。
先得说下GUID,它是Globally Unique Identifier的简称,中文翻译为“全局唯一标示符”,在Windows系统中也称之为Class ID,缩写为CLSID。
先简单的说明一下基本的处理流程吧:
① 因为用到了GDI+,所以要先初始化GDI+环境
② 根据给出的图片保存格式,获取到对应的编码器CLSID(也就是GUID)
③ 根据给出的文件路径,通过SHGetFileInfo函数获取到ICON的list
④ 根据给出的保存图片的大小获取到对应图标的句柄
⑤ 通过获取到的HICON句柄,创建GDiplus::Bitmap
⑥ 通过获取的CLSID和Gdiplus::Bitmap将图片保存到指定的位置
⑦ 程序退出,关闭GDI+
下面我就来说一下这个CPEIconHelper基本的构成
一、 对应的宏定义
① 下面的这四个定义是用于初始化操作的时候的返回值
//操作过程中 返回的一些 错误信息,函数SetAttribute的返回值 #define ICON_SUCCESS 0x00 //初始化成功 #define ICON_ERRO_CLSID 0x01 //初始化CLSID出错 #define ICON_ERRO_HICON 0x02 //初始化HIcon出错 #define ICON_ERRO_BITMAP 0x03 //初始化Gdiplus::Bitmap出错
② 下面的3个宏定义是指明获取的图标大小
//图标的大小,分为16/32/256 #define SIZE_SMALL SHIL_SMALL //16x16 #define SIZE_MID SHIL_LARGE //32x32 #define SIZE_BIG SHIL_JUMBO // Vista 之后的 256x256
③ 下面的5中宏表示了5中不同的格式
//需要保存的图标 格式 #define SAVE_BMP L"image/bmp" #define SAVE_JPPEG L"image/jpeg" #define SAVE_PNG L"image/png" #define SAVE_GIF L"image/gif" #define SAVE_TIFF L"image/tiff"
④ 下面的这2个宏可以忽略,是类内使用的
//获取 CLSID|GUID 的值的时候的返回值,类内使用的,无需关心 #define CLSID_SUCCESS 0x00 #define CLSID_FAILD 0x01
二、 类内的成员变量
① HICON m_hIcon;//保存 ICO的 句柄
② CLSID m_Clsid;//解码器 GUID | CLSID
③ std::string m_szFilePath;//文件路径
④ std::wstring m_wszFormat;//文件的格式
⑤ DWORD m_dwWantSize; //需要获取到的size
⑥ Gdiplus::Bitmap* m_lpBitmap;//保存图片时用到的 Gdi的bitmap
三、 类内的成员函数
① CPEIconHelper();
~CPEIconHelper();
这两个是构造函数和析构函数
② DWORD SetFileAttribute(std::string szPath,std::wstring
wszFormat=SAVE_PNG,
DWORD dwWantSize=SIZE_MID);
这个函数是设置文件的信息的:
参数1:文件的完整路径
参数2:需要保存的图片格式,默认PNG
参数3:需要获取的图片大小,默认是32X32的
返回值: ICON_SUCCESS、ICON_XXXX这些的,表示初始化的结果
③ Gdiplus::Status SaveToFile(std::wstring wszSavePath);
这个函数是用于保存操作的,只有当初始化正确后才能调用
参数1:图标的保存路径,例如C:\test.png
如果你是Win8系统,保存到系统盘可能有权限的限制,需要管理员权限运行
返回值: enum Status
{
Ok = 0,
GenericError = 1,
InvalidParameter = 2,
OutOfMemory = 3,
ObjectBusy = 4,
InsufficientBuffer = 5,
NotImplemented = 6,
Win32Error = 7,
WrongState = 8,
Aborted = 9,
FileNotFound = 10,
ValueOverflow = 11,
AccessDenied = 12,
UnknownImageFormat = 13,
FontFamilyNotFound = 14,
FontStyleNotFound = 15,
NotTrueTypeFont = 16,
UnsupportedGdiplusVersion = 17,
GdiplusNotInitialized = 18,
PropertyNotFound = 19,
PropertyNotSupported = 20,
#if (GDIPVER >= 0x0110)
ProfileNotFound = 21,
#endif //(GDIPVER >= 0x0110)
};
描述了保存文件操作的结果.
④ bool SetSaveFormat(std::wstring wszNewFmt);
函数用于重设图片保存的格式
参数1:新的图片格式
返回值:true表示成功,false表示失败
⑤ bool SetSaveSize(DWORD dwWantSize);
函数用于重设保存的图片大小
参数1:重设的图片大小
返回值: true表示成功,false表示失败
⑥ int InitEncodersCLSID();
函数用于初始化解码器的CLSID值,类内自动调用,不可访问
⑦ bool InitHIcon();
函数用于初始化图标的句柄,类内自动调用,不可访问
⑧ bool InitGBitmap();
函数用于初始化保存图片用的Gdiplus::Bitmap,类内自动调用,不可访问
四、类内核心
类中的主要核心是通过函数SHGetFileInfo获取到图标的ImageList,然后解析除出需要的Ico句柄,然后调用Gdiplus::Bitmap::FromHICON(m_hIcon);函数创建对应的Gdiplus::Bitmap,然后调用Gdiplus::Bitmap::Save操作保存到对应的图片格式.
这是我的转换执行测试结果:
附上示例代码的下载地址: (C++VS2010工程)
解压密码 yscode
百度网盘下载地址:http://pan.baidu.com/s/1qW9F4ZE