Miniatuurafbeeldingverwerkers bouwen
Vanaf Windows Vista wordt meer gebruik gemaakt van bestandsspecifieke miniatuurafbeeldingen dan in eerdere versies van Windows. Ze worden gebruikt in alle weergaven, in dialoogvensters en voor elk bestandstype dat ze biedt. Miniatuurweergave is ook gewijzigd. Er is een doorlopend spectrum van door de gebruiker te selecteren grootten beschikbaar in plaats van de discrete grootten, zoals pictogrammen en miniaturen.
De IThumbnailProvider interface maakt het bieden van een miniatuur eenvoudiger dan de oudere IExtractImage of IExtractImage2. Houd er echter rekening mee dat bestaande code die gebruikmaakt van IExtractImage of IExtractImage2 nog steeds geldig en ondersteund is.
RecipeThumbnailProvider Sample
In deze sectie wordt het RecipeThumbnailProvider voorbeeld besproken, dat is opgenomen in de Windows Software Development Kit (SDK). De standaardinstallatielocatie is C:\Program Files\Microsoft SDK's\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. Het grootste deel van de code wordt hier echter ook opgenomen.
In het RecipeThumbnailProvider voorbeeld ziet u de implementatie van een miniatuurhandler voor een nieuw bestandstype dat is geregistreerd met de extensie .recipe. Het voorbeeld illustreert het gebruik van de verschillende API's van de miniatuurhandler voor het registreren van COM-servers (Component Object Model) voor miniatuurextractie voor aangepaste bestandstypen. In dit onderwerp leiden we u door de voorbeeldcode, waarbij we de coderingskeuzes en richtlijnen belichten.
Een miniatuurhandler moet altijd IThumbnailProvider implementeren in combinatie met een van deze interfaces:
Er zijn gevallen waarin initialisatie met streams niet mogelijk is. In scenario's waarin uw miniatuurhandler geen IInitializeWithStream-implementeert, moet deze zich afmelden voor uitvoering in het geïsoleerde proces waarin de systeemindexeerfunctie het standaard plaatst wanneer er een verandering in de gegevensstroom plaatsvindt. Als u zich wilt afmelden voor de functie voor procesisolatie, stelt u de volgende registerwaarde in.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
Als u IInitializeWithStream- implementeert en een streamgebaseerde initialisatie uitvoert, is uw handler veiliger en betrouwbaarder. Normaal gesproken is het uitschakelen van procesisolatie alleen bedoeld voor verouderde handlers; vermijd het uitschakelen van deze functie voor nieuwe code. IInitializeWithStream- moet waar mogelijk uw eerste keuze zijn voor de initialisatie-interface.
Omdat het afbeeldingsbestand in het voorbeeld niet is ingesloten in het receptbestand en geen deel uitmaakt van de bestandsstroom, wordt IInitializeWithItem- in het voorbeeld gebruikt. De implementatie van de methode IInitializeWithItem::Initialize geeft eenvoudig de parameters door aan privéklassevariabelen.
IThumbnailProvider heeft slechts één methode(GetThumbnail) die wordt aangeroepen met de grootste gewenste grootte van de afbeelding, in pixels. Hoewel de parameter de naam cx-heeft, wordt de waarde ervan gebruikt als de maximale grootte van zowel de x- als de y-dimensie van de afbeelding. Als de opgehaalde miniatuur niet vierkant is, wordt de langere as beperkt door cx- en blijft de hoogte-breedteverhouding van de oorspronkelijke afbeelding behouden.
Bij terugkeer biedt GetThumbnail een verwijzing naar de opgehaalde afbeelding. Het biedt ook een waarde die de kleurnotatie van de afbeelding aangeeft en of deze geldige alfa-informatie bevat.
De GetThumbnail-implementatie in het voorbeeld begint met een aanroep naar de privé-_GetBase64EncodedImageString methode.
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
Het bestandstype .recept is gewoon een XML-bestand dat is geregistreerd als een unieke bestandsnaamextensie. Het bevat een element met de naam Picture dat het relatieve pad en de bestandsnaam van de afbeelding aangeeft die als miniatuur moet worden gebruikt voor dit specifieke .recipe-bestand. Het element Picture bestaat uit het kenmerk Source waarmee een base 64-gecodeerde afbeelding wordt opgegeven en een optioneel kenmerk Grootte.
Grootte heeft twee waarden: Klein en Groot. Hiermee kunt u meerdere Picture-knooppunten met afzonderlijke afbeeldingen opgeven. De opgehaalde afbeelding is vervolgens afhankelijk van de maximale groottewaarde (cx) die in de aanroep naar GetThumbnail-is opgegeven. Omdat Windows de afbeelding nooit groter maakt dan de maximale grootte, kunnen er verschillende afbeeldingen worden geleverd voor verschillende resoluties. Voor het gemak laat het voorbeeld echter het kenmerk Grootte weg en biedt slechts één afbeelding voor alle situaties.
De _GetBase64EncodedImageString methode, waarvan de implementatie hier wordt weergegeven, maakt gebruik van DOM-API's (XML Document Object Model) om het knooppunt Afbeelding op te halen. Vanuit dat knooppunt wordt de afbeelding geëxtraheerd uit de bron- kenmerkgegevens.
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 geeft de opgehaalde tekenreeks vervolgens door aan _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);
De _GetStreamFromString methode, waarvan de implementatie hier wordt weergegeven, waarmee de gecodeerde afbeelding wordt geconverteerd naar een stream.
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- gebruikt vervolgens de Windows Imaging Component (WIC) API's om een bitmap uit de stream te extraheren en een handle voor die bitmap op te halen. De alfa-informatie is ingesteld, WIC wordt correct afgesloten en de methode wordt succesvol beëindigd.
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;
}