Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
238 views
in Technique[技术] by (71.8m points)

c++ - Extract high resolution icon or thumbnail for file

I'm trying to get a high resolution icon or thumbnail in Windows given a full path to that file. Doesn't need to be a thumbnail —?a good looking Icon will be great. I Don't care if it's an HICON or an HBITMAP: I'm going to put it in a GDI+ object and render it into a device context.

I've tried using SHGetFileInfo (with various variations on flags), but never get more than a ~32x32 icon back, which scales horribly to the 128 pixels or so that I need.

if (!SHGetFileInfoW(path, 0, &fi, sizeof(fi),
                    SHGFI_ICON | SHGFI_ICONLARGE | SHGFI_TYPENAME))
    return GetLastError();

// fi.hIcon is a valid icon here, but it's horrible quality with
// a black mask on it. I want higher quality, and dare I dream of
// alpha channel? Mask is acceptable, i suppose.

SHGetFileInfo returns "" when I call with SHGFI_ICONLOCATION (which appears to be a known problem with that API).

I've also tried using SHCreateItemFromParsingName name with the intention of getting IThumbnailProvider, but BindToHandler always returns E_NOTIMPL for BHID_ThumbnailHandler ...

IShellItem *psi;
hr = SHCreateItemFromParsingName(path, NULL, IID_PPV_ARGS(&psi));
if (SUCCEEDED(hr))
{
    IThumbnailProvider *pThumbProvider;
    hr = psi->BindToHandler(NULL, BHID_ThumbnailHandler,
                            IID_PPV_ARGS(&pThumbProvider));
    if (SUCCEEDED(hr))
    { 
    // never get here because hr == E_NOTIMPL !!!

I've actually run the Microsoft Thumbnail Providers Sample and found that it suffers from the same problem with BindToInterface.

So, any suggestions on what else I could try? I just want something picture-y that more or less represents this file at, say, at least 100px size — just anything better than 32x32 ...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you are targeting Vista and higher, you can get a 256x256 icon from the jumbo image list. If you need to target XP, you can at least use the extra large image list, which is 48x48 (slightly better than 32x32 large).

#include <commoncontrols.h>
#include <shellapi.h>

HICON GetHighResolutionIcon(LPTSTR pszPath)
{
    // 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_TRANSPARENT, &hico);

    // Clean up
    piml->Release();

    // Return the icon
    return hico;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...