Erstellen von Miniaturansichtshandlern
Ab Windows Vista werden dateispezifische Miniaturansichten stärker verwendet als in früheren Versionen von Windows. Sie werden in allen Ansichten, in Dialogfeldern und für jeden Dateityp verwendet, der sie bereitstellt. Die Miniaturansicht wurde ebenfalls geändert. Anstelle der diskreten Größen wie Symbole und Miniaturansichten ist ein fortlaufendes Spektrum von vom Benutzer auswählbaren Größen verfügbar.
Die IThumbnailProvider-Schnittstelle macht die Bereitstellung einer Miniaturansicht einfacher als die ältere IExtractImage oder IExtractImage2. Beachten Sie jedoch, dass vorhandener Code, der IExtractImage oder IExtractImage2 verwendet, weiterhin gültig und unterstützt wird.
Das RecipeThumbnailProvider-Beispiel
Das In diesem Abschnitt sezierte RecipeThumbnailProvider-Beispiel ist im Windows Software Development Kit (SDK) enthalten. Der Standardinstallationsspeicherort ist C:\Programme\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. Der Großteil des Codes ist jedoch auch hier enthalten.
Das RecipeThumbnailProvider-Beispiel veranschaulicht die Implementierung eines Miniaturansichtshandlers für einen neuen Dateityp, der mit der Erweiterung .recipe registriert ist. Das Beispiel veranschaulicht die Verwendung der verschiedenen Miniaturansichtshandler-APIs zum Registrieren von COM-Servern (Component Object Model, Component Object Model) für benutzerdefinierte Dateitypen. In diesem Thema werden Sie durch den Beispielcode und die Auswahlmöglichkeiten und Richtlinien für die Codierung erläutert.
Ein Miniaturansichtshandler muss IThumbnailProvider immer gemeinsam mit einer der folgenden Schnittstellen implementieren:
Es gibt Fälle, in denen die Initialisierung mit Streams nicht möglich ist. In Szenarien, in denen Ihr Miniaturansichtshandler IInitializeWithStream nicht implementiert, muss er die Ausführung im isolierten Prozess deaktivieren, in dem der Systemindexer ihn standardmäßig platziert, wenn eine Änderung am Stream erfolgt. Um das Feature zur Prozessisolation zu deaktivieren, legen Sie den folgenden Registrierungswert fest.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
Wenn Sie IInitializeWithStream implementieren und eine streambasierte Initialisierung durchführen, ist Ihr Handler sicherer und zuverlässiger. In der Regel ist das Deaktivieren der Prozessisolation nur für Legacyhandler vorgesehen. Vermeiden Sie die Deaktivierung dieses Features für neuen Code. IInitializeWithStream sollte ihre erste Wahl für die Initialisierungsschnittstelle sein, wann immer möglich.
Da die Imagedatei im Beispiel nicht in die Rezeptdatei eingebettet ist und nicht Teil des Dateidatenstroms ist, wird IInitializeWithItem im Beispiel verwendet. Die Implementierung der IInitializeWithItem::Initialize-Methode übergibt ihre Parameter einfach an private Klassenvariablen.
IThumbnailProvider verfügt nur über eine Methode – GetThumbnail –, die mit der größten gewünschten Größe des Bilds in Pixel aufgerufen wird. Obwohl der Parameter cx heißt, wird sein Wert als maximale Größe der x- und y-Dimensionen des Bilds verwendet. Wenn die abgerufene Miniaturansicht nicht quadratisch ist, wird die längere Achse durch cx begrenzt, und das Seitenverhältnis des ursprünglichen Bilds bleibt erhalten.
Wenn es zurückgibt, stellt GetThumbnail ein Handle für das abgerufene Image bereit. Außerdem wird ein Wert bereitgestellt, der das Farbformat des Bilds angibt und ob es gültige Alphainformationen enthält.
Die GetThumbnail-Implementierung im Beispiel beginnt mit einem Aufruf der privaten _GetBase64EncodedImageString-Methode .
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
Der Rezeptdateityp ist einfach eine XML-Datei, die als eindeutige Dateinamenerweiterung registriert ist. Es enthält ein Element namens Picture , das den relativen Pfad und dateinamen des Bilds bereitstellt, das als Miniaturansicht für diese bestimmte REZEPT-Datei verwendet werden soll. Das Picture-Element besteht aus dem Source-Attribut , das ein Basis-64-codiertes Bild angibt, und einem optionalen Size-Attribut .
Die Größe hat zwei Werte: Klein und Groß. Dadurch können Sie mehrere Bildknoten mit separaten Images bereitstellen. Das abgerufene Bild hängt dann vom maximalen Größenwert (cx) ab, der im Aufruf von GetThumbnail angegeben wird. Da Windows das Image nie größer als die maximale Größe hat, können unterschiedliche Images für unterschiedliche Auflösungen bereitgestellt werden. Der Einfachheit halber lässt das Beispiel jedoch das Size-Attribut weg und stellt nur ein Bild für alle Situationen bereit.
Die _GetBase64EncodedImageString-Methode , deren Implementierung hier gezeigt wird, verwendet XML-DOM-APIs (Document Object Model), um den Knoten Picture abzurufen. Aus diesem Knoten extrahiert es das Image aus den Source-Attributdaten .
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 übergibt dann die abgerufene Zeichenfolge an _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);
Die _GetStreamFromString-Methode , deren Implementierung hier gezeigt wird, die das codierte Bild in einen Stream konvertiert.
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 verwendet dann WIC-APIs (Windows Imaging Component), um eine Bitmap aus dem Stream zu extrahieren und ein Handle für diese Bitmap abzurufen. Die Alphainformationen sind festgelegt, WIC wird ordnungsgemäß beendet, und die Methode wird erfolgreich beendet.
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;
}
Zugehörige Themen