LoginSignup
2
2

More than 5 years have passed since last update.

Windows版Qtでファイル拡張子からアイコンを取得する

Last updated at Posted at 2017-10-30

ファイルの実体が存在しているときは、QFileIconProviderというクラスを利用して、アイコンを取得することができます。拡張子だけわかっていて、その拡張子に関連付けられたアイコンを取得するには次のようにします。

static QIcon iconFromExtension_(QString const &ext, UINT flag)
{
    QIcon icon;
    QString name = "*." + ext;
    SHFILEINFOW shinfo;
    if (SHGetFileInfoW((wchar_t const *)name.utf16(), 0, &shinfo, sizeof(shinfo), flag | SHGFI_ICON | SHGFI_USEFILEATTRIBUTES) != 0) {
        if (shinfo.hIcon) {
            QPixmap pm = QtWin::fromHICON(shinfo.hIcon);
            if (!pm.isNull()) {
                icon = QIcon(pm);
            }
            DestroyIcon(shinfo.hIcon);
        }
    }
    return icon;
}

QIcon iconFromExtensionLarge(QString const &ext)
{
    return iconFromExtension_(ext, SHGFI_LARGEICON);
}

QIcon iconFromExtensionSmall(QString const &ext)
{
    return iconFromExtension_(ext, SHGFI_SMALLICON);
}

シェルAPIを利用すると共に、QtWin::fromHICON()というWindows専用の特殊なQt関数を使用します。そのため普段はあまり見慣れないファイルをincludeする必要があります。

#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include <commoncontrols.h>
#include <QtWinExtras/QtWinExtras>

ビルドするときは、winextrasを有効にし、shell32.libuser32.libをリンクします。Qtのプロジェクトファイルには下記のように記述します。

win32:QT += winextras
win32:LIBS += -lshell32 -luser32

上記サンプルでは、Small(16x16)とLarge(32x32)のアイコンを取得しました。普通はこれでいいのですが、シェルAPIのイメージリストからExtraLargeなアイコンも取得することができます。

QIcon iconFromExtensionExtraLarge(QString const &ext)
{
    QIcon icon;
    QString name = "*." + ext;
    SHFILEINFOW shinfo;
    if (SHGetFileInfoW((wchar_t const *)name.utf16(), 0, &shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES) != 0) {
        IImageList *pImageList;
        if (SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void **)&pImageList) == S_OK) {
            HICON hIcon;
            if (pImageList->GetIcon(shinfo.iIcon, ILD_TRANSPARENT, &hIcon) == S_OK) {
                QPixmap pm = QtWin::fromHICON(hIcon);
                if (!pm.isNull()) {
                    icon = QIcon(pm);
                }
                DestroyIcon(hIcon);
            }
            pImageList->Release();
        }
    }
    return icon;
}

ExtraLargeサイズは、もしかしたら拡張子によっては取得できないかもしれません。

通常は、Large(32x32)でいいと思うので、以下のようにして使います。取得できなかった場合は、QFileIconProviderから、既定のアイコンで代用します。

    QIcon icon = iconFromExtensionLarge("html");
    if (icon.isNull()) {
        icon = QFileIconProvider().icon(QFileIconProvider::File);
    }

※ このプログラムはWindowsの機能に依存していますので、LinuxやmacOSでは使えません。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2