Jan 282010

This code will use the IExtractImage interface in the shell to get an HBITMAP of the shell representation of a thumbnail.  This is what shows up in the Explorer as a preview of a file.  It works for any file type that has a filter installed for the Explorer.  I cobbled this code together based on other articles that I read. I couldn’t find anything callable in C++/MFC so this might be useful to someone else.  The application that produces the preview in Explorer will need to be installed on the system where this code is called.

//
// Attempt to get a thumbnail from the Windows shell.  This is faster than getting the bitmap bits
// using DirectShow and also  gives us the same thing the user sees in the Explorer.  It will only
// work if there is an IExtractImage filter registered for the file type.
//
HRESULT CVideoInfo::CreateThumbnail(LPCTSTR szPath, LPCTSTR szFile, DWORD dwWidth,
    DWORD dwHeight, HBITMAP *pThumbnail)
{
    LPITEMIDLIST pidList = NULL;
    DWORD dwPriority = 0;
    DWORD dwFlags = IEIFLAG_ASPECT;
    HRESULT hr = E_NOINTERFACE;
    SIZE size;
    WCHAR szBuffer[MAX_PATH];
    IExtractImage *peiURL = NULL;
    IShellFolder  *psfWorkDir = NULL;
    IShellFolder  *psfDesktop = NULL;

    size.cx = dwWidth;
    size.cy = dwHeight;

    int nTries = 0;

    try {
     // We need to try more than once in case the video file returns a false error
        while(!SUCCEEDED(hr) &amp;&amp; nTries++ < NUM_VIDEO_TRIES) {
            CoInitialize(NULL);

            hr = SHGetDesktopFolder(&Desktop);
            if(SUCCEEDED(hr)) {
                hr = psfDesktop->ParseDisplayName(NULL, NULL, (LPWSTR)szPath, NULL, &pidList, NULL);
                if(SUCCEEDED(hr)) {
                    hr = psfDesktop->BindToObject(pidList, NULL, IID_IShellFolder, (void **)&psfWorkDir);
                    if(SUCCEEDED(hr)) {
                        hr = psfWorkDir->ParseDisplayName(NULL, NULL, (LPWSTR)szFile, NULL, &pidList, NULL);
                        if(SUCCEEDED(hr)) {
                            LPCITEMIDLIST pidl = pidList;
                            hr = psfWorkDir->GetUIObjectOf(NULL, 1, &pidl, IID_IExtractImage, NULL,
                                                             (void **)&peiURL);
                            if(SUCCEEDED(hr)) {
                                hr = peiURL->GetLocation(szBuffer, MAX_PATH, &dwPriority, &size, 16, &dwFlags);
                                if(SUCCEEDED(hr) || hr == E_PENDING) {
                                    hr = peiURL->Extract(pThumbnail);
                                }
                            }
                        }
                    }
                }
            }

            IMallocFree(pidList);
            if(peiURL != NULL)
                peiURL->Release();
            if(psfDesktop != NULL)
                psfDesktop->Release();
            if(psfWorkDir != NULL)
                psfWorkDir->Release();
            CoUninitialize();
        }
    }
    catch(...) {
       return E_ABORT;
    }

    return hr;
}

Leave a Reply

(required)

(required)