我需要获取带有叠加图标(例如快捷方式的链接图标)的大型“巨型”文件图标(256x256像素),基本上与在Windows文件资源管理器中设置为以超大图标查看项目时所见到的相同。
例如,我有一个指向文本文件的快捷方式“a.txt.lnk”,它在文件资源管理器中具有此图标。这就是我想要获取的内容(是的,左下角的箭头就是我所说的叠加图标): 我非常努力地谷歌了一下,找到了如何做这件事的方法。
为了实验代码,我使用了Qt框架中的QtWinExtras库中的iconextractor示例。不幸的是,它有一些问题,无法正常工作。我所能做的就是获取带有快捷方式叠加的小图标(32x32像素)或没有叠加的“巨型”图标。这个: 或者这样: 我将Qt示例中的代码简化成了这个
和
我的问题是我不理解这行代码
例如,我有一个指向文本文件的快捷方式“a.txt.lnk”,它在文件资源管理器中具有此图标。这就是我想要获取的内容(是的,左下角的箭头就是我所说的叠加图标): 我非常努力地谷歌了一下,找到了如何做这件事的方法。
为了实验代码,我使用了Qt框架中的QtWinExtras库中的iconextractor示例。不幸的是,它有一些问题,无法正常工作。我所能做的就是获取带有快捷方式叠加的小图标(32x32像素)或没有叠加的“巨型”图标。这个: 或者这样: 我将Qt示例中的代码简化成了这个
main.cpp
:#include <QtWin>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QGuiApplication>
#include <QImage>
#include <QPixmap>
#include <comdef.h>
#include <CommCtrl.h>
#include <commoncontrols.h>
struct PixmapEntry {
QString name;
QPixmap pixmap;
};
using PixmapEntryList = QVector<PixmapEntry>;
static QString formatSize(const QSize &size)
{
return QString::number(size.width()) + u'x' + QString::number(size.height());
}
static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info)
{
QPixmap result;
static const IID iID_IImageList = {0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50}};
IImageList *imageList = nullptr;
if (FAILED(SHGetImageList(iImageList, iID_IImageList, reinterpret_cast<void **>(&imageList))))
return result;
HICON hIcon = nullptr;
// NOTE: the following was missing in original Qt code
// and therefore returned no jumbo icons at all when
// overlays were requested.
// Highest 8 bits are reverved for overlay index.
int iconIndex = info.iIcon & 0xFFFFFF;
if (SUCCEEDED(imageList->GetIcon(iconIndex, ILD_TRANSPARENT, &hIcon))) {
result = QtWin::fromHICON(hIcon);
DestroyIcon(hIcon);
}
return result;
}
static PixmapEntryList extractShellIcons(const QString &sourceFile, bool addOverlays)
{
enum { // Shell image list ids
sHIL_EXTRALARGE = 0x2, // 48x48 or user-defined
sHIL_JUMBO = 0x4 // 256x256 (Vista or later)
};
struct FlagEntry {
QString name;
unsigned flags;
};
const QString nativeName = QDir::toNativeSeparators(sourceFile);
const auto *sourceFileC = reinterpret_cast<const wchar_t *>(nativeName.utf16());
SHFILEINFO info;
unsigned int flags = SHGFI_ICON | SHGFI_SYSICONINDEX | SHGFI_SHELLICONSIZE;
if (addOverlays)
flags |= SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX; // What do these flags do? How to utilize the overlay index?
PixmapEntryList result;
const QString prefix = "sh_";
ZeroMemory(&info, sizeof(SHFILEINFO));
SHGetFileInfo(sourceFileC, 0, &info, sizeof(SHFILEINFO), flags);
// extract standard icon
PixmapEntry entry;
entry.pixmap = QtWin::fromHICON(info.hIcon);
DestroyIcon(info.hIcon);
if (entry.pixmap.isNull()) {
qWarning() << "Error converting icons.";
return PixmapEntryList();
}
entry.name = prefix + formatSize(entry.pixmap.size());
const int iconIndex = info.iIcon & 0xFFFFFF;
const int overlayIconIndex = info.iIcon >> 24; // Note: some resources suggest there should be -1 to adjust for 0-based index. Really?
qDebug() << "Obtained icon #" << iconIndex << "overlay #" << overlayIconIndex;
result.append(entry);
// extract jumbo icon
const QPixmap jumbo = pixmapFromShellImageList(sHIL_JUMBO, info);
if (!jumbo.isNull()) {
PixmapEntry entry;
entry.pixmap = jumbo;
entry.name = QLatin1String("jumbo_") + formatSize(jumbo.size());
result.append(entry);
}
return result;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
const QString &sourceFile = "C:/my/path/to/some/link/a.txt.lnk";
QString imageFileRoot = QDir::currentPath() + u'/';
// Note: Settings true or false in the following line has no effect of overlays.
// Small icons have always overlays, jumbo icons have never overlays.
const PixmapEntryList pixmaps = extractShellIcons(sourceFile, true);
for (const auto &entry : pixmaps) {
const QString fileName = imageFileRoot + entry.name + QLatin1String(".png");
entry.pixmap.save(fileName);
qDebug() << "Wrote " << QDir::toNativeSeparators(fileName);
}
return 0;
}
和
iconextractor.pro
:TEMPLATE = app
TARGET = iconextractor
CONFIG += console
QT = core gui winextras
LIBS += -lshell32 -luser32
SOURCES += main.cpp
我的问题是我不理解这行代码
flags |= SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX;
的作用是什么。它对标准图标没有影响(即使没有这行代码,它们也包含覆盖层),对巨型图标也没有影响(它们本来就不包含覆盖层)。显然我可以获取图标覆盖层的索引,但我不知道该如何使用它。如何获取带有覆盖层的巨型图标?