SHGetFileInfo:Как получить иконку, ассоциированную с файлом?
От: dmitryx Киргизия www.moshkin.info
Дата: 06.06.08 12:27
Оценка:
Реализую IExtractIcon. Мне необходимо получить иконку ассоциированную с файлом.
Все, вроде бы, хорошо с SHGetFileInfo... НО... Как быть с большими иконками в Vista и XP?
Если вызывать SHGetFileInfo с флагами SHGFI_USEFILEATTRIBUTES и SHGFI_ICONLOCATION, то в основном
возвращается пустая строка в SHFILEINFO.szDisplayName,а индекс указывает на кэш проводника.
Приходится вызывать SHGetFileInfo с флагами SHGFI_USEFILEATTRIBUTES и SHGFI_SYSICONINDEX, чтобы
получить индекс в кэше проводника и его HIMAGELIST... Потом дергать оттуда иконки через ImageList_GetIcon.
Но иконки возвращаются маленькие, и шелл их растягивает при отображении — получается такая гадость!

Подскажите, пожалуйста, кто сталкивался, чем еще можно выдергивать иконки, ассоциированные с файлами?
Independent software developer
Re: SHGetFileInfo:Как получить иконку, ассоциированную с фай
От: Аноним  
Дата: 06.06.08 13:09
Оценка:
Здравствуйте, 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;
Re[2]: SHGetFileInfo:Как получить иконку, ассоциированную с
От: dmitryx Киргизия www.moshkin.info
Дата: 06.06.08 16:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>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;
Independent software developer
Re[3]: SHGetFileInfo:Как получить иконку, ассоциированную с
От: dmitryx Киргизия www.moshkin.info
Дата: 09.06.08 05:15
Оценка:
Спасибо исходникам 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;
}
Independent software developer
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.