Using IPreviewHandler to preview images

62 views Asked by At

I am attempting to use IPreviewHandler to create a dll that can preview an image in the file preview pane. I am basing it off of:

https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appshellintegration/RecipePreviewHandler

To boil down my current approach I am hard coding in the path to an image, loading it as a HBITMAP and sending it to the pane window via SendMessage(). This approach is causing the following issues:

  • I am unable to resize HBITMAP without reloading it, this seems highly inefficient.

  • I am unable to choose to change the path of the bitmap depending on which file I click on. I would ideally like to extract the file name and use that to determine a path to the bitmap in another folder of the same name.

If anyone knows or can guide me to a better approach please let me know. I would ideally like it to act like how VLC treats its preview panes with an image previewing the video alongside the software's logo.

=========================EDIT============================

Here is how I have implemented the above:

Starting with loadPreview() which loads the bitmap.

    boolean CRecipePreviewHandler::loadPreview
        (
        void
        )
    //*Description
    // change the bitmap control part of this to show the preview
    // from the file associated with m_bitmapFile
    {
        boolean r = TRUE;
        // Find dimension of bitmap
        std::ifstream file;
        file.open(m_bitmapFile, std::ios::binary);
        if (file.fail())
        {
            // File does not exist
            file.close();
            return r;
        }
        BITMAPINFOHEADER bmiHeader;
        file.seekg(sizeof(BITMAPFILEHEADER));
        file.read((char*)&bmiHeader, sizeof(BITMAPINFOHEADER));
        file.close();
        UINT cx = bmiHeader.biWidth;
        UINT cy = bmiHeader.biHeight;
        if (cx == 0 || cy == 0)
        {
            return r;
        }
    
    // transfer picture to dialog control
        m_b = (HBITMAP)LoadImage(NULL, m_bitmapFile, IMAGE_BITMAP, cx, cy, LR_LOADFROMFILE);
        r = FALSE;
        return r;
    }

Where m_b is type HBITMAP, and m_bitmapFile is type LPCWSTR containing the path to the bitmap.

This is called by DoPreview(), an override from the IPreviewHandler class which sends the bitmap to the preview pane child window.

HRESULT CRecipePreviewHandler::DoPreview()
{
    HRESULT hr = E_FAIL;
    if (_hwndPreview == NULL && _pStream) // cannot call more than once (Unload should be called before another DoPreview)
    {
        int border = 0;
        // Create the preview window
        _hwndPreview = CreateWindowExW(0, L"STATIC", NULL,
                                       SS_BITMAP | SS_CENTERIMAGE | SS_REALSIZECONTROL | WS_CHILDWINDOW,   // Always create read-only
                                       _rcParent.left+border, _rcParent.top+border, RECTWIDTH(_rcParent)+border, RECTHEIGHT(_rcParent)+border,
                                       _hwndParent, NULL, NULL, NULL);
        if (_hwndPreview == NULL)
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
        else
        {
            if (loadPreview())
            {
                hr = HRESULT_FROM_WIN32(GetLastError());
            }
            else
            {
                SendMessage(_hwndPreview, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)m_b);
                ShowWindow(_hwndPreview, SW_SHOW);
            }
        }
    }
    return hr;
}

The rest of the code is fairly standard with an initializer, an uninitializer and a rectangle size setter (I am currently not changing the size of the bitmap due to the high cost).

0

There are 0 answers