Win32 - определить, есть ли на пути значок большого размера

У меня есть код для получения гигантских значков из файла:

// Get the image list index of the icon
SHFILEINFO sfi;
if (!SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX)) return NULL;

// Get the jumbo image list
IImageList *piml;
if (FAILED(SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&piml)))) return NULL;

// Extract an icon
HICON hico;
piml->GetIcon(sfi.iIcon, ILD_SCALE|ILD_TRANSPARENT, &hico);

Теперь проблема в том, что если путь не имеет значка 256x256, связанного с ним, я не хочу, чтобы значок возвращался ImageList. (Он любезно возьмет 32x32 и поместит его в значок 256x256, который я не могу использовать).

Итак, есть ли способ узнать, есть ли у значка, который (будет) связан с путем, большой значок для него или действительно будет масштабированный 32x32? Если нет, я просто получу обычный системный значок.

ЗАМЕТКА:

Окончательное решение, вдохновленное Джонатаном ниже:

HBITMAP hbitmapForFile(LPCWSTR path, int w, int h)
{
    IShellItemImageFactory *pif;    
    HBITMAP hbm;

    SIZE sz = { w, h };
    SHCreateItemFromParsingName(path, NULL, IID_PPV_ARGS(&pif));
    pif->GetImage(sz, SIIGBF_RESIZETOFIT, &hbm);
    pif->Release();
    return hbm;
}

Я взял получившийся HBITMAP и поместил его в элемент управления STATIC с помощью SS_BITMAP.

Я понял одну важную вещь: вы не можете использовать IShellItemImageFactory из HookProc. Известное ограничение Windows; Пришлось PostMessage к окну и потом им пользоваться.


person MarcWan    schedule 18.09.2012    source источник
comment
Разве ILD_SCALE не означает, что его нужно масштабировать?   -  person user541686    schedule 18.09.2012
comment
Вы можете попробовать использовать LookupIconIdFromDirectoryEx или PrivateExtractIcons.   -  person Jay    schedule 18.09.2012
comment
@Mehrdad Да, я тоже на это надеялся, но это не помогает. :( На самом деле это вызвало проблемы в другом месте (stackoverflow.com/questions/12471020 /)   -  person MarcWan    schedule 19.09.2012
comment
@MarcWan: я думаю, что сталкивался с этой проблемой раньше ... вы случайно не пробовали использовать DrawIcon вместо DrawIconEx?   -  person user541686    schedule 19.09.2012
comment
@Mehrdad Ха-ха, хорошая мысль, но на самом деле стало только хуже :( Из-за этого даже мои большие значки выглядели крошечными. Ай.   -  person MarcWan    schedule 19.09.2012
comment
@Jay: PrivateExtractIcons — отличная идея, за исключением того, что мне нужно пропустить один шаг: Учитывая c:\docs\user\my.doc, как мне получить c:\pf\microsft\office \winword.exe|iconid где находится значок? … Предложения, где искать? Спасибо!   -  person MarcWan    schedule 19.09.2012
comment
@MarcWan: Ах, ха-ха, интересно. Если вы действительно в настроении, вы можете попробовать извлечь растровое изображение значка с помощью GetIconInfo, а затем изменить размер растрового изображения вручную с помощью StretchBlt (масштабирование HALFTONE), а затем преобразовать его обратно в значок и нарисовав его с помощью DrawIcon. =P Не уверен, что оно того стоит.   -  person user541686    schedule 19.09.2012
comment
@MarcWan: Что касается вашего последнего вопроса к Джею: IExtractIcon::GetIconLocation должен сообщить вам местоположение, но использовать его неудобно. :( Взгляните на ReactOS, может быть... как я обычно это что-то вроде LPITEMIDLIST shidl = ILCreateFromPath(normalizedPath);, затем SHBindToParent(shidl, IID_IShellFolder, &parent, &shidlChild)), затем parent->GetUIObjectOf(*this, 1, &shidlChild, IID_IExtractIcon, NULL, &pei), а затем я использую IExtractIcon.YMMV.   -  person user541686    schedule 19.09.2012
comment
@Mehrdad: Ну, вот и кикер — я знаю, КАК растягивать, но я хочу растягивать только те, которые НЕ 256x256. Откуда я знаю? 'IImageList::GetIcon' w JUMBO возвращает 256x256 независимо от значка. Нужно научиться определять, какие из них маленькие, какие нет.   -  person MarcWan    schedule 19.09.2012
comment
@MarcWan: Ах, да, я действительно понял вопрос, но я неправильно понял ваш последний комментарий, когда вы сказали, что даже мои большие значки выглядят крошечными. Так что, если вы сделаете следующее? Не используйте ILD_SCALE и попросите его предоставить вам значок исходного размера, затем используйте GetIconInfo, чтобы получить растровое изображение значка, и GetObject, чтобы получить размер растрового изображения. Это должно сказать вам размер значка.   -  person user541686    schedule 19.09.2012


Ответы (1)


Я считаю, что правильный способ сделать это — не использовать SHGetFileInfo, а вместо этого использовать метод IShellItemImageFactory::GetImage с флагом SIIGBF_THUMBNAILONLY.

person Jonathan Potter    schedule 19.09.2012
comment
ДА. Это в значительной степени сводит на нет все остальное, о чем я спрашивал за последние два дня. ВУ. - person MarcWan; 20.09.2012