Реализую IExtractIcon. Мне необходимо получить иконку ассоциированную с файлом.
Все, вроде бы, хорошо с SHGetFileInfo... НО... Как быть с большими иконками в Vista и XP?
Если вызывать SHGetFileInfo с флагами SHGFI_USEFILEATTRIBUTES и SHGFI_ICONLOCATION, то в основном
возвращается пустая строка в SHFILEINFO.szDisplayName,а индекс указывает на кэш проводника.
Приходится вызывать SHGetFileInfo с флагами SHGFI_USEFILEATTRIBUTES и SHGFI_SYSICONINDEX, чтобы
получить индекс в кэше проводника и его HIMAGELIST... Потом дергать оттуда иконки через ImageList_GetIcon.
Но иконки возвращаются маленькие, и шелл их растягивает при отображении — получается такая гадость!
Подскажите, пожалуйста, кто сталкивался, чем еще можно выдергивать иконки, ассоциированные с файлами?
Здравствуйте, dmitryx, Вы писали:
D>Реализую IExtractIcon. Мне необходимо получить иконку ассоциированную с файлом.
D>Все, вроде бы, хорошо с SHGetFileInfo... НО... Как быть с большими иконками в Vista и XP?
D>Если вызывать SHGetFileInfo с флагами SHGFI_USEFILEATTRIBUTES и SHGFI_ICONLOCATION, то в основном
D>возвращается пустая строка в SHFILEINFO.szDisplayName,а индекс указывает на кэш проводника.
D>Приходится вызывать SHGetFileInfo с флагами SHGFI_USEFILEATTRIBUTES и SHGFI_SYSICONINDEX, чтобы
D>получить индекс в кэше проводника и его HIMAGELIST... Потом дергать оттуда иконки через ImageList_GetIcon.
D>Но иконки возвращаются маленькие, и шелл их растягивает при отображении — получается такая гадость!
D>Подскажите, пожалуйста, кто сталкивался, чем еще можно выдергивать иконки, ассоциированные с файлами?
dwFileAttributes = 0;
uFlags = SHGFI_ICON | SHGFI_ICONLOCATION | SHGFI_LARGEICON | SHGFI_DISPLAYNAME;
SHFILEINFO::hIcon = hIcon;
Здравствуйте, Аноним, Вы писали:
А>dwFileAttributes = 0;
А>uFlags = SHGFI_ICON | SHGFI_ICONLOCATION | SHGFI_LARGEICON | SHGFI_DISPLAYNAME;
А>SHFILEINFO::hIcon = hIcon;
А>
Это тоже пробовал. Результаты те же. Только надо еще добавить SHGFI_USEFILEATTRIBUTES,
т.к. работаем мы не с реальным файлом, а только с его расширением.
Код CExtractIconImpl::Extract примерно такой:
SHFILEINFO sfi;
DWORD dwFileAttributes = 0;
UINT uFlags = SHGFI_ICON | SHGFI_ICONLOCATION | SHGFI_LARGEICON | SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES;
SHGetFileInfo( m_strExt, dwFileAttributes, &sfi, sizeof(sfi), uFlags );
*phiconLarge = sfi.hIcon;
dwFileAttributes = 0;
uFlags = SHGFI_ICON | SHGFI_ICONLOCATION | SHGFI_SMALLICON | SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES;
SHGetFileInfo( m_strExt, dwFileAttributes, &sfi, sizeof(sfi), uFlags );
*phiconSmall = sfi.hIcon;
return S_OK;
Спасибо исходникам Windows 2000.
Проблема решена очень просто:
HRESULT CExtractIconImpl::GetIconLocation(
UINT uFlags,
LPWSTR szIconFile,
UINT cchMax,
int * piIndex,
UINT * pwFlags )
{
// Готовим параметры
bool bOpen = ( uFlags & GIL_OPENICON ) == GIL_OPENICON;
bool bDir = m_item->get_type() == CItem::typeDirectory;
// Пытаемся получить размещение иконки
HRESULT hr = GetIconLocation( m_item->get_name(), bDir, bOpen, szIconFile, cchMax, piIndex );
// Если ничего не получилось - ну и фиг с ним :)
if ( FAILED(hr) ) return E_FAIL;
// Если получили пустую строку, то это значит, что иконка уже есть загруженная в кэше проводника
if ( szIconFile[0] == L'\0' ) {
// Это HACK от Microsoft. Чтобы проводник грузил иконку не из файла, а из своего кэша, ему надо вместо имени файла
// подсунуть "*" и вернуть флаг GIL_NOTFILENAME.
// P.S. под Vista тоже работает...
wcscpy( szIconFile, L"*" );
*pwFlags |= GIL_NOTFILENAME;
}
return S_OK;
}
HRESULT CExtractIconImpl::Extract(
LPCWSTR pszFile,
UINT nIconIndex,
HICON *phiconLarge,
HICON *phiconSmall,
UINT nIconSize )
{
// Делегируем проводнику загрузку иконки.
return S_FALSE;
}
HRESULT CExtractIconImpl::GetIconLocation( std::wstring strName, bool bDir, bool bOpen, LPWSTR pszFile, UINT cchMax, int *pIndex )
{
UINT uFlags = SHGFI_USEFILEATTRIBUTES | SHGFI_ICONLOCATION | SHGFI_LARGEICON;
if ( bOpen ) uFlags |= SHGFI_OPENICON;
UINT uAttributes = bDir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
CAtlString strExt;
if ( bDir ) {
strExt = L"*";
} else {
int nLastDot = strName.ReverseFind( L'.' );
if ( nLastDot != -1 )
strExt = strName.Mid(nLastDot);
}
SHFILEINFO sfi;
DWORD_PTR nResult = SHGetFileInfo( strExt, uAttributes, &sfi, sizeof(sfi), uFlags );
if (nResult == 0)
return E_FAIL;
wcsncpy( pszFile, sfi.szDisplayName, cchMax );
*pIndex = sfi.iIcon;
return S_OK;
}