Skapa hanterare för miniatyrbilder
Från och med Windows Vista används filspecifika miniatyrbilder i större grad än i tidigare versioner av Windows. De används i alla vyer, i dialogrutor och för alla filtyper som tillhandahåller dem. Miniatyrvisningen ändrades också. Det finns ett kontinuerligt spektrum av användarvalsbara storlekar i stället för diskreta storlekar som ikoner och miniatyrer.
Gränssnittet IThumbnailProvider gör det enklare att ge en miniatyrbild än den äldre IExtractImage eller IExtractImage2. Observera dock att befintlig kod som använder IExtractImage eller IExtractImage2 fortfarande är giltig och stöds.
Exempel på RecipeThumbnailProvider
Det exempel på RecipeThumbnailProvider som analyseras i det här avsnittet ingår i Windows Software Development Kit (SDK). Dess standardinstallationsplats är C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. Huvuddelen av koden ingår dock även här.
Exemplet RecipeThumbnailProvider visar implementeringen av en miniatyrhanterare för en ny filtyp som registrerats med ett .recepttillägg. Exemplet illustrerar användningen av de olika miniatyrhanterar-API:erna för att registrera miniatyrutvinnings-COM-servrar (Component Object Model) för anpassade filtyper. Det här avsnittet vägleder dig genom exempelkoden och belyser kodningsalternativ och riktlinjer.
En miniatyrhanterare måste alltid implementera IThumbnailProvider tillsammans med något av följande gränssnitt:
Det finns fall där initiering med strömmar inte är möjlig. I scenarier där miniatyrhanteraren inte implementerar IInitializeWithStreammåste den välja bort att köras i den isolerade processen där systemindexeraren placerar den som standard när strömmen ändras. Om du vill välja bort funktionen för processisolering anger du följande registervärde.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
Om du implementerar IInitializeWithStream och gör en strömbaserad initiering är hanteraren säkrare och mer tillförlitlig. Normalt är inaktivering av processisolering endast avsett för äldre hanterare. undvik att inaktivera den här funktionen för ny kod. IInitializeWithStream bör vara ditt första val av initieringsgränssnitt när det är möjligt.
Eftersom bildfilen i exemplet inte är inbäddad i .recipe-filen och inte är en del av filströmmen används IInitializeWithItem i exemplet. Implementeringen av IInitializeWithItem::Initiera-metoden skickar helt enkelt dess parametrar till privata klassvariabler.
IThumbnailProvider har bara en metod–GetThumbnail– som anropas med den största önskade storleken på bilden, i bildpunkter. Även om parametern heter cxanvänds dess värde som maximal storlek för både x- och y-dimensionerna i bilden. Om den hämtade miniatyrbilden inte är kvadratisk begränsas den längre axeln av cx- och proportionerna i den ursprungliga bilden bevaras.
När den återvänder ger GetThumbnail en referens till den hämtade avbildningen. Det ger också ett värde som anger färgformatet för bilden och om den har giltig alfainformation.
GetThumbnail-implementeringen i exemplet börjar med ett anrop till metoden private _GetBase64EncodedImageString.
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
Filtypen .recipe är helt enkelt en XML-fil som registrerats som ett unikt filnamnstillägg. Den innehåller ett element som heter Picture som innehåller den relativa sökvägen och filnamnet för bilden som ska användas som miniatyrbild för just den här .receptfilen. Elementet Picture består av attributet Source som anger en base 64-kodad bild och det valfria attributet Storlek.
Storlek har två värden, Små och Stora. På så sätt kan du ange flera Bild noder med separata bilder. Bilden som hämtas beror sedan på det maximala storleksvärdet (cx) som anges i anropet till GetThumbnail. Eftersom Windows aldrig storleksanpassar avbildningen större än dess maximala storlek kan olika bilder tillhandahållas för olika upplösningar. För enkelhetens skull utelämnar exemplet attributet Size och tillhandahåller bara en bild för alla situationer.
Metoden _GetBase64EncodedImageString, vars implementering visas här, använder API:er för XML Document Object Model (DOM) för att hämta noden Picture. Från noden extraheras avbildningen från Source attributdata.
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 skickar sedan den hämtade strängen till _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);
Metoden _GetStreamFromString, vars implementering visas här, konverterar den kodade bilden till en ström.
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 använder sedan API:er för Windows Imaging Component (WIC) för att extrahera en bitmapp från strömmen och få ett handtag till bitmappen. Alfainformationen har angetts, WIC avslutas korrekt och metoden avslutas framgångsrikt.
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;
}
Relaterade ämnen
-
riktlinjer för miniatyrhanterare