Compartir a través de


Creación de controladores de miniaturas

A partir de Windows Vista, se usa una mayor utilización de imágenes en miniatura específicas del archivo que en versiones anteriores de Windows. Se usan en todas las vistas, en diálogos y para cualquier tipo de archivo que los proporcione. También se ha cambiado la presentación de miniaturas. Hay disponible un espectro continuo de tamaños seleccionables por el usuario en lugar de los tamaños discretos, como iconos y miniaturas.

La interfaz IThumbnailProvider permite proporcionar una miniatura más sencilla que la anterior IExtractImage o IExtractImage2. Sin embargo, tenga en cuenta que el código existente que usa IExtractImage o IExtractImage2 sigue siendo válido y compatible.

El ejemplo RecipeThumbnailProvider

El ejemplo RecipeThumbnailProvider dissecado en esta sección se incluye en el Kit de desarrollo de software (SDK) de Windows. Su ubicación de instalación predeterminada es C:\Archivos de programa\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. Sin embargo, también se incluye la mayor parte del código aquí.

El ejemplo RecipeThumbnailProvider muestra la implementación de un controlador de miniaturas para un nuevo tipo de archivo registrado con una extensión .recipe. En el ejemplo se muestra el uso de las diferentes API del controlador de miniaturas para registrar servidores de modelo de objetos componentes de extracción de miniaturas (COM) para tipos de archivo personalizados. Este tema le guiará por el código de ejemplo, donde se resaltan las opciones de codificación y las directrices.

Un controlador de miniaturas siempre debe implementar IThumbnailProvider junto con una de estas interfaces:

Hay casos en los que no es posible inicializar con secuencias. En escenarios en los que el controlador de miniaturas no implementa IInitializeWithStream, debe optar por no ejecutarse en el proceso aislado donde el indexador del sistema lo coloca de forma predeterminada cuando hay un cambio en la secuencia. Para no participar en la característica de aislamiento de procesos, establezca el siguiente valor del Registro.

HKEY_CLASSES_ROOT
   CLSID
      {The CLSID of your thumbnail handler}
         DisableProcessIsolation = 1

Si implementa IInitializeWithStream y realiza una inicialización basada en secuencias, el controlador es más seguro y confiable. Normalmente, deshabilitar el aislamiento de procesos solo está pensado para controladores heredados; evite deshabilitar esta característica para cualquier código nuevo. IInitializeWithStream debe ser la primera opción de interfaz de inicialización siempre que sea posible.

Dado que el archivo de imagen del ejemplo no está incrustado en el archivo .recipe y no forma parte de su secuencia de archivos, se usa IInitializeWithItem en el ejemplo. La implementación del método IInitializeWithItem::Initialize simplemente pasa sus parámetros a variables de clase privada.

IThumbnailProvider tiene solo un método (GetThumbnail), al que se llama con el tamaño deseado más grande de la imagen, en píxeles. Aunque el parámetro se denomina cx, su valor se usa como tamaño máximo de las dimensiones x e y de la imagen. Si la miniatura recuperada no es cuadrada, el eje más largo está limitado por cx y se conserva la relación de aspecto de la imagen original.

Cuando se devuelve, GetThumbnail proporciona un identificador a la imagen recuperada. También proporciona un valor que indica el formato de color de la imagen y si tiene información alfa válida.

La implementación getThumbnail del ejemplo comienza con una llamada al método _GetBase64EncodedImageString privado.

IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx, 
                                                  HBITMAP *phbmp, 
                                                  WTS_ALPHATYPE *pdwAlpha)
{
    PWSTR pszBase64EncodedImageString;
    HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);

El tipo de archivo .recipe es simplemente un archivo XML registrado como una extensión de nombre de archivo única. Incluye un elemento denominado Picture que proporciona la ruta de acceso relativa y el nombre de archivo de la imagen que se va a usar como miniatura para este archivo .recipe determinado. El elemento Picture consta del atributo Source que especifica una imagen codificada en base 64 y un atributo Size opcional.

Size tiene dos valores, Small y Large. Esto le permite proporcionar varios nodos de imagen con imágenes independientes. La imagen recuperada depende del valor de tamaño máximo (cx) proporcionado en la llamada a GetThumbnail. Dado que Windows nunca cambia el tamaño de la imagen más grande que su tamaño máximo, se pueden proporcionar diferentes imágenes para diferentes resoluciones. Sin embargo, para simplificar, el ejemplo omite el atributo Size y proporciona solo una imagen para todas las situaciones.

El método _GetBase64EncodedImageString , cuya implementación se muestra aquí, usa las API del Modelo de objetos de documento (DOM) XML para recuperar el nodo Picture . De ese nodo extrae la imagen de los datos del atributo Source .

