다음을 통해 공유


썸네일 처리기 빌드

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;
}

썸네일 처리기

썸네일 처리기 지침

IID_PPV_ARGS