썸네일 처리기 빌드
Windows Vista를 기준으로 이전 버전의 Windows보다 파일별 썸네일 이미지로 더 많이 사용합니다. 모든 보기, 대화 상자 및 이를 제공하는 모든 파일 형식에 사용됩니다. 축소판 그림 표시도 변경되었습니다. 아이콘 및 축소판 그림과 같은 개별 크기가 아닌 사용자가 선택할 수 있는 크기의 연속 스펙트럼을 사용할 수 있습니다.
IThumbnailProvider 인터페이스를 사용하면 이전 IExtractImage 또는 IExtractImage2보다 썸네일을 더 간단하게 제공할 수 있습니다. 그러나 IExtractImage 또는 IExtractImage2를 사용하는 기존 코드는 여전히 유효하고 지원됩니다.
RecipeThumbnailProvider 샘플
이 섹션에서 해부된 RecipeThumbnailProvider 샘플은 Windows SDK(소프트웨어 개발 키트)에 포함되어 있습니다. 기본 설치 위치는 C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WinUI\Shell\AppShellIntegration\RecipeThumbnailProvider입니다. 그러나 코드의 대부분도 여기에 포함됩니다.
RecipeThumbnailProvider 샘플은 .recipe 확장 프로그램에 등록된 새 파일 형식에 대한 썸네일 처리기의 구현을 보여 줍니다. 샘플에서는 다른 썸네일 처리기 API를 사용하여 사용자 지정 파일 형식에 대한 썸네일 추출 COM(구성 요소 개체 모델) 서버를 등록하는 방법을 보여 줍니다. 이 항목에서는 코딩 선택 사항 및 지침을 강조 표시하는 샘플 코드를 안내합니다.
썸네일 처리기는 항상 다음 인터페이스 중 하나와 함께 IThumbnailProvider 를 구현해야 합니다.
스트림을 사용하여 초기화할 수 없는 경우가 있습니다. 썸네일 처리기가 IInitializeWithStream을 구현하지 않는 시나리오에서는 스트림이 변경될 때 시스템 인덱서가 기본적으로 배치하는 격리된 프로세스에서 실행을 옵트아웃해야 합니다. 프로세스 격리 기능을 옵트아웃하려면 다음 레지스트리 값을 설정합니다.
HKEY_CLASSES_ROOT
CLSID
{The CLSID of your thumbnail handler}
DisableProcessIsolation = 1
IInitializeWithStream을 구현하고 스트림 기반 초기화를 수행하는 경우 처리기가 더 안전하고 안정적입니다. 일반적으로 프로세스 격리를 사용하지 않도록 설정하는 것은 레거시 처리기에만 사용됩니다. 새 코드에 대해 이 기능을 사용하지 않도록 설정하지 마세요. IInitializeWithStream 은 가능할 때마다 첫 번째 초기화 인터페이스 선택이어야 합니다.
샘플의 이미지 파일이 .recipe 파일에 포함되지 않고 파일 스트림의 일부가 아니므로 샘플에서 IInitializeWithItem 이 사용됩니다. IInitializeWithItem::Initialize 메서드의 구현은 단순히 해당 매개 변수를 프라이빗 클래스 변수에 전달합니다.
IThumbnailProvider 에는 이미지의 가장 큰 원하는 크기(픽셀)로 호출되는 GetThumbnail이라는 메서드가 하나만 있습니다. 매개 변수 이름은 cx이지만 해당 값은 이미지의 x 및 y 차원의 최대 크기로 사용됩니다. 검색된 썸네일이 정사각형이 아니면 더 긴 축이 cx 로 제한되고 원래 이미지의 가로 세로 비율이 유지됩니다.
반환될 때 GetThumbnail 은 검색된 이미지에 대한 핸들을 제공합니다. 또한 이미지의 색 형식과 유효한 알파 정보가 있는지 여부를 나타내는 값을 제공합니다.
샘플의 GetThumbnail 구현은 프라이빗 _GetBase64EncodedImageString 메서드 호출로 시작합니다.
IFACEMETHODIMP CRecipeThumbProvider::GetThumbnail(UINT cx,
HBITMAP *phbmp,
WTS_ALPHATYPE *pdwAlpha)
{
PWSTR pszBase64EncodedImageString;
HRESULT hr = _GetBase64EncodedImageString(cx, &pszBase64EncodedImageString);
.recipe 파일 형식은 고유한 파일 이름 확장명으로 등록된 XML 파일일 뿐입니다. 이 파일에는 이 특정 .recipe 파일의 축소판 그림으로 사용할 이미지의 상대 경로 및 파일 이름을 제공하는 Picture 라는 요소가 포함되어 있습니다. Picture 요소는 Base 64로 인코딩된 이미지와 선택적 Size 특성을 지정하는 Source 특성으로 구성됩니다.
Size 에는 Small 및 Large의 두 값이 있습니다. 이렇게 하면 여러 그림 노드에 별도의 이미지를 제공할 수 있습니다. 그런 다음 검색된 이미지는 GetThumbnail 호출에 제공된 최대 크기 값(cx)에 따라 달라집니다. Windows는 이미지 크기를 최대 크기보다 크게 지정하지 않으므로 다양한 해상도에 대해 다른 이미지를 제공할 수 있습니다. 그러나 간단히 하기 위해 샘플은 Size 특성을 생략하고 모든 상황에 대해 하나의 이미지만 제공합니다.
구현이 여기에 표시된 _GetBase64EncodedImageString 메서드는 XML DOM(문서 개체 모델) API를 사용하여 그림 노드를 검색합니다. 해당 노드에서 원본 특성 데이터에서 이미지를 추출합니다.
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 은 검색된 문자열을 _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);
구현이 여기에 표시된 _GetStreamFromString 메서드는 인코딩된 이미지를 스트림으로 변환합니다.
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 은 WIC(Windows 이미징 구성 요소) API를 사용하여 스트림에서 비트맵을 추출하고 해당 비트맵에 대한 핸들을 가져옵니다. 알파 정보가 설정되고 WIC가 제대로 종료되고 메서드가 성공적으로 종료됩니다.
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;
}
관련 항목