HRESULT CRecipeThumbProvider::_GetBase64EncodedImageString(UINT /* cx */, 
                                                           PWSTR *ppszResult)
{
    *ppszResult = NULL;

    IXMLDOMDocument *pXMLDoc;
    HRESULT hr = _LoadXMLDocument(&pXMLDoc);
    if (SUCCEEDED(hr))
    {
        BSTR bstrQuery = SysAllocString(L"Recipe/Attachments/Picture");
        hr = bstrQuery ? S_OK : E_OUTOFMEMORY;
        if (SUCCEEDED(hr))
        {
            IXMLDOMNode *pXMLNode;
            hr = pXMLDoc->selectSingleNode(bstrQuery, &pXMLNode);
            if (SUCCEEDED(hr))
            {
                IXMLDOMElement *pXMLElement;
                hr = pXMLNode->QueryInterface(&pXMLElement);
                if (SUCCEEDED(hr))
                {
                    BSTR bstrAttribute = SysAllocString(L"Source");
                    hr = bstrAttribute ? S_OK : E_OUTOFMEMORY;
                    if (SUCCEEDED(hr))
                    {
                        VARIANT varValue;
                        hr = pXMLElement->getAttribute(bstrAttribute, &varValue);
                        if (SUCCEEDED(hr))
                        {
                            if ((varValue.vt == VT_BSTR) && varValue.bstrVal && varValue.bstrVal[0])
                            {
                                hr = SHStrDupW(varValue.bstrVal, ppszResult);
                            }
                            else
                            {
                                hr = E_FAIL;
                            }
                            VariantClear(&varValue);
                        }
                        SysFreeString(bstrAttribute);
                    }
                    pXMLElement->Release();
                }
                pXMLNode->Release();
            }
            SysFreeString(bstrQuery);
        }
        pXMLDoc->Release();
    }
    return hr;
}

GetThumbnail pasa la cadena recuperada a _GetStreamFromString.

IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx, 
                                                  HBITMAP *phbmp, 
                                                  WTS_ALPHATYPE *pdwAlpha)
{
    PWSTR pszBase64EncodedImageString;
    HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
    if (SUCCEEDED(hr))
    {
        IStream *pImageStream;
        hr = _GetStreamFromString(pszBase64EncodedImageString, &pImageStream);

El método _GetStreamFromString , cuya implementación se muestra aquí, que convierte la imagen codificada en una secuencia.

HRESULT CRecipeThumbProvider::_GetStreamFromString(PCWSTR pszImageName, 
                                                   IStream **ppImageStream)
{
    HRESULT hr = E_FAIL;

    DWORD dwDecodedImageSize = 0;
    DWORD dwSkipChars        = 0;
    DWORD dwActualFormat     = 0;

    // Base64-decode the string
    BOOL fSuccess = CryptStringToBinaryW(pszImageName, 
                                         NULL, 
                                         CRYPT_STRING_BASE64,
                                         NULL, 
                                         &dwDecodedImageSize, 
                                         &dwSkipChars, 
                                         &dwActualFormat);
    if (fSuccess)
    {
        BYTE *pbDecodedImage = (BYTE*)LocalAlloc(LPTR, dwDecodedImageSize);
        if (pbDecodedImage)
        {
            fSuccess = CryptStringToBinaryW(pszImageName, 
                                            lstrlenW(pszImageName), 
                                            CRYPT_STRING_BASE64,
                                            pbDecodedImage, 
                                            &dwDecodedImageSize, 
                                            &dwSkipChars, 
                                            &dwActualFormat);
            if (fSuccess)
            {
                *ppImageStream = SHCreateMemStream(pbDecodedImage, 
                                                   dwDecodedImageSize);
                if (*ppImageStream != NULL)
                {
                    hr = S_OK;
                }
            }
            LocalFree(pbDecodedImage);
        }
    }
    return hr;
}

A continuación, GetThumbnail usa las API de Componente de creación de imágenes de Windows (WIC) para extraer un mapa de bits de la secuencia y obtener un identificador para ese mapa de bits. La información alfa se establece, WIC se cierra correctamente y el método finaliza correctamente.

IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx, 
                                                  HBITMAP *phbmp, 
                                                  WTS_ALPHATYPE *pdwAlpha)
{
    PWSTR pszBase64EncodedImageString;
    HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
    if (SUCCEEDED(hr))
    {
        IStream *pImageStream;
        hr = _GetStreamFromString(pszBase64EncodedImageString, &pImageStream);
        if (SUCCEEDED(hr))
        {
            hr = WICCreate32BitsPerPixelHBITMAP(pImageStream, 
                                                cx, 
                                                phbmp, 
                                                pdwAlpha);;

            pImageStream->Release();
        }
        CoTaskMemFree(pszBase64EncodedImageString);
    }
    return hr;
}

Controladores de miniaturas

Instrucciones del controlador de miniaturas

IID_PPV_ARGS