Vytváření zpracovatelů miniatur
Ve Windows Vista je využití miniatur specifických pro soubory větší než v předchozích verzích Windows. Používají se ve všech zobrazeních, v dialozích a pro všechny typy souborů, které je poskytují. Zobrazení miniatury se také změnilo. Místo samostatných velikostí, jako jsou ikony a miniatury, je k dispozici souvislé spektrum velikostí s možností výběru uživatelů.
Rozhraní IThumbnailProvider zjednodušuje poskytování miniatur, což je snadnější než u starších IExtractImage nebo IExtractImage2. Upozorňujeme však, že stávající kód, který používá IExtractImage nebo IExtractImage2 je stále platný a podporovaný.
Ukázka ReceptThumbnailProvider
Ukázka RecipeThumbnailProvider v této části je součástí sady Windows Software Development Kit (SDK). Výchozí umístění instalace je C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. Tady je ale i část kódu.
Ukázka RecipeThumbnailProvider ukazuje implementaci obslužné rutiny miniatur pro nový typ souboru zaregistrovaného s příponou .recept. Ukázka demonstruje použití různých API pro obsluhu miniatur k registraci serverů COM (Component Object Model) k extrakci miniatur specifických typů souborů. Toto téma vás provede ukázkovým kódem a zvýrazní možnosti kódování a pokyny.
Obsluha miniatur musí vždy implementovat IThumbnailProvider ve spojení s jedním z těchto rozhraní:
Existují případy, kdy inicializace s datovými proudy není možná. Ve scénářích, kdy váš zpracovatel miniatur neimplementuje IInitializeWithStream, musí se rozhodnout nepracovat v izolovaném procesu, kam jej systémový indexer ve výchozím nastavení umístí při změně datového proudu. Chcete-li se odhlásit z funkce izolace procesu, nastavte následující hodnotu registru.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
Pokud implementujete IInitializeWithStream a provedete inicializaci založenou na datových proudech, je obslužná rutina bezpečnější a spolehlivější. Zakázání izolace procesů je obvykle určeno pouze pro starší obslužné rutiny; vyhněte se zakázání této funkce pro jakýkoli nový kód. IInitializeWithStream by mělo být vaší první volbou rozhraní inicializace, kdykoli je to možné.
Vzhledem k tomu, že soubor obrázku v ukázce není vložen do souboru .recept a není součástí jeho streamu souboru, IInitializeWithItem se používá v ukázce. Implementace metody IInitializeWithItem::Initialize jednoduše předává své parametry do privátních proměnných třídy.
IThumbnailProvider má pouze jednu metodu –GetThumbnail– která se volá s největší požadovanou velikostí obrázku v pixelech. Přestože se parametr jmenuje cx, jeho hodnota se používá jako maximální velikost rozměru x i y obrázku. Pokud načtená miniatura není čtvercová, je delší osa omezená cx a poměr stran původního obrázku se zachová.
Když se vrátí, GetThumbnail poskytuje popisovač načteného obrázku. Poskytuje také hodnotu, která označuje barevný formát obrázku a jestli obsahuje platné alfa informace.
Implementace GetThumbnail v ukázce začíná voláním privátní _GetBase64EncodedImageString metody.
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
Typ souboru .recept je jednoduše soubor XML zaregistrovaný jako jedinečná přípona názvu souboru. Obsahuje prvek s názvem Picture, který poskytuje relativní cestu a název souboru obrázku, který se má použít jako miniatura pro tento konkrétní soubor .recept. Element Picture se skládá z atributu Source, který určuje základní 64 kódovaný obrázek a volitelný atribut Size.
Velikost má dvě hodnoty: Malá a Velká. To vám umožní poskytnout více uzlů obrázků a s rozdílnými obrázky. Načtený obrázek poté závisí na maximální velikosti (cx) zadané ve volání GetThumbnail. Vzhledem k tomu, že Systém Windows nikdy velikost obrázku nezvětší, než je maximální velikost, lze různé obrázky poskytnout pro různá rozlišení. Pro jednoduchost však ukázka vynechá atribut Size a poskytuje pouze jeden obrázek pro všechny situace.
Metoda _GetBase64EncodedImageString, jejíž implementace je zde zobrazena, používá rozhraní API XML Document Object Model (DOM) k vyhledání uzlu Picture. Z daného uzlu extrahuje obraz z dat atributu Zdroj .
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 pak předá načtený řetězec do _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);
Metoda _GetStreamFromString, jejíž implementace je zde zobrazena, která převádí kódovaný obrázek na datový proud.
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 pak pomocí rozhraní WIC (Windows Imaging Component) API extrahuje rastrový obrázek z datového proudu a získá popisovač tohoto rastrového obrázku. Nastaví se informace o alfě, WIC se správně ukončí a metoda byla úspěšně ukončena.
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;
}