ファイルの実体が存在しているときは、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.lib
とuser32.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では使えません。