最近做一个程序,想从EXE,DLL或者其他什么的文件中提取 图标。
从网上搜集了一下资料发现只能够提取到 比较小的图标,小图标为 16x16,大图标为32x32,这远远满足不了需求,下面是一般做法:
QString filePath;
QFileInfo fileInfo(filePath); QFileIconProvider fileIcon();
QIcon icon=fileIcon ().icon (fileInfo);
QPixmap pixmap=icon.pixmap (128,128);
结果只能够最多得到32x32的图标。
于是我查看QFileIconProvider的实现源文件,发现主要由SHGetFileInfo这个函数实现。
//Get the small icon
#ifndef Q_OS_WINCE
val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX);
//Get the big icon
#ifndef Q_OS_WINCE
val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX);
这样就只能够得到16x16的小图标和32x32的大图标。
虽然上面用的是QPixmap pixmap=icon.pixmap (128,128); 但是还是只能够得到32x32的图标。
于是查看了一下windows函数,发现 SHGetImageList这个函数可以实现获取256x256的超大图标,不过这个在win7下才支持256x256的图标,这个函数也在WIN7下才比较好用,XP上好像会出问题。
但是在#include <shellapi.h> 后发现 这个函数 报错,在MSDN上查到明明就在这个头文件里面啊,然后F2打开shellapi.h后发现里面没有这个函数的定义,这是什么情况呢。
后来才发现原来 QT默认使用的 mingw里面的 库,现在 QT的mingw版本里面并不包含有 SHGetImageList这个函数,然后打开VS2010下的库 查看里面的 shellapi.h发现里面果然有SHGetImageList。
于是便琢磨着如何使用VS2010下的库呢?
思来想去水平太低了没想出个办法,但突然想到咱可以用 VS2010做个DLL 给QT调用啊。
于是在VS2010下 写个到出函数:
#include <ShellAPI.h>
#include <CommCtrl.h>
#include <commoncontrols.h>
#include <windows.h>
EXTERN_C _declspec(dllexport) HICON getJumbIcon(CONST TCHAR *filePath)
{
// Get the icon index using SHGetFileInfo
SHFILEINFOW sfi = {0};
SHGetFileInfo(filePath, -1, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
// Retrieve the system image list.
// To get the 48x48 icons, use SHIL_EXTRALARGE
// To get the 256x256 icons (Vista only), use SHIL_JUMBO
IImageList* imageList;
HRESULT hResult = SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&imageList);
if (hResult == S_OK) {
// Get the icon we need from the list. Note that the HIMAGELIST we retrieved
// earlier needs to be casted to the IImageList interface before use.
HICON hIcon;
hResult = (imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon);
if (hResult == S_OK) {
// Do something with the icon here.
return hIcon;
}
}
}
然后在QT里面调用:
typedef HICON (*getIcon)(CONST TCHAR *filePath); //定义函数指针,以备调用
HICON test(QString filePath)
{
QLibrary mylib("./configure/dll/icon.dll"); //声明所用到的dll文件
HICON jumbIcon;
if (mylib.load())
{
getIcon icon=(getIcon)mylib.resolve("getJumbIcon"); //援引 getJumbIcon() 函数
if (icon) //是否成功连接上 getJumbIcon() 函数
{
filePath.replace ("/","\\");
jumbIcon=icon((CONST TCHAR *)filePath.utf16 ()); //这里函数指针调用dll中的 getJumbIcon 函数
return jumbIcon;
}
else
QMessageBox::information(NULL,"NO","Linke to Function is not OK!!!!");
}
else
QMessageBox::information(NULL,"NO","DLL is not loaded!");
return NULL;
}
HICON hicon=test(filePath);QPixmap icon=QPixmap::fromWinHICON (hicon);DestroyIcon(hicon);
最后icon便可以显示256X256的图片了。
可以更改SHIL_JUMBO来决定 图标的大小。
不过令我感到奇怪的是:为什么当filePath中 包含了 网页的桌面快捷方式的时候 会多出来好几M的内存使用,得再研究。
最后是DLL文件了。