Penangan Gambar Mini Bangunan
Pada Windows Vista, penggunaan yang lebih besar terbuat dari gambar mini khusus file daripada di versi Windows sebelumnya. Mereka digunakan dalam semua tampilan, dalam dialog, dan untuk jenis file apa pun yang menyediakannya. Tampilan gambar mini juga diubah. Spektrum berkelanjutan dari ukuran yang dapat dipilih pengguna tersedia daripada ukuran diskrit seperti Ikon dan Gambar Mini.
Antarmuka IThumbnailProvider membuat penyediaan gambar mini lebih mudah daripada IExtractImage atau IExtractImage2 yang lebih lama. Namun, perhatikan bahwa kode yang ada yang menggunakan IExtractImage atau IExtractImage2 masih valid dan didukung.
Sampel RecipeThumbnailProvider
Sampel RecipeThumbnailProvider yang dibedah di bagian ini termasuk dalam Kit Pengembangan Perangkat Lunak (SDK) Windows. Lokasi penginstalan defaultnya adalah C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider. Namun, sebagian besar kode disertakan di sini juga.
Sampel RecipeThumbnailProvider menunjukkan implementasi handler gambar mini untuk jenis file baru yang terdaftar dengan ekstensi .recipe. Sampel ini menggambarkan penggunaan API penangan gambar mini yang berbeda untuk mendaftarkan server Model Objek Komponen (COM) ekstraksi gambar mini untuk jenis file kustom. Topik ini memancang Anda melalui kode sampel, menyoroti pilihan dan panduan pengodean.
Handler thumbnail harus selalu mengimplementasikan IThumbnailProvider secara bersamaan dengan salah satu antarmuka berikut:
Ada kasus di mana inisialisasi dengan aliran tidak dimungkinkan. Dalam skenario di mana handler thumbnail Anda tidak mengimplementasikan IInitializeWithStream, pengindeks harus memilih untuk tidak menjalankan dalam proses terisolasi di mana pengindeks sistem menempatkannya secara default ketika ada perubahan pada aliran. Untuk menolak fitur isolasi proses, atur nilai registri berikut.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
Jika Anda menerapkan IInitializeWithStream dan melakukan inisialisasi berbasis aliran, handler Anda lebih aman dan andal. Biasanya, menonaktifkan isolasi proses hanya ditujukan untuk penangan warisan; hindari menonaktifkan fitur ini untuk kode baru apa pun. IInitializeWithStream harus menjadi pilihan pertama antarmuka inisialisasi Anda jika memungkinkan.
Karena file gambar dalam sampel tidak disematkan dalam file .recipe dan bukan bagian dari aliran filenya, IInitializeWithItem digunakan dalam sampel. Implementasi metode IInitializeWithItem::Initialize hanya meneruskan parameternya ke variabel kelas privat.
IThumbnailProvider hanya memiliki satu metode—GetThumbnail—yang dipanggil dengan ukuran gambar terbesar yang diinginkan, dalam piksel. Meskipun parameter diberi nama cx, nilainya digunakan sebagai ukuran maksimum dimensi x dan y gambar. Jika gambar mini yang diambil tidak persegi, maka sumbu yang lebih panjang dibatasi oleh cx dan rasio aspek gambar asli dipertahankan.
Saat kembali, GetThumbnail menyediakan handel ke gambar yang diambil. Ini juga menyediakan nilai yang menunjukkan format warna gambar dan apakah gambar tersebut memiliki informasi alfa yang valid.
Implementasi GetThumbnail dalam sampel dimulai dengan panggilan ke metode _GetBase64EncodedImageString privat.
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
Jenis file .recipe hanyalah file XML yang terdaftar sebagai ekstensi nama file yang unik. Ini termasuk elemen yang disebut Gambar yang menyediakan jalur relatif dan nama file gambar untuk digunakan sebagai gambar mini untuk file .recipe khusus ini. Elemen Gambar terdiri dari atribut Sumber yang menentukan gambar dasar yang dikodekan 64, dan atribut Ukuran opsional.
Ukuran memiliki dua nilai, Kecil dan Besar. Ini memungkinkan Anda untuk menyediakan beberapa simpul Gambar dengan gambar terpisah. Gambar yang diambil kemudian tergantung pada nilai ukuran maksimum (cx) yang disediakan dalam panggilan ke GetThumbnail. Karena Windows tidak pernah mengukur gambar yang lebih besar dari ukuran maksimumnya, gambar yang berbeda dapat disediakan untuk resolusi yang berbeda. Namun, untuk kesederhanaan, sampel menghilangkan atribut Ukuran dan hanya menyediakan satu gambar untuk semua situasi.
Metode _GetBase64EncodedImageString , yang implementasinya ditampilkan di sini, menggunakan API Model Objek Dokumen (DOM) XML untuk mengambil simpul Gambar . Dari simpul itu, ia mengekstrak gambar dari data atribut Sumber .
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 kemudian meneruskan string yang diambil ke _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);
Metode _GetStreamFromString , yang implementasinya ditampilkan di sini, yang mengonversi gambar yang dikodekan menjadi aliran.
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 kemudian menggunakan API Windows Imaging Component (WIC) untuk mengekstrak bitmap dari aliran dan mendapatkan handel ke bitmap tersebut. Informasi alfa diatur, WIC keluar dengan benar, dan metode berhasil dihentikan.
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;
}