diff options
Diffstat (limited to 'examples/winextras/iconextractor/main.cpp')
-rw-r--r-- | examples/winextras/iconextractor/main.cpp | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/examples/winextras/iconextractor/main.cpp b/examples/winextras/iconextractor/main.cpp deleted file mode 100644 index 6e11816..0000000 --- a/examples/winextras/iconextractor/main.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWinExtras module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtWin> - -#include <QCommandLineParser> -#include <QCommandLineOption> -#include <QDir> -#include <QFileInfo> -#include <QGuiApplication> -#include <QImage> -#include <QPixmap> -#include <QScopedArrayPointer> -#include <QStringList> -#include <QSysInfo> - -#include <iostream> - -#include <shellapi.h> -#include <comdef.h> -#include <commctrl.h> -#include <objbase.h> -#include <commoncontrols.h> - -/* This example demonstrates the Windows-specific image conversion - * functions. */ - -struct PixmapEntry { - QString name; - QPixmap pixmap; -}; - -using PixmapEntryList = QList<PixmapEntry>; - -static std::wostream &operator<<(std::wostream &str, const QString &s) -{ -#ifdef Q_OS_WIN - str << reinterpret_cast<const wchar_t *>(s.utf16()); -#else - str << s.toStdWString(); -#endif - return str; -} - -static QString formatSize(const QSize &size) -{ - return QString::number(size.width()) + u'x' + QString::number(size.height()); -} - -// Extract icons contained in executable or DLL using the Win32 API ExtractIconEx() -static PixmapEntryList extractIcons(const QString &sourceFile, bool large) -{ - const QString nativeName = QDir::toNativeSeparators(sourceFile); - const auto *sourceFileC = reinterpret_cast<const wchar_t *>(nativeName.utf16()); - const UINT iconCount = ExtractIconEx(sourceFileC, -1, nullptr, nullptr, 0); - if (!iconCount) { - std::wcerr << sourceFile << " does not appear to contain icons.\n"; - return PixmapEntryList(); - } - - QScopedArrayPointer<HICON> icons(new HICON[iconCount]); - const UINT extractedIconCount = large ? - ExtractIconEx(sourceFileC, 0, icons.data(), nullptr, iconCount) : - ExtractIconEx(sourceFileC, 0, nullptr, icons.data(), iconCount); - if (!extractedIconCount) { - qErrnoWarning("Failed to extract icons from %s", qPrintable(sourceFile)); - return PixmapEntryList(); - } - - PixmapEntryList result; - result.reserve(int(extractedIconCount)); - - std::wcout << sourceFile << " contains " << extractedIconCount << " icon(s).\n"; - - for (UINT i = 0; i < extractedIconCount; ++i) { - PixmapEntry entry; - entry.pixmap = QtWin::fromHICON(icons[i]); - if (entry.pixmap.isNull()) { - std::wcerr << "Error converting icons.\n"; - return PixmapEntryList(); - } - entry.name = QString::fromLatin1("%1_%2x%3").arg(i, 3, 10, QLatin1Char('0')) - .arg(entry.pixmap.width()).arg(entry.pixmap.height()); - result.append(entry); - } - return result; -} - -// Helper for extracting large/jumbo icons available from Windows Vista onwards -// via SHGetImageList(). -static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info) -{ - QPixmap result; - // For MinGW: - 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; - if (SUCCEEDED(imageList->GetIcon(info.iIcon, ILD_TRANSPARENT, &hIcon))) { - result = QtWin::fromHICON(hIcon); - DestroyIcon(hIcon); - } - return result; -} - -// Extract icons that would be displayed by the Explorer (shell) -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 { - const char *name; - unsigned flags; - }; - - const FlagEntry modeEntries[] = - { - {"", 0}, - {"open", SHGFI_OPENICON}, - {"sel", SHGFI_SELECTED}, - }; - const FlagEntry standardSizeEntries[] = - { - {"s", SHGFI_SMALLICON}, - {"l", SHGFI_LARGEICON}, - {"sh", SHGFI_SHELLICONSIZE}, - }; - - const QString nativeName = QDir::toNativeSeparators(sourceFile); - const auto *sourceFileC = reinterpret_cast<const wchar_t *>(nativeName.utf16()); - - SHFILEINFO info; - unsigned int baseFlags = SHGFI_ICON | SHGFI_SYSICONINDEX | SHGFI_ICONLOCATION; - if (addOverlays) - baseFlags |= SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX; - if (!QFileInfo(sourceFile).isDir()) - baseFlags |= SHGFI_USEFILEATTRIBUTES; - - PixmapEntryList result; - for (auto modeEntry : modeEntries) { - const unsigned modeFlags = baseFlags | modeEntry.flags; - QString modePrefix = QLatin1String("_shell_"); - if (modeEntry.name[0]) - modePrefix += QLatin1String(modeEntry.name) + u'_'; - for (auto standardSizeEntry : standardSizeEntries) { - const unsigned flags = modeFlags | standardSizeEntry.flags; - const QString prefix = modePrefix + QLatin1String(standardSizeEntry.name) - + u'_'; - ZeroMemory(&info, sizeof(SHFILEINFO)); - const HRESULT hr = SHGetFileInfo(sourceFileC, 0, &info, sizeof(SHFILEINFO), flags); - if (FAILED(hr)) { - _com_error error(hr); - std::wcerr << "SHGetFileInfo() failed for \"" << nativeName << "\", " - << std::hex << std::showbase << flags << std::dec << std::noshowbase - << " (" << prefix << "): " << error.ErrorMessage() << '\n'; - continue; - } - - if (info.hIcon) { - PixmapEntry entry; - entry.pixmap = QtWin::fromHICON(info.hIcon); - DestroyIcon(info.hIcon); - if (entry.pixmap.isNull()) { - std::wcerr << "Error converting icons.\n"; - return PixmapEntryList(); - } - entry.name = prefix + formatSize(entry.pixmap.size()); - - const int iconIndex = info.iIcon & 0xFFFFFF; - const int overlayIconIndex = info.iIcon >> 24; - - std::wcout << "Obtained icon #" << iconIndex; - if (addOverlays) - std::wcout << " (overlay #" << overlayIconIndex << ')'; - if (info.szDisplayName[0]) - std::wcout << " from " << QString::fromWCharArray(info.szDisplayName); - std::wcout << " (" << entry.pixmap.width() << 'x' - << entry.pixmap.height() << ") for " << std::hex << std::showbase << flags - << std::dec << std::noshowbase << '\n'; - - result.append(entry); - } - } // for standardSizeEntryCount - // Windows Vista onwards: extract large/jumbo icons - if (info.hIcon) { - const QPixmap extraLarge = pixmapFromShellImageList(sHIL_EXTRALARGE, info); - if (!extraLarge.isNull()) { - PixmapEntry entry; - entry.pixmap = extraLarge; - entry.name = modePrefix + QLatin1String("xl_") + formatSize(extraLarge.size()); - result.append(entry); - } - const QPixmap jumbo = pixmapFromShellImageList(sHIL_JUMBO, info); - if (!jumbo.isNull()) { - PixmapEntry entry; - entry.pixmap = jumbo; - entry.name = modePrefix + QLatin1String("jumbo_") + formatSize(extraLarge.size()); - result.append(entry); - } - } - } // for modes - return result; -} - -static const char description[] = - "\nExtracts Windows icons from executables, DLL or icon files and writes them\n" - "out as numbered .png-files.\n" - "When passing the --shell option, the icons displayed by Explorer are extracted.\n"; - -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - QCoreApplication::setApplicationName(QStringLiteral("Icon Extractor")); - QCoreApplication::setOrganizationName(QStringLiteral("QtProject")); - QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR)); - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions); - parser.setApplicationDescription(QLatin1String(description)); - parser.addHelpOption(); - parser.addVersionOption(); - const QCommandLineOption largeIconOption(QStringLiteral("large"), QStringLiteral("Extract large icons")); - parser.addOption(largeIconOption); - const QCommandLineOption shellIconOption(QStringLiteral("shell"), QStringLiteral("Extract shell icons using SHGetFileInfo()")); - parser.addOption(shellIconOption); - const QCommandLineOption shellOverlayOption(QStringLiteral("overlay"), QStringLiteral("Extract shell overlay icons")); - parser.addOption(shellOverlayOption); - parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("The file to open.")); - parser.addPositionalArgument(QStringLiteral("image_file_folder"), QStringLiteral("The folder to store the images.")); - parser.process(app); - const QStringList &positionalArguments = parser.positionalArguments(); - if (positionalArguments.isEmpty()) - parser.showHelp(0); - - QString imageFileRoot = positionalArguments.size() > 1 ? positionalArguments.at(1) : QDir::currentPath(); - const QFileInfo imageFileRootInfo(imageFileRoot); - if (!imageFileRootInfo.isDir()) { - std::wcerr << imageFileRoot << " is not a directory.\n"; - return 1; - } - const QString &sourceFile = positionalArguments.constFirst(); - imageFileRoot = imageFileRootInfo.absoluteFilePath() + u'/' + QFileInfo(sourceFile).baseName(); - - const PixmapEntryList pixmaps = parser.isSet(shellIconOption) - ? extractShellIcons(sourceFile, parser.isSet(shellOverlayOption)) - : extractIcons(sourceFile, parser.isSet(largeIconOption)); - - for (const auto &entry : pixmaps) { - const QString fileName = imageFileRoot + entry.name + QLatin1String(".png"); - if (!entry.pixmap.save(fileName)) { - std::wcerr << "Error writing image file " << fileName << ".\n"; - return 1; - } - std::wcout << "Wrote " << QDir::toNativeSeparators(fileName) << ".\n"; - } - return 0; -} |