Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A partir do Windows Vista, é feito maior uso de imagens em miniatura específicas do arquivo do que em versões anteriores do Windows. Eles são usados em todos os modos de exibição, em caixas de diálogo e para qualquer tipo de arquivo que os forneça. A exibição de miniaturas também foi alterada. Um espectro contínuo de tamanhos selecionáveis pelo usuário está disponível em vez dos tamanhos discretos, como ícones e miniaturas.
A interface IThumbnailProvider torna o fornecimento de uma miniatura mais simples do que o antigo IExtractImage ou IExtractImage2. Observe, no entanto, que o código existente que usa IExtractImage ou IExtractImage2 ainda é válido e suportado.
O exemplo de RecipeThumbnailProvider
O exemplo RecipeThumbnailProvider dissecado nesta seção está incluído no Windows Software Development Kit (SDK). Seu local de instalação padrão é C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. No entanto, a maior parte do código também está incluída aqui.
O exemplo de RecipeThumbnailProvider demonstra a implementação de um manipulador de miniaturas para um novo tipo de arquivo registrado com uma extensão .recipe. O exemplo ilustra o uso das diferentes APIs do manipulador de miniaturas para registrar servidores COM (Component Object Model) de extração de miniaturas para tipos de arquivo personalizados. Este tópico orienta você pelo código de exemplo, destacando opções e diretrizes de codificação.
Um manipulador de miniaturas deve sempre implementar IThumbnailProvider em conjunto com uma destas interfaces:
- IInitializeWithStream
- IInitializeWithItem
- IInitializeWithFile
Há casos em que a inicialização com fluxos não é possível. Em cenários em que seu manipulador de miniaturas não implementa IInitializeWithStream, ele deve optar por não executar no processo isolado onde o indexador do sistema o coloca por padrão quando há uma alteração no fluxo. Para desativar o recurso de isolamento de processo, configure o seguinte valor do Registro.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
Se você implementar IInitializeWithStream e fizer uma inicialização baseada em fluxo, seu manipulador será mais seguro e confiável. Normalmente, a desativação do isolamento de processos destina-se apenas a manipuladores herdados; Evite desativar esse recurso para qualquer novo código. IInitializeWithStream deve ser sua primeira escolha de interface de inicialização sempre que possível.
Como o arquivo de imagem no exemplo não está incorporado no arquivo .recipe e não faz parte de seu fluxo de arquivos, IInitializeWithItem é usado no exemplo. A implementação do método IInitializeWithItem::Initialize simplesmente passa seus parâmetros para variáveis de classe privadas.
IThumbnailProvider tem apenas um método —GetThumbnail— que é chamado com o maior tamanho desejado da imagem, em pixels. Embora o parâmetro seja nomeado cx, seu valor é usado como o tamanho máximo das dimensões x e y da imagem. Se a miniatura recuperada não for quadrada, o eixo mais longo será limitado por cx e a proporção da imagem original será preservada.
Quando ele retorna, GetThumbnail fornece um identificador para a imagem recuperada. Ele também fornece um valor que indica o formato de cor da imagem e se ela tem informações alfa válidas.
A implementação GetThumbnail no exemplo começa com uma chamada para o método _GetBase64EncodedImageString privado.
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
O tipo de arquivo .recipe é simplesmente um arquivo XML registrado como uma extensão de nome de arquivo exclusivo. Ele inclui um elemento chamado Picture que fornece o caminho relativo e o nome do arquivo da imagem para usar como miniatura para esse arquivo .recipe específico. O elemento Picture consiste no atributo Source que especifica uma imagem codificada base 64 e um atributo opcional Size.
Tamanho tem dois valores, Pequeno e Grande. Isso permite-lhe fornecer vários nós Picture com imagens separadas. A imagem recuperada depende do valor de tamanho máximo (cx) fornecido na chamada para GetThumbnail. Como o Windows nunca dimensiona a imagem maior do que seu tamanho máximo, imagens diferentes podem ser fornecidas para resoluções diferentes. No entanto, para simplificar, o exemplo omite o atributo Tamanho e fornece apenas uma imagem para todas as situações.
O método _GetBase64EncodedImageString, cuja implementação é mostrada aqui, usa APIs DOM (Document Object Model) XML para recuperar o nó Picture. Desse nó, ele extrai a imagem dos dados do 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 passa a string obtida para _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);
O método _GetStreamFromString, cuja implementação é mostrada aqui, que converte a imagem codificada em um fluxo.
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;
}
GetThumbnail usa APIs do Windows Imaging Component (WIC) para extrair um bitmap do fluxo e obter um identificador para esse bitmap. As informações alfa são definidas, o WIC é encerrado corretamente e o método termina com êxito.
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;
}