アイコン

IExtractIcon::Extractを使っていると、XPのエクスプローラと同じにはできない。

  • xlsを48*48で描画しようとすると、32*32を引き伸ばしたものになる。
  • またアイコンのないexeはダミーのアイコンを取得できない。

SHGetFileInfoならばダミーのアイコンを取得できるのに。


いろいろ調べているうちにSHGetImageListを発見した。
SHIL_EXTRALARGEは32x32より大きいイメージリストを扱えるらしい。
これまたXPからしか対応していない。


またIExtractIconは遅い気がするので調べてみた。
動作が違うので単純に比較するわけにはいけないけど、デスクトップの列挙を
100回繰り返した。
SHGetFileInfoは2515, 2422, 2484ms。
IExtractIconは6219, 6266,6219ms。
あと、SHMapPIDLToSystemImageListIndexというのを見つけて、2437, 2406, 2453ms。
成績はSHMapPIDLToSystemImageListIndexが最も良い。


IExtractIconはDestroyIconをしているので遅いのかと思い試したけど、
IExtractIconはどうもキャッシュが働いていないみたい。
おそらく、より低レベルな実装なのではないだろうか。
また、SHGetFileInfoは内部でSHMapPIDLToSystemImageListIndexを
単純に呼び出しているのではないだろうか。
時間の差はそれくらいの差に思える。


SHFILEINFO inf;

SHGetFileInfo((LPCTSTR)il, 0, &inf, sizeof(SHFILEINFO),

SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
}


IExtractIcon* ie;
UINT reserved;
hr = sf->GetUIObjectOf(NULL, 1, &il, IID_IExtractIcon, &reserved, (LPVOID*)&ie);
TCHAR buf[MAX_PATH] = _T("");
UINT flags = 0;
int index = 0;
hr = ie->GetIconLocation(GIL_FORSHELL, buf, MAX_PATH, &index, &flags);
HICON smallIcon=NULL, largeIcon=NULL;
ie->Extract(buf, index, &largeIcon, &smallIcon, MAKELONG(32, 16));

DestroyIcon(smallIcon);
DestroyIcon(largeIcon);


int index = ::SHMapPIDLToSystemImageListIndex(sf, il, NULL);