diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-06-04 13:37:30 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-06-04 14:57:11 -0500 |
commit | 700b48c723531bfc38bab185f237d932144f3b26 (patch) | |
tree | 0a7acc65b0de9f47e6b2d2fa3a2994809cfcbfa6 /src/libs/dutil | |
parent | 34639850c2c07a35c1e502e174866cd8630eb8ec (diff) | |
download | wix-700b48c723531bfc38bab185f237d932144f3b26.tar.gz wix-700b48c723531bfc38bab185f237d932144f3b26.tar.bz2 wix-700b48c723531bfc38bab185f237d932144f3b26.zip |
Add thmutil Image element to allow specifying multiple resolutions.
Rename previous Image element to ImageListItem.
Last partial fix for #6155
Diffstat (limited to 'src/libs/dutil')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/thmutil.h | 14 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/thmutil.cpp | 382 |
2 files changed, 371 insertions, 25 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h index c8c6b340..6ac3711f 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h | |||
@@ -110,6 +110,7 @@ struct THEME_COLUMN | |||
110 | struct THEME_IMAGE_REFERENCE | 110 | struct THEME_IMAGE_REFERENCE |
111 | { | 111 | { |
112 | THEME_IMAGE_REFERENCE_TYPE type; | 112 | THEME_IMAGE_REFERENCE_TYPE type; |
113 | DWORD dwImageIndex; | ||
113 | DWORD dwImageInstanceIndex; | 114 | DWORD dwImageInstanceIndex; |
114 | int nX; | 115 | int nX; |
115 | int nY; | 116 | int nY; |
@@ -122,6 +123,15 @@ struct THEME_IMAGE_INSTANCE | |||
122 | Gdiplus::Bitmap* pBitmap; | 123 | Gdiplus::Bitmap* pBitmap; |
123 | }; | 124 | }; |
124 | 125 | ||
126 | struct THEME_IMAGE | ||
127 | { | ||
128 | LPWSTR sczId; | ||
129 | DWORD dwIndex; | ||
130 | |||
131 | DWORD cImageInstances; | ||
132 | THEME_IMAGE_INSTANCE* rgImageInstances; | ||
133 | }; | ||
134 | |||
125 | 135 | ||
126 | struct THEME_TAB | 136 | struct THEME_TAB |
127 | { | 137 | { |
@@ -342,6 +352,9 @@ struct THEME | |||
342 | DWORD cFonts; | 352 | DWORD cFonts; |
343 | THEME_FONT* rgFonts; | 353 | THEME_FONT* rgFonts; |
344 | 354 | ||
355 | DWORD cImages; | ||
356 | THEME_IMAGE* rgImages; | ||
357 | |||
345 | DWORD cStandaloneImages; | 358 | DWORD cStandaloneImages; |
346 | THEME_IMAGE_INSTANCE* rgStandaloneImages; | 359 | THEME_IMAGE_INSTANCE* rgStandaloneImages; |
347 | 360 | ||
@@ -356,6 +369,7 @@ struct THEME | |||
356 | 369 | ||
357 | // internal state variables -- do not use outside ThmUtil.cpp | 370 | // internal state variables -- do not use outside ThmUtil.cpp |
358 | STRINGDICT_HANDLE sdhFontDictionary; | 371 | STRINGDICT_HANDLE sdhFontDictionary; |
372 | STRINGDICT_HANDLE sdhImageDictionary; | ||
359 | HWND hwndParent; // parent for loaded controls | 373 | HWND hwndParent; // parent for loaded controls |
360 | HWND hwndHover; // current hwnd hovered over | 374 | HWND hwndHover; // current hwnd hovered over |
361 | DWORD dwCurrentPageId; | 375 | DWORD dwCurrentPageId; |
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp index ab320b1d..1e0051d4 100644 --- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp | |||
@@ -139,6 +139,12 @@ static HRESULT GetAttributeFontId( | |||
139 | __in LPCWSTR wzAttribute, | 139 | __in LPCWSTR wzAttribute, |
140 | __inout DWORD* pdwValue | 140 | __inout DWORD* pdwValue |
141 | ); | 141 | ); |
142 | static HRESULT GetAttributeImageId( | ||
143 | __in THEME* pTheme, | ||
144 | __in IXMLDOMNode* pixn, | ||
145 | __in LPCWSTR wzAttribute, | ||
146 | __inout DWORD* pdwValue | ||
147 | ); | ||
142 | static HRESULT ParseSourceXY( | 148 | static HRESULT ParseSourceXY( |
143 | __in IXMLDOMNode* pixn, | 149 | __in IXMLDOMNode* pixn, |
144 | __in THEME* pTheme, | 150 | __in THEME* pTheme, |
@@ -162,6 +168,12 @@ static HRESULT ParseFonts( | |||
162 | __in IXMLDOMElement* pElement, | 168 | __in IXMLDOMElement* pElement, |
163 | __in THEME* pTheme | 169 | __in THEME* pTheme |
164 | ); | 170 | ); |
171 | static HRESULT ParseImages( | ||
172 | __in_opt HMODULE hModule, | ||
173 | __in_opt LPCWSTR wzRelativePath, | ||
174 | __in IXMLDOMElement* pElement, | ||
175 | __in THEME* pTheme | ||
176 | ); | ||
165 | static HRESULT ParsePages( | 177 | static HRESULT ParsePages( |
166 | __in_opt HMODULE hModule, | 178 | __in_opt HMODULE hModule, |
167 | __in_opt LPCWSTR wzRelativePath, | 179 | __in_opt LPCWSTR wzRelativePath, |
@@ -371,6 +383,9 @@ static void FreeFontInstance( | |||
371 | static void FreeFont( | 383 | static void FreeFont( |
372 | __in THEME_FONT* pFont | 384 | __in THEME_FONT* pFont |
373 | ); | 385 | ); |
386 | static void FreeImage( | ||
387 | __in THEME_IMAGE* pImage | ||
388 | ); | ||
374 | static void FreeImageInstance( | 389 | static void FreeImageInstance( |
375 | __in THEME_IMAGE_INSTANCE* pImageInstance | 390 | __in THEME_IMAGE_INSTANCE* pImageInstance |
376 | ); | 391 | ); |
@@ -486,11 +501,13 @@ static HRESULT LoadControlString( | |||
486 | __in HMODULE hResModule | 501 | __in HMODULE hResModule |
487 | ); | 502 | ); |
488 | static void ResizeControls( | 503 | static void ResizeControls( |
504 | __in THEME* pTheme, | ||
489 | __in DWORD cControls, | 505 | __in DWORD cControls, |
490 | __in THEME_CONTROL* rgControls, | 506 | __in THEME_CONTROL* rgControls, |
491 | __in const RECT* prcParent | 507 | __in const RECT* prcParent |
492 | ); | 508 | ); |
493 | static void ResizeControl( | 509 | static void ResizeControl( |
510 | __in THEME* pTheme, | ||
494 | __in THEME_CONTROL* pControl, | 511 | __in THEME_CONTROL* pControl, |
495 | __in const RECT* prcParent | 512 | __in const RECT* prcParent |
496 | ); | 513 | ); |
@@ -532,6 +549,12 @@ static void GetControls( | |||
532 | __out DWORD& cControls, | 549 | __out DWORD& cControls, |
533 | __out THEME_CONTROL*& rgControls | 550 | __out THEME_CONTROL*& rgControls |
534 | ); | 551 | ); |
552 | static void ScaleImageReference( | ||
553 | __in THEME* pTheme, | ||
554 | __in THEME_IMAGE_REFERENCE* pImageRef, | ||
555 | __in int nDestWidth, | ||
556 | __in int nDestHeight | ||
557 | ); | ||
535 | static void UnloadControls( | 558 | static void UnloadControls( |
536 | __in DWORD cControls, | 559 | __in DWORD cControls, |
537 | __in THEME_CONTROL* rgControls | 560 | __in THEME_CONTROL* rgControls |
@@ -685,6 +708,11 @@ DAPI_(void) ThemeFree( | |||
685 | FreeFont(pTheme->rgFonts + i); | 708 | FreeFont(pTheme->rgFonts + i); |
686 | } | 709 | } |
687 | 710 | ||
711 | for (DWORD i = 0; i < pTheme->cImages; ++i) | ||
712 | { | ||
713 | FreeImage(pTheme->rgImages + i); | ||
714 | } | ||
715 | |||
688 | for (DWORD i = 0; i < pTheme->cStandaloneImages; ++i) | 716 | for (DWORD i = 0; i < pTheme->cStandaloneImages; ++i) |
689 | { | 717 | { |
690 | FreeImageInstance(pTheme->rgStandaloneImages + i); | 718 | FreeImageInstance(pTheme->rgStandaloneImages + i); |
@@ -708,10 +736,12 @@ DAPI_(void) ThemeFree( | |||
708 | ReleaseMem(pTheme->rgControls); | 736 | ReleaseMem(pTheme->rgControls); |
709 | ReleaseMem(pTheme->rgPages); | 737 | ReleaseMem(pTheme->rgPages); |
710 | ReleaseMem(pTheme->rgStandaloneImages); | 738 | ReleaseMem(pTheme->rgStandaloneImages); |
739 | ReleaseMem(pTheme->rgImages); | ||
711 | ReleaseMem(pTheme->rgFonts); | 740 | ReleaseMem(pTheme->rgFonts); |
712 | 741 | ||
713 | ReleaseStr(pTheme->sczCaption); | 742 | ReleaseStr(pTheme->sczCaption); |
714 | ReleaseDict(pTheme->sdhFontDictionary); | 743 | ReleaseDict(pTheme->sdhFontDictionary); |
744 | ReleaseDict(pTheme->sdhImageDictionary); | ||
715 | ReleaseMem(pTheme); | 745 | ReleaseMem(pTheme); |
716 | } | 746 | } |
717 | } | 747 | } |
@@ -1063,7 +1093,8 @@ extern "C" LRESULT CALLBACK ThemeDefWindowProc( | |||
1063 | { | 1093 | { |
1064 | pTheme->fForceResize = FALSE; | 1094 | pTheme->fForceResize = FALSE; |
1065 | ::GetClientRect(pTheme->hwndParent, &rcParent); | 1095 | ::GetClientRect(pTheme->hwndParent, &rcParent); |
1066 | ResizeControls(pTheme->cControls, pTheme->rgControls, &rcParent); | 1096 | ScaleImageReference(pTheme, &pTheme->windowImageRef, rcParent.right - rcParent.left, rcParent.bottom - rcParent.top); |
1097 | ResizeControls(pTheme, pTheme->cControls, pTheme->rgControls, &rcParent); | ||
1067 | return 0; | 1098 | return 0; |
1068 | } | 1099 | } |
1069 | break; | 1100 | break; |
@@ -1819,6 +1850,10 @@ static HRESULT ParseTheme( | |||
1819 | hr = ParseFonts(pThemeElement, pTheme); | 1850 | hr = ParseFonts(pThemeElement, pTheme); |
1820 | ThmExitOnFailure(hr, "Failed to parse theme fonts."); | 1851 | ThmExitOnFailure(hr, "Failed to parse theme fonts."); |
1821 | 1852 | ||
1853 | // Parse the images. | ||
1854 | hr = ParseImages(hModule, wzRelativePath, pThemeElement, pTheme); | ||
1855 | ThmExitOnFailure(hr, "Failed to parse theme images."); | ||
1856 | |||
1822 | // Parse the window element. | 1857 | // Parse the window element. |
1823 | hr = ParseWindow(hModule, wzRelativePath, pThemeElement, pTheme); | 1858 | hr = ParseWindow(hModule, wzRelativePath, pThemeElement, pTheme); |
1824 | ThmExitOnFailure(hr, "Failed to parse theme window element."); | 1859 | ThmExitOnFailure(hr, "Failed to parse theme window element."); |
@@ -1950,16 +1985,37 @@ static HRESULT ParseOwnerDrawImage( | |||
1950 | ) | 1985 | ) |
1951 | { | 1986 | { |
1952 | HRESULT hr = S_OK; | 1987 | HRESULT hr = S_OK; |
1988 | DWORD dwValue = 0; | ||
1953 | BOOL fXmlFound = FALSE; | 1989 | BOOL fXmlFound = FALSE; |
1954 | BOOL fFoundImage = FALSE; | 1990 | BOOL fFoundImage = FALSE; |
1955 | Gdiplus::Bitmap* pBitmap = NULL; | 1991 | Gdiplus::Bitmap* pBitmap = NULL; |
1956 | 1992 | ||
1993 | hr = GetAttributeImageId(pTheme, pElement, L"ImageId", &dwValue); | ||
1994 | ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to parse ImageId attribute."); | ||
1995 | |||
1996 | if (fXmlFound) | ||
1997 | { | ||
1998 | pImageRef->type = THEME_IMAGE_REFERENCE_TYPE_COMPLETE; | ||
1999 | pImageRef->dwImageIndex = dwValue; | ||
2000 | pImageRef->dwImageInstanceIndex = 0; | ||
2001 | fFoundImage = TRUE; | ||
2002 | } | ||
2003 | else | ||
2004 | { | ||
2005 | pImageRef->dwImageIndex = THEME_INVALID_ID; | ||
2006 | } | ||
2007 | |||
1957 | // Parse the optional background resource image. | 2008 | // Parse the optional background resource image. |
1958 | hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pBitmap); | 2009 | hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pBitmap); |
1959 | ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing control image."); | 2010 | ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing control image."); |
1960 | 2011 | ||
1961 | if (fXmlFound) | 2012 | if (fXmlFound) |
1962 | { | 2013 | { |
2014 | if (fFoundImage) | ||
2015 | { | ||
2016 | ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected image attribute with ImageId attribute."); | ||
2017 | } | ||
2018 | |||
1963 | hr = AddStandaloneImage(pTheme, &pBitmap, &pImageRef->dwImageInstanceIndex); | 2019 | hr = AddStandaloneImage(pTheme, &pBitmap, &pImageRef->dwImageInstanceIndex); |
1964 | ThmExitOnFailure(hr, "Failed to store owner draw image."); | 2020 | ThmExitOnFailure(hr, "Failed to store owner draw image."); |
1965 | 2021 | ||
@@ -2284,6 +2340,41 @@ LExit: | |||
2284 | return hr; | 2340 | return hr; |
2285 | } | 2341 | } |
2286 | 2342 | ||
2343 | static HRESULT GetAttributeImageId( | ||
2344 | __in THEME* pTheme, | ||
2345 | __in IXMLDOMNode* pixn, | ||
2346 | __in LPCWSTR wzAttribute, | ||
2347 | __inout DWORD* pdwValue | ||
2348 | ) | ||
2349 | { | ||
2350 | HRESULT hr = S_OK; | ||
2351 | BSTR bstrId = NULL; | ||
2352 | THEME_IMAGE* pImage = NULL; | ||
2353 | BOOL fXmlFound = FALSE; | ||
2354 | |||
2355 | hr = XmlGetAttribute(pixn, wzAttribute, &bstrId); | ||
2356 | ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get image id attribute."); | ||
2357 | |||
2358 | if (!fXmlFound) | ||
2359 | { | ||
2360 | ExitFunction1(hr = E_NOTFOUND); | ||
2361 | } | ||
2362 | |||
2363 | hr = DictGetValue(pTheme->sdhImageDictionary, bstrId, reinterpret_cast<void**>(&pImage)); | ||
2364 | if (E_NOTFOUND == hr) | ||
2365 | { | ||
2366 | ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unknown image id: %ls", bstrId); | ||
2367 | } | ||
2368 | ThmExitOnFailure(hr, "Failed to find image with id: %ls", bstrId); | ||
2369 | |||
2370 | *pdwValue = pImage->dwIndex; | ||
2371 | |||
2372 | LExit: | ||
2373 | ReleaseBSTR(bstrId); | ||
2374 | |||
2375 | return hr; | ||
2376 | } | ||
2377 | |||
2287 | static HRESULT ParseSourceXY( | 2378 | static HRESULT ParseSourceXY( |
2288 | __in IXMLDOMNode* pixn, | 2379 | __in IXMLDOMNode* pixn, |
2289 | __in THEME* pTheme, | 2380 | __in THEME* pTheme, |
@@ -2366,6 +2457,7 @@ static HRESULT ParseSourceXY( | |||
2366 | } | 2457 | } |
2367 | 2458 | ||
2368 | pReference->type = THEME_IMAGE_REFERENCE_TYPE_PARTIAL; | 2459 | pReference->type = THEME_IMAGE_REFERENCE_TYPE_PARTIAL; |
2460 | pReference->dwImageIndex = THEME_INVALID_ID; | ||
2369 | pReference->dwImageInstanceIndex = dwImageInstanceIndex; | 2461 | pReference->dwImageInstanceIndex = dwImageInstanceIndex; |
2370 | pReference->nX = nX; | 2462 | pReference->nX = nX; |
2371 | pReference->nY = nY; | 2463 | pReference->nY = nY; |
@@ -2747,6 +2839,131 @@ LExit: | |||
2747 | return hr; | 2839 | return hr; |
2748 | } | 2840 | } |
2749 | 2841 | ||
2842 | |||
2843 | static HRESULT ParseImages( | ||
2844 | __in_opt HMODULE hModule, | ||
2845 | __in_opt LPCWSTR wzRelativePath, | ||
2846 | __in IXMLDOMElement* pElement, | ||
2847 | __in THEME* pTheme | ||
2848 | ) | ||
2849 | { | ||
2850 | HRESULT hr = S_OK; | ||
2851 | IXMLDOMNodeList* pixnl = NULL; | ||
2852 | IXMLDOMNode* pixn = NULL; | ||
2853 | LPWSTR sczImageId = NULL; | ||
2854 | DWORD dwImageIndex = 0; | ||
2855 | Gdiplus::Bitmap* pDefaultBitmap = NULL; | ||
2856 | IXMLDOMNodeList* pixnlAlternates = NULL; | ||
2857 | IXMLDOMNode* pixnAlternate = NULL; | ||
2858 | DWORD dwInstances = 0; | ||
2859 | THEME_IMAGE_INSTANCE* pInstance = NULL; | ||
2860 | BOOL fXmlFound = FALSE; | ||
2861 | |||
2862 | hr = XmlSelectNodes(pElement, L"Image", &pixnl); | ||
2863 | ThmExitOnFailure(hr, "Failed to find font elements."); | ||
2864 | |||
2865 | hr = pixnl->get_length(reinterpret_cast<long*>(&pTheme->cImages)); | ||
2866 | ThmExitOnFailure(hr, "Failed to count the number of theme images."); | ||
2867 | |||
2868 | if (!pTheme->cImages) | ||
2869 | { | ||
2870 | ExitFunction1(hr = S_OK); | ||
2871 | } | ||
2872 | |||
2873 | pTheme->rgImages = static_cast<THEME_IMAGE*>(MemAlloc(sizeof(THEME_IMAGE) * pTheme->cImages, TRUE)); | ||
2874 | ThmExitOnNull(pTheme->rgImages, hr, E_OUTOFMEMORY, "Failed to allocate theme images."); | ||
2875 | |||
2876 | hr = DictCreateWithEmbeddedKey(&pTheme->sdhImageDictionary, pTheme->cImages, reinterpret_cast<void**>(&pTheme->rgImages), offsetof(THEME_IMAGE, sczId), DICT_FLAG_NONE); | ||
2877 | ThmExitOnFailure(hr, "Failed to create image dictionary."); | ||
2878 | |||
2879 | while (S_OK == (hr = XmlNextElement(pixnl, &pixn, NULL))) | ||
2880 | { | ||
2881 | hr = XmlGetAttributeEx(pixn, L"Id", &sczImageId); | ||
2882 | ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find image id."); | ||
2883 | |||
2884 | hr = DictKeyExists(pTheme->sdhImageDictionary, sczImageId); | ||
2885 | if (E_NOTFOUND != hr) | ||
2886 | { | ||
2887 | ThmExitOnFailure(hr, "Failed to check for duplicate image id."); | ||
2888 | ThmExitOnRootFailure(hr = E_INVALIDDATA, "Theme image id duplicated: %ls", sczImageId); | ||
2889 | } | ||
2890 | |||
2891 | THEME_IMAGE* pImage = pTheme->rgImages + dwImageIndex; | ||
2892 | pImage->sczId = sczImageId; | ||
2893 | sczImageId = NULL; | ||
2894 | pImage->dwIndex = dwImageIndex; | ||
2895 | ++dwImageIndex; | ||
2896 | |||
2897 | hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pixn, &pDefaultBitmap); | ||
2898 | ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to parse Image: %ls", pImage->sczId); | ||
2899 | |||
2900 | if (!fXmlFound) | ||
2901 | { | ||
2902 | ThmExitWithRootFailure(hr, E_INVALIDDATA, "Image didn't specify an image: %ls.", pImage->sczId); | ||
2903 | } | ||
2904 | |||
2905 | hr = DictAddValue(pTheme->sdhImageDictionary, pImage); | ||
2906 | ThmExitOnFailure(hr, "Failed to add image to dictionary."); | ||
2907 | |||
2908 | // Parse alternates, if any. | ||
2909 | hr = XmlSelectNodes(pixn, L"AlternateResolution", &pixnlAlternates); | ||
2910 | ThmExitOnFailure(hr, "Failed to select child AlternateResolution nodes."); | ||
2911 | |||
2912 | hr = pixnlAlternates->get_length(reinterpret_cast<long*>(&dwInstances)); | ||
2913 | ThmExitOnFailure(hr, "Failed to count the number of alternates."); | ||
2914 | |||
2915 | dwInstances += 1; | ||
2916 | |||
2917 | pImage->rgImageInstances = static_cast<THEME_IMAGE_INSTANCE*>(MemAlloc(sizeof(THEME_IMAGE_INSTANCE) * dwInstances, TRUE)); | ||
2918 | ThmExitOnNull(pImage->rgImageInstances, hr, E_OUTOFMEMORY, "Failed to allocate image instances."); | ||
2919 | |||
2920 | pInstance = pImage->rgImageInstances; | ||
2921 | pInstance->pBitmap = pDefaultBitmap; | ||
2922 | pDefaultBitmap = NULL; | ||
2923 | pImage->cImageInstances += 1; | ||
2924 | |||
2925 | while (S_OK == (hr = XmlNextElement(pixnlAlternates, &pixnAlternate, NULL))) | ||
2926 | { | ||
2927 | pInstance = pImage->rgImageInstances + pImage->cImageInstances; | ||
2928 | |||
2929 | hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pixnAlternate, &pInstance->pBitmap); | ||
2930 | ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to parse Image: '%ls', alternate resolution: %u", pImage->sczId, pImage->cImageInstances); | ||
2931 | |||
2932 | if (!fXmlFound) | ||
2933 | { | ||
2934 | ThmExitWithRootFailure(hr, E_INVALIDDATA, "Image: '%ls', alternate resolution: %u, didn't specify an image.", pImage->sczId, pImage->cImageInstances); | ||
2935 | } | ||
2936 | |||
2937 | ReleaseNullObject(pixnAlternate); | ||
2938 | |||
2939 | pImage->cImageInstances += 1; | ||
2940 | } | ||
2941 | |||
2942 | ReleaseNullObject(pixnlAlternates); | ||
2943 | ReleaseNullObject(pixn); | ||
2944 | } | ||
2945 | ThmExitOnFailure(hr, "Failed to enumerate all images."); | ||
2946 | |||
2947 | if (S_FALSE == hr) | ||
2948 | { | ||
2949 | hr = S_OK; | ||
2950 | } | ||
2951 | |||
2952 | LExit: | ||
2953 | if (pDefaultBitmap) | ||
2954 | { | ||
2955 | delete pDefaultBitmap; | ||
2956 | } | ||
2957 | |||
2958 | ReleaseObject(pixnAlternate); | ||
2959 | ReleaseObject(pixnlAlternates); | ||
2960 | ReleaseStr(sczImageId); | ||
2961 | ReleaseObject(pixn); | ||
2962 | ReleaseObject(pixnl); | ||
2963 | |||
2964 | return hr; | ||
2965 | } | ||
2966 | |||
2750 | static HRESULT ParsePages( | 2967 | static HRESULT ParsePages( |
2751 | __in_opt HMODULE hModule, | 2968 | __in_opt HMODULE hModule, |
2752 | __in_opt LPCWSTR wzRelativePath, | 2969 | __in_opt LPCWSTR wzRelativePath, |
@@ -2853,8 +3070,8 @@ static HRESULT ParseImageLists( | |||
2853 | hr = XmlGetAttributeEx(pixnImageList, L"Name", &pThemeImageList->sczName); | 3070 | hr = XmlGetAttributeEx(pixnImageList, L"Name", &pThemeImageList->sczName); |
2854 | ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find ImageList/@Name attribute."); | 3071 | ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find ImageList/@Name attribute."); |
2855 | 3072 | ||
2856 | hr = XmlSelectNodes(pixnImageList, L"Image", &pixnlImages); | 3073 | hr = XmlSelectNodes(pixnImageList, L"ImageListItem", &pixnlImages); |
2857 | ThmExitOnFailure(hr, "Failed to select child Image nodes."); | 3074 | ThmExitOnFailure(hr, "Failed to select child ImageListItem nodes."); |
2858 | 3075 | ||
2859 | hr = pixnlImages->get_length(reinterpret_cast<long*>(&dwImageCount)); | 3076 | hr = pixnlImages->get_length(reinterpret_cast<long*>(&dwImageCount)); |
2860 | ThmExitOnFailure(hr, "Failed to count the number of images in list."); | 3077 | ThmExitOnFailure(hr, "Failed to count the number of images in list."); |
@@ -4300,7 +4517,24 @@ static void GetImageInstance( | |||
4300 | __out const THEME_IMAGE_INSTANCE** ppInstance | 4517 | __out const THEME_IMAGE_INSTANCE** ppInstance |
4301 | ) | 4518 | ) |
4302 | { | 4519 | { |
4303 | *ppInstance = pTheme->rgStandaloneImages + pReference->dwImageInstanceIndex; | 4520 | switch (pReference->type) |
4521 | { | ||
4522 | case THEME_IMAGE_REFERENCE_TYPE_PARTIAL: | ||
4523 | case THEME_IMAGE_REFERENCE_TYPE_COMPLETE: | ||
4524 | if (THEME_INVALID_ID == pReference->dwImageIndex) | ||
4525 | { | ||
4526 | *ppInstance = pTheme->rgStandaloneImages + pReference->dwImageInstanceIndex; | ||
4527 | } | ||
4528 | else | ||
4529 | { | ||
4530 | THEME_IMAGE* pImage = pTheme->rgImages + pReference->dwImageIndex; | ||
4531 | *ppInstance = pImage->rgImageInstances + pReference->dwImageInstanceIndex; | ||
4532 | } | ||
4533 | break; | ||
4534 | default: | ||
4535 | *ppInstance = NULL; | ||
4536 | break; | ||
4537 | } | ||
4304 | } | 4538 | } |
4305 | 4539 | ||
4306 | static HRESULT DrawImageReference( | 4540 | static HRESULT DrawImageReference( |
@@ -4321,24 +4555,24 @@ static HRESULT DrawImageReference( | |||
4321 | int nHeight = 0; | 4555 | int nHeight = 0; |
4322 | 4556 | ||
4323 | GetImageInstance(pTheme, pReference, &pImageInstance); | 4557 | GetImageInstance(pTheme, pReference, &pImageInstance); |
4324 | if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pReference->type) | 4558 | ExitOnNull(pImageInstance, hr, E_INVALIDARG, "Invalid image reference for drawing."); |
4559 | |||
4560 | switch (pReference->type) | ||
4325 | { | 4561 | { |
4562 | case THEME_IMAGE_REFERENCE_TYPE_PARTIAL: | ||
4326 | nX = pReference->nX; | 4563 | nX = pReference->nX; |
4327 | nY = pReference->nY; | 4564 | nY = pReference->nY; |
4328 | nWidth = pReference->nWidth; | 4565 | nWidth = pReference->nWidth; |
4329 | nHeight = pReference->nHeight; | 4566 | nHeight = pReference->nHeight; |
4330 | } | 4567 | break; |
4331 | else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pReference->type) | 4568 | case THEME_IMAGE_REFERENCE_TYPE_COMPLETE: |
4332 | { | ||
4333 | nX = 0; | 4569 | nX = 0; |
4334 | nY = 0; | 4570 | nY = 0; |
4335 | nWidth = pImageInstance->pBitmap->GetWidth(); | 4571 | nWidth = pImageInstance->pBitmap->GetWidth(); |
4336 | nHeight = pImageInstance->pBitmap->GetHeight(); | 4572 | nHeight = pImageInstance->pBitmap->GetHeight(); |
4337 | } | 4573 | break; |
4338 | else | 4574 | default: |
4339 | { | 4575 | ExitFunction1(hr = E_INVALIDARG); // This should be unreachable because GetImageInstance should have returned null. |
4340 | AssertSz(FALSE, "Invalid image reference type for drawing"); | ||
4341 | ExitFunction1(hr = E_INVALIDARG); | ||
4342 | } | 4576 | } |
4343 | 4577 | ||
4344 | hr = DrawGdipBitmap(hdc, destX, destY, destWidth, destHeight, pImageInstance->pBitmap, nX, nY, nWidth, nHeight); | 4578 | hr = DrawGdipBitmap(hdc, destX, destY, destWidth, destHeight, pImageInstance->pBitmap, nX, nY, nWidth, nHeight); |
@@ -4424,23 +4658,22 @@ static HRESULT DrawProgressBar( | |||
4424 | } | 4658 | } |
4425 | 4659 | ||
4426 | GetImageInstance(pTheme, pImageRef, &pInstance); | 4660 | GetImageInstance(pTheme, pImageRef, &pInstance); |
4661 | ExitOnNull(pInstance, hr, E_INVALIDARG, "Invalid image reference for drawing."); | ||
4427 | 4662 | ||
4428 | if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pImageRef->type) | 4663 | switch (pImageRef->type) |
4429 | { | 4664 | { |
4665 | case THEME_IMAGE_REFERENCE_TYPE_PARTIAL: | ||
4430 | nSourceHeight = pImageRef->nHeight; | 4666 | nSourceHeight = pImageRef->nHeight; |
4431 | nSourceX = pImageRef->nX; | 4667 | nSourceX = pImageRef->nX; |
4432 | nSourceY = pImageRef->nY; | 4668 | nSourceY = pImageRef->nY; |
4433 | } | 4669 | break; |
4434 | else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pImageRef->type) | 4670 | case THEME_IMAGE_REFERENCE_TYPE_COMPLETE: |
4435 | { | ||
4436 | nSourceHeight = pInstance->pBitmap->GetHeight(); | 4671 | nSourceHeight = pInstance->pBitmap->GetHeight(); |
4437 | nSourceX = 0; | 4672 | nSourceX = 0; |
4438 | nSourceY = 0; | 4673 | nSourceY = 0; |
4439 | } | 4674 | break; |
4440 | else | 4675 | default: |
4441 | { | 4676 | ExitFunction1(hr = E_INVALIDARG); // This should be unreachable because GetImageInstance should have returned null. |
4442 | AssertSz(FALSE, "Invalid image reference type for drawing"); | ||
4443 | ExitFunction1(hr = E_INVALIDARG); | ||
4444 | } | 4677 | } |
4445 | 4678 | ||
4446 | // Draw the left side of the progress bar. | 4679 | // Draw the left side of the progress bar. |
@@ -4721,6 +4954,21 @@ static void FreeFont( | |||
4721 | } | 4954 | } |
4722 | 4955 | ||
4723 | 4956 | ||
4957 | static void FreeImage( | ||
4958 | __in THEME_IMAGE* pImage | ||
4959 | ) | ||
4960 | { | ||
4961 | if (pImage) | ||
4962 | { | ||
4963 | for (DWORD i = 0; i < pImage->cImageInstances; ++i) | ||
4964 | { | ||
4965 | FreeImageInstance(pImage->rgImageInstances + i); | ||
4966 | } | ||
4967 | |||
4968 | ReleaseStr(pImage->sczId); | ||
4969 | } | ||
4970 | } | ||
4971 | |||
4724 | static void FreeImageInstance( | 4972 | static void FreeImageInstance( |
4725 | __in THEME_IMAGE_INSTANCE* pImageInstance | 4973 | __in THEME_IMAGE_INSTANCE* pImageInstance |
4726 | ) | 4974 | ) |
@@ -6232,6 +6480,7 @@ LExit: | |||
6232 | } | 6480 | } |
6233 | 6481 | ||
6234 | static void ResizeControls( | 6482 | static void ResizeControls( |
6483 | __in THEME* pTheme, | ||
6235 | __in DWORD cControls, | 6484 | __in DWORD cControls, |
6236 | __in THEME_CONTROL* rgControls, | 6485 | __in THEME_CONTROL* rgControls, |
6237 | __in const RECT* prcParent | 6486 | __in const RECT* prcParent |
@@ -6240,11 +6489,12 @@ static void ResizeControls( | |||
6240 | for (DWORD i = 0; i < cControls; ++i) | 6489 | for (DWORD i = 0; i < cControls; ++i) |
6241 | { | 6490 | { |
6242 | THEME_CONTROL* pControl = rgControls + i; | 6491 | THEME_CONTROL* pControl = rgControls + i; |
6243 | ResizeControl(pControl, prcParent); | 6492 | ResizeControl(pTheme, pControl, prcParent); |
6244 | } | 6493 | } |
6245 | } | 6494 | } |
6246 | 6495 | ||
6247 | static void ResizeControl( | 6496 | static void ResizeControl( |
6497 | __in THEME* pTheme, | ||
6248 | __in THEME_CONTROL* pControl, | 6498 | __in THEME_CONTROL* pControl, |
6249 | __in const RECT* prcParent | 6499 | __in const RECT* prcParent |
6250 | ) | 6500 | ) |
@@ -6266,8 +6516,20 @@ static void ResizeControl( | |||
6266 | } | 6516 | } |
6267 | #endif | 6517 | #endif |
6268 | 6518 | ||
6269 | if (THEME_CONTROL_TYPE_LISTVIEW == pControl->type) | 6519 | |
6520 | switch (pControl->type) | ||
6270 | { | 6521 | { |
6522 | case THEME_CONTROL_TYPE_BUTTON: | ||
6523 | for (DWORD i = 0; i < (sizeof(pControl->Button.rgImageRef) / sizeof(pControl->Button.rgImageRef[0])); ++i) | ||
6524 | { | ||
6525 | ScaleImageReference(pTheme, pControl->Button.rgImageRef + i, w, h); | ||
6526 | } | ||
6527 | |||
6528 | break; | ||
6529 | case THEME_CONTROL_TYPE_IMAGE: | ||
6530 | ScaleImageReference(pTheme, &pControl->Image.imageRef, w, h); | ||
6531 | break; | ||
6532 | case THEME_CONTROL_TYPE_LISTVIEW: | ||
6271 | SizeListViewColumns(pControl); | 6533 | SizeListViewColumns(pControl); |
6272 | 6534 | ||
6273 | for (DWORD j = 0; j < pControl->ListView.cColumns; ++j) | 6535 | for (DWORD j = 0; j < pControl->ListView.cColumns; ++j) |
@@ -6278,12 +6540,21 @@ static void ResizeControl( | |||
6278 | return; | 6540 | return; |
6279 | } | 6541 | } |
6280 | } | 6542 | } |
6543 | |||
6544 | break; | ||
6545 | case THEME_CONTROL_TYPE_PROGRESSBAR: | ||
6546 | for (DWORD i = 0; i < pControl->ProgressBar.cImageRef; ++i) | ||
6547 | { | ||
6548 | ScaleImageReference(pTheme, pControl->ProgressBar.rgImageRef + i, 4, h); | ||
6549 | } | ||
6550 | |||
6551 | break; | ||
6281 | } | 6552 | } |
6282 | 6553 | ||
6283 | if (pControl->cControls) | 6554 | if (pControl->cControls) |
6284 | { | 6555 | { |
6285 | ::GetClientRect(pControl->hWnd, &rcControl); | 6556 | ::GetClientRect(pControl->hWnd, &rcControl); |
6286 | ResizeControls(pControl->cControls, pControl->rgControls, &rcControl); | 6557 | ResizeControls(pTheme, pControl->cControls, pControl->rgControls, &rcControl); |
6287 | } | 6558 | } |
6288 | } | 6559 | } |
6289 | 6560 | ||
@@ -6390,6 +6661,67 @@ static void ScaleControl( | |||
6390 | } | 6661 | } |
6391 | } | 6662 | } |
6392 | 6663 | ||
6664 | static void ScaleImageReference( | ||
6665 | __in THEME* pTheme, | ||
6666 | __in THEME_IMAGE_REFERENCE* pImageRef, | ||
6667 | __in int nDestWidth, | ||
6668 | __in int nDestHeight | ||
6669 | ) | ||
6670 | { | ||
6671 | THEME_IMAGE* pImage = NULL; | ||
6672 | THEME_IMAGE_INSTANCE* pDownscaleInstance = NULL; | ||
6673 | THEME_IMAGE_INSTANCE* pUpscaleInstance = NULL; | ||
6674 | THEME_IMAGE_INSTANCE* pInstance = NULL; | ||
6675 | DWORD dwIndex = THEME_INVALID_ID; | ||
6676 | DWORD64 qwPixels = 0; | ||
6677 | DWORD64 qwBestMatchPixels = 0; | ||
6678 | |||
6679 | if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pImageRef->type && THEME_INVALID_ID != pImageRef->dwImageIndex) | ||
6680 | { | ||
6681 | pImage = pTheme->rgImages + pImageRef->dwImageIndex; | ||
6682 | |||
6683 | //The dimensions of the destination rectangle are compared to all of the available sources: | ||
6684 | // 1. If there is an exact match for width and height then that source will be used (no scaling required). | ||
6685 | // 2. If there is not an exact match then the smallest source whose width and height are larger or equal to the destination will be used and downscaled. | ||
6686 | // 3. If there is still no match then the largest source will be used and upscaled. | ||
6687 | for (DWORD i = 0; i < pImage->cImageInstances; ++i) | ||
6688 | { | ||
6689 | pInstance = pImage->rgImageInstances + i; | ||
6690 | |||
6691 | if (nDestWidth == (int)pInstance->pBitmap->GetWidth() && nDestHeight == (int)pInstance->pBitmap->GetHeight()) | ||
6692 | { | ||
6693 | dwIndex = i; | ||
6694 | break; | ||
6695 | } | ||
6696 | else if (nDestWidth <= (int)pInstance->pBitmap->GetWidth() && nDestHeight <= (int)pInstance->pBitmap->GetHeight()) | ||
6697 | { | ||
6698 | qwPixels = (DWORD64)pInstance->pBitmap->GetWidth() * pInstance->pBitmap->GetHeight(); | ||
6699 | if (!pDownscaleInstance || qwPixels < qwBestMatchPixels) | ||
6700 | { | ||
6701 | qwBestMatchPixels = qwPixels; | ||
6702 | pDownscaleInstance = pInstance; | ||
6703 | dwIndex = i; | ||
6704 | } | ||
6705 | } | ||
6706 | else if (!pDownscaleInstance) | ||
6707 | { | ||
6708 | qwPixels = (DWORD64)pInstance->pBitmap->GetWidth() * pInstance->pBitmap->GetHeight(); | ||
6709 | if (!pUpscaleInstance || qwPixels > qwBestMatchPixels) | ||
6710 | { | ||
6711 | qwBestMatchPixels = qwPixels; | ||
6712 | pUpscaleInstance = pInstance; | ||
6713 | dwIndex = i; | ||
6714 | } | ||
6715 | } | ||
6716 | } | ||
6717 | |||
6718 | if (THEME_INVALID_ID != dwIndex) | ||
6719 | { | ||
6720 | pImageRef->dwImageInstanceIndex = dwIndex; | ||
6721 | } | ||
6722 | } | ||
6723 | } | ||
6724 | |||
6393 | static void UnloadControls( | 6725 | static void UnloadControls( |
6394 | __in DWORD cControls, | 6726 | __in DWORD cControls, |
6395 | __in THEME_CONTROL* rgControls | 6727 | __in THEME_CONTROL* rgControls |