aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-06-04 13:35:35 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-06-04 14:57:11 -0500
commitc0fa77405e0cc1e231dfef357b9ca6e1645c1fe3 (patch)
tree89d8c05ec5cac312d89e823727b958f7310cb5c0
parentb22a62fd6eed5bb7a2c04d51828438daa621db6c (diff)
downloadwix-c0fa77405e0cc1e231dfef357b9ca6e1645c1fe3.tar.gz
wix-c0fa77405e0cc1e231dfef357b9ca6e1645c1fe3.tar.bz2
wix-c0fa77405e0cc1e231dfef357b9ca6e1645c1fe3.zip
Require separate images for thmutil graphic Buttons and Progressbars.
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/thmutil.h44
-rw-r--r--src/libs/dutil/WixToolset.DUtil/thmutil.cpp532
2 files changed, 389 insertions, 187 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
index 2a7cabb9..d21c3e17 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
@@ -188,12 +188,38 @@ struct THEME_CONTROL
188 LPWSTR sczVisibleCondition; 188 LPWSTR sczVisibleCondition;
189 BOOL fDisableVariableFunctionality; 189 BOOL fDisableVariableFunctionality;
190 190
191 THEME_IMAGE_REFERENCE imageRef; 191 union
192 HBITMAP hImage; 192 {
193 HICON hIcon; 193 struct
194 {
195 THEME_IMAGE_REFERENCE rgImageRef[4];
196 } Button;
197 struct
198 {
199 HBITMAP hImage;
200 HICON hIcon;
201
202 DWORD cConditionalNotes;
203 THEME_CONDITIONAL_TEXT* rgConditionalNotes;
204 } CommandLink;
205 struct
206 {
207 THEME_IMAGE_REFERENCE imageRef;
208 } Image;
209 struct
210 {
211 // Don't free these; it's just a handle to the central image lists stored in THEME. The handle is freed once, there.
212 HIMAGELIST rghImageList[4];
194 213
195 // Don't free these; it's just a handle to the central image lists stored in THEME. The handle is freed once, there. 214 THEME_COLUMN* ptcColumns;
196 HIMAGELIST rghImageList[4]; 215 DWORD cColumns;
216 } ListView;
217 struct
218 {
219 DWORD cImageRef;
220 THEME_IMAGE_REFERENCE* rgImageRef;
221 } ProgressBar;
222 };
197 223
198 DWORD dwStyle; 224 DWORD dwStyle;
199 DWORD dwExtendedStyle; 225 DWORD dwExtendedStyle;
@@ -218,10 +244,6 @@ struct THEME_CONTROL
218 DWORD dwFontHoverId; 244 DWORD dwFontHoverId;
219 DWORD dwFontSelectedId; 245 DWORD dwFontSelectedId;
220 246
221 // Used by listview controls
222 THEME_COLUMN *ptcColumns;
223 DWORD cColumns;
224
225 // Used by radio button controls 247 // Used by radio button controls
226 BOOL fLastRadioButton; 248 BOOL fLastRadioButton;
227 LPWSTR sczValue; 249 LPWSTR sczValue;
@@ -235,10 +257,6 @@ struct THEME_CONTROL
235 DWORD cConditionalText; 257 DWORD cConditionalText;
236 THEME_CONDITIONAL_TEXT* rgConditionalText; 258 THEME_CONDITIONAL_TEXT* rgConditionalText;
237 259
238 // Used by command link controls
239 DWORD cConditionalNotes;
240 THEME_CONDITIONAL_TEXT* rgConditionalNotes;
241
242 // state variables that should be ignored 260 // state variables that should be ignored
243 HWND hWnd; 261 HWND hWnd;
244 DWORD dwData; // type specific data 262 DWORD dwData; // type specific data
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
index 363c3be1..5292d1e3 100644
--- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
@@ -104,6 +104,15 @@ static HRESULT ParseOwnerDrawImage(
104 __in_z_opt LPCWSTR wzRelativePath, 104 __in_z_opt LPCWSTR wzRelativePath,
105 __in THEME* pTheme, 105 __in THEME* pTheme,
106 __in IXMLDOMNode* pElement, 106 __in IXMLDOMNode* pElement,
107 __in_z LPCWSTR wzElementName,
108 __in THEME_CONTROL* pControl,
109 __in THEME_IMAGE_REFERENCE* pImageRef
110 );
111static HRESULT ParseButtonImages(
112 __in_opt HMODULE hModule,
113 __in_z_opt LPCWSTR wzRelativePath,
114 __in THEME* pTheme,
115 __in IXMLDOMNode* pElement,
107 __in THEME_CONTROL* pControl 116 __in THEME_CONTROL* pControl
108 ); 117 );
109static HRESULT ParseCommandLinkImage( 118static HRESULT ParseCommandLinkImage(
@@ -112,6 +121,13 @@ static HRESULT ParseCommandLinkImage(
112 __in IXMLDOMNode* pElement, 121 __in IXMLDOMNode* pElement,
113 __in THEME_CONTROL* pControl 122 __in THEME_CONTROL* pControl
114 ); 123 );
124static HRESULT ParseProgressBarImages(
125 __in_opt HMODULE hModule,
126 __in_z_opt LPCWSTR wzRelativePath,
127 __in THEME* pTheme,
128 __in IXMLDOMNode* pElement,
129 __in THEME_CONTROL* pControl
130 );
115static HRESULT GetAttributeCoordinateOrDimension( 131static HRESULT GetAttributeCoordinateOrDimension(
116 __in IXMLDOMNode* pixn, 132 __in IXMLDOMNode* pixn,
117 __in LPCWSTR wzAttribute, 133 __in LPCWSTR wzAttribute,
@@ -1528,11 +1544,14 @@ DAPI_(HRESULT) ThemeSetProgressControlColor(
1528 THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); 1544 THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
1529 1545
1530 // Only set color on owner draw progress bars. 1546 // Only set color on owner draw progress bars.
1531 if (pControl && (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW)) 1547 if (pControl && (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW) && THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
1532 { 1548 {
1533 DWORD dwCurrentColor = HIWORD(pControl->dwData); 1549 if (pControl->ProgressBar.cImageRef <= dwColorIndex)
1550 {
1551 ThmExitWithRootFailure(hr, E_INVALIDARG, "Invalid progress bar color index: %u", dwColorIndex);
1552 }
1534 1553
1535 if (dwCurrentColor != dwColorIndex) 1554 if (HIWORD(pControl->dwData) != dwColorIndex)
1536 { 1555 {
1537 DWORD dwCurrentProgress = LOWORD(pControl->dwData); 1556 DWORD dwCurrentProgress = LOWORD(pControl->dwData);
1538 pControl->dwData = MAKEDWORD(dwCurrentProgress, dwColorIndex); 1557 pControl->dwData = MAKEDWORD(dwCurrentProgress, dwColorIndex);
@@ -1923,7 +1942,9 @@ static HRESULT ParseOwnerDrawImage(
1923 __in_z_opt LPCWSTR wzRelativePath, 1942 __in_z_opt LPCWSTR wzRelativePath,
1924 __in THEME* pTheme, 1943 __in THEME* pTheme,
1925 __in IXMLDOMNode* pElement, 1944 __in IXMLDOMNode* pElement,
1926 __in THEME_CONTROL* pControl 1945 __in_z LPCWSTR wzElementName,
1946 __in THEME_CONTROL* pControl,
1947 __in THEME_IMAGE_REFERENCE* pImageRef
1927 ) 1948 )
1928{ 1949{
1929 HRESULT hr = S_OK; 1950 HRESULT hr = S_OK;
@@ -1937,15 +1958,15 @@ static HRESULT ParseOwnerDrawImage(
1937 1958
1938 if (fXmlFound) 1959 if (fXmlFound)
1939 { 1960 {
1940 hr = AddStandaloneImage(pTheme, &pBitmap, &pControl->imageRef.dwImageInstanceIndex); 1961 hr = AddStandaloneImage(pTheme, &pBitmap, &pImageRef->dwImageInstanceIndex);
1941 ThmExitOnFailure(hr, "Failed to store owner draw image."); 1962 ThmExitOnFailure(hr, "Failed to store owner draw image.");
1942 1963
1943 pControl->imageRef.type = THEME_IMAGE_REFERENCE_TYPE_COMPLETE; 1964 pImageRef->type = THEME_IMAGE_REFERENCE_TYPE_COMPLETE;
1944 1965
1945 fFoundImage = TRUE; 1966 fFoundImage = TRUE;
1946 } 1967 }
1947 1968
1948 hr = ParseSourceXY(pElement, pTheme, pControl->nWidth, pControl->nHeight, &pControl->imageRef); 1969 hr = ParseSourceXY(pElement, pTheme, pControl->nWidth, pControl->nHeight, pImageRef);
1949 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get control SourceX and SourceY attributes."); 1970 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get control SourceX and SourceY attributes.");
1950 1971
1951 if (fXmlFound) 1972 if (fXmlFound)
@@ -1962,9 +1983,9 @@ static HRESULT ParseOwnerDrawImage(
1962 fFoundImage = TRUE; 1983 fFoundImage = TRUE;
1963 } 1984 }
1964 1985
1965 if (THEME_CONTROL_TYPE_IMAGE == pControl->type && !fFoundImage) 1986 if (!fFoundImage)
1966 { 1987 {
1967 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Image control didn't specify an image."); 1988 ThmExitWithRootFailure(hr, E_INVALIDDATA, "%ls didn't specify an image.", wzElementName);
1968 } 1989 }
1969 1990
1970LExit: 1991LExit:
@@ -1977,6 +1998,97 @@ LExit:
1977} 1998}
1978 1999
1979 2000
2001static HRESULT ParseButtonImages(
2002 __in_opt HMODULE hModule,
2003 __in_z_opt LPCWSTR wzRelativePath,
2004 __in THEME* pTheme,
2005 __in IXMLDOMNode* pElement,
2006 __in THEME_CONTROL* pControl
2007 )
2008{
2009 HRESULT hr = S_OK;
2010 DWORD i = 0;
2011 IXMLDOMNodeList* pixnl = NULL;
2012 IXMLDOMNode* pixnChild = NULL;
2013 BSTR bstrType = NULL;
2014 THEME_IMAGE_REFERENCE* pImageRef = NULL;
2015 THEME_IMAGE_REFERENCE* pDefaultImageRef = NULL;
2016 THEME_IMAGE_REFERENCE* pFocusImageRef = NULL;
2017 THEME_IMAGE_REFERENCE* pHoverImageRef = NULL;
2018 THEME_IMAGE_REFERENCE* pSelectedImageRef = NULL;
2019
2020 hr = XmlSelectNodes(pElement, L"ButtonImage|ButtonFocusImage|ButtonHoverImage|ButtonSelectedImage", &pixnl);
2021 ThmExitOnFailure(hr, "Failed to select child ButtonImage nodes.");
2022
2023 i = 0;
2024 while (S_OK == (hr = XmlNextElement(pixnl, &pixnChild, &bstrType)))
2025 {
2026 if (!bstrType)
2027 {
2028 hr = E_UNEXPECTED;
2029 ThmExitOnFailure(hr, "Null element encountered!");
2030 }
2031
2032 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrType, -1, L"ButtonFocusImage", -1))
2033 {
2034 if (pFocusImageRef)
2035 {
2036 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Duplicate ButtonFocusImage element.");
2037 }
2038
2039 pImageRef = pFocusImageRef = pControl->Button.rgImageRef + 3;
2040 }
2041 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrType, -1, L"ButtonHoverImage", -1))
2042 {
2043 if (pHoverImageRef)
2044 {
2045 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Duplicate ButtonHoverImage element.");
2046 }
2047
2048 pImageRef = pHoverImageRef = pControl->Button.rgImageRef + 1;
2049 }
2050 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrType, -1, L"ButtonSelectedImage", -1))
2051 {
2052 if (pSelectedImageRef)
2053 {
2054 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Duplicate ButtonSelectedImage element.");
2055 }
2056
2057 pImageRef = pSelectedImageRef = pControl->Button.rgImageRef + 2;
2058 }
2059 else
2060 {
2061 if (pDefaultImageRef)
2062 {
2063 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Duplicate ButtonImage element.");
2064 }
2065
2066 pImageRef = pDefaultImageRef = pControl->Button.rgImageRef;
2067 }
2068
2069 hr = ParseOwnerDrawImage(hModule, wzRelativePath, pTheme, pixnChild, bstrType, pControl, pImageRef);
2070 ThmExitOnFailure(hr, "Failed when parsing %ls", bstrType);
2071
2072 ReleaseBSTR(bstrType);
2073 ReleaseNullObject(pixnChild);
2074 ++i;
2075 }
2076
2077 if (!pDefaultImageRef && (pFocusImageRef || pHoverImageRef || pSelectedImageRef) ||
2078 pDefaultImageRef && (!pHoverImageRef || !pSelectedImageRef))
2079 {
2080 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Graphic buttons require ButtonImage, ButtonHoverImage, and ButtonSelectedImage.");
2081 }
2082
2083LExit:
2084 ReleaseObject(pixnl);
2085 ReleaseObject(pixnChild);
2086 ReleaseBSTR(bstrType);
2087
2088 return hr;
2089}
2090
2091
1980static HRESULT ParseCommandLinkImage( 2092static HRESULT ParseCommandLinkImage(
1981 __in_opt HMODULE hModule, 2093 __in_opt HMODULE hModule,
1982 __in_z_opt LPCWSTR wzRelativePath, 2094 __in_z_opt LPCWSTR wzRelativePath,
@@ -1997,7 +2109,7 @@ static HRESULT ParseCommandLinkImage(
1997 2109
1998 if (pBitmap) 2110 if (pBitmap)
1999 { 2111 {
2000 hr = GdipBitmapToGdiBitmap(pBitmap, &pControl->hImage); 2112 hr = GdipBitmapToGdiBitmap(pBitmap, &pControl->CommandLink.hImage);
2001 ThmExitOnFailure(hr, "Failed to convert bitmap for CommandLink."); 2113 ThmExitOnFailure(hr, "Failed to convert bitmap for CommandLink.");
2002 } 2114 }
2003 2115
@@ -2011,8 +2123,8 @@ static HRESULT ParseCommandLinkImage(
2011 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected IconResource attribute with image attribute."); 2123 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected IconResource attribute with image attribute.");
2012 } 2124 }
2013 2125
2014 pControl->hIcon = reinterpret_cast<HICON>(::LoadImageW(hModule, MAKEINTRESOURCEW(wResourceId), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE)); 2126 pControl->CommandLink.hIcon = reinterpret_cast<HICON>(::LoadImageW(hModule, MAKEINTRESOURCEW(wResourceId), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
2015 ThmExitOnNullWithLastError(pControl->hIcon, hr, "Failed to load icon."); 2127 ThmExitOnNullWithLastError(pControl->CommandLink.hIcon, hr, "Failed to load icon.");
2016 } 2128 }
2017 2129
2018 hr = XmlGetAttribute(pElement, L"IconFile", &bstr); 2130 hr = XmlGetAttribute(pElement, L"IconFile", &bstr);
@@ -2024,7 +2136,7 @@ static HRESULT ParseCommandLinkImage(
2024 { 2136 {
2025 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected IconFile attribute with image attribute."); 2137 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected IconFile attribute with image attribute.");
2026 } 2138 }
2027 else if (pControl->hIcon) 2139 else if (pControl->CommandLink.hIcon)
2028 { 2140 {
2029 ThmExitWithRootFailure(hr, E_INVALIDDATA, "IconFile attribute can't be specified with IconResource attribute."); 2141 ThmExitWithRootFailure(hr, E_INVALIDDATA, "IconFile attribute can't be specified with IconResource attribute.");
2030 } 2142 }
@@ -2040,8 +2152,8 @@ static HRESULT ParseCommandLinkImage(
2040 ThmExitOnFailure(hr, "Failed to get image filename."); 2152 ThmExitOnFailure(hr, "Failed to get image filename.");
2041 } 2153 }
2042 2154
2043 pControl->hIcon = reinterpret_cast<HICON>(::LoadImageW(NULL, sczIconFile, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE)); 2155 pControl->CommandLink.hIcon = reinterpret_cast<HICON>(::LoadImageW(NULL, sczIconFile, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE));
2044 ThmExitOnNullWithLastError(pControl->hIcon, hr, "Failed to load icon: %ls.", sczIconFile); 2156 ThmExitOnNullWithLastError(pControl->CommandLink.hIcon, hr, "Failed to load icon: %ls.", sczIconFile);
2045 } 2157 }
2046 2158
2047 ThmExitOnUnexpectedAttribute(hr, pElement, L"CommandLink", L"SourceX"); 2159 ThmExitOnUnexpectedAttribute(hr, pElement, L"CommandLink", L"SourceX");
@@ -2060,6 +2172,53 @@ LExit:
2060} 2172}
2061 2173
2062 2174
2175static HRESULT ParseProgressBarImages(
2176 __in_opt HMODULE hModule,
2177 __in_z_opt LPCWSTR wzRelativePath,
2178 __in THEME* pTheme,
2179 __in IXMLDOMNode* pElement,
2180 __in THEME_CONTROL* pControl
2181 )
2182{
2183 HRESULT hr = S_OK;
2184 DWORD i = 0;
2185 IXMLDOMNodeList* pixnl = NULL;
2186 IXMLDOMNode* pixnChild = NULL;
2187
2188 hr = XmlSelectNodes(pElement, L"ProgressbarImage", &pixnl);
2189 ThmExitOnFailure(hr, "Failed to select child ProgressbarImage nodes.");
2190
2191 hr = pixnl->get_length(reinterpret_cast<long*>(&pControl->ProgressBar.cImageRef));
2192 ThmExitOnFailure(hr, "Failed to count the number of ProgressbarImage nodes.");
2193
2194 if (!pControl->ProgressBar.cImageRef)
2195 {
2196 ExitFunction();
2197 }
2198
2199 MemAllocArray(reinterpret_cast<LPVOID*>(&pControl->ProgressBar.rgImageRef), sizeof(THEME_IMAGE_REFERENCE), pControl->ProgressBar.cImageRef);
2200 ThmExitOnNull(pControl->ProgressBar.rgImageRef, hr, E_OUTOFMEMORY, "Failed to allocate progress bar images.");
2201
2202 i = 0;
2203 while (S_OK == (hr = XmlNextElement(pixnl, &pixnChild, NULL)))
2204 {
2205 THEME_IMAGE_REFERENCE* pImageRef = pControl->ProgressBar.rgImageRef + i;
2206
2207 hr = ParseOwnerDrawImage(hModule, wzRelativePath, pTheme, pixnChild, L"ProgressbarImage", pControl, pImageRef);
2208 ThmExitOnFailure(hr, "Failed when parsing ProgressbarImage image: %u.", i);
2209
2210 ReleaseNullObject(pixnChild);
2211 ++i;
2212 }
2213
2214LExit:
2215 ReleaseObject(pixnl);
2216 ReleaseObject(pixnChild);
2217
2218 return hr;
2219}
2220
2221
2063static HRESULT GetAttributeCoordinateOrDimension( 2222static HRESULT GetAttributeCoordinateOrDimension(
2064 __in IXMLDOMNode* pixn, 2223 __in IXMLDOMNode* pixn,
2065 __in LPCWSTR wzAttribute, 2224 __in LPCWSTR wzAttribute,
@@ -3005,10 +3164,16 @@ static HRESULT ParseControl(
3005 ThmExitOnFailure(hr, "Failed while parsing CommandLink image."); 3164 ThmExitOnFailure(hr, "Failed while parsing CommandLink image.");
3006 break; 3165 break;
3007 case THEME_CONTROL_TYPE_BUTTON: 3166 case THEME_CONTROL_TYPE_BUTTON:
3167 hr = ParseButtonImages(hModule, wzRelativePath, pTheme, pixn, pControl);
3168 ThmExitOnFailure(hr, "Failed while parsing Button images.");
3169 break;
3008 case THEME_CONTROL_TYPE_IMAGE: 3170 case THEME_CONTROL_TYPE_IMAGE:
3171 hr = ParseOwnerDrawImage(hModule, wzRelativePath, pTheme, pixn, wzElementName, pControl, &pControl->Image.imageRef);
3172 ThmExitOnFailure(hr, "Failed while parsing ImageControl image.");
3173 break;
3009 case THEME_CONTROL_TYPE_PROGRESSBAR: 3174 case THEME_CONTROL_TYPE_PROGRESSBAR:
3010 hr = ParseOwnerDrawImage(hModule, wzRelativePath, pTheme, pixn, pControl); 3175 hr = ParseProgressBarImages(hModule, wzRelativePath, pTheme, pixn, pControl);
3011 ThmExitOnFailure(hr, "Failed while parsing OwnerDraw image."); 3176 ThmExitOnFailure(hr, "Failed while parsing Progressbar images.");
3012 break; 3177 break;
3013 default: 3178 default:
3014 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"ImageId"); 3179 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"ImageId");
@@ -3161,7 +3326,7 @@ static HRESULT ParseControl(
3161 3326
3162 if (fXmlFound) 3327 if (fXmlFound)
3163 { 3328 {
3164 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[0]); 3329 hr = FindImageList(pTheme, bstrText, &pControl->ListView.rghImageList[0]);
3165 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageList for ListView.", bstrText); 3330 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageList for ListView.", bstrText);
3166 } 3331 }
3167 3332
@@ -3170,7 +3335,7 @@ static HRESULT ParseControl(
3170 3335
3171 if (fXmlFound) 3336 if (fXmlFound)
3172 { 3337 {
3173 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[1]); 3338 hr = FindImageList(pTheme, bstrText, &pControl->ListView.rghImageList[1]);
3174 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListSmall for ListView.", bstrText); 3339 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListSmall for ListView.", bstrText);
3175 } 3340 }
3176 3341
@@ -3179,7 +3344,7 @@ static HRESULT ParseControl(
3179 3344
3180 if (fXmlFound) 3345 if (fXmlFound)
3181 { 3346 {
3182 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[2]); 3347 hr = FindImageList(pTheme, bstrText, &pControl->ListView.rghImageList[2]);
3183 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListState for ListView.", bstrText); 3348 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListState for ListView.", bstrText);
3184 } 3349 }
3185 3350
@@ -3188,7 +3353,7 @@ static HRESULT ParseControl(
3188 3353
3189 if (fXmlFound) 3354 if (fXmlFound)
3190 { 3355 {
3191 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[3]); 3356 hr = FindImageList(pTheme, bstrText, &pControl->ListView.rghImageList[3]);
3192 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListGroupHeader for ListView.", bstrText); 3357 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListGroupHeader for ListView.", bstrText);
3193 } 3358 }
3194 3359
@@ -3446,18 +3611,18 @@ static HRESULT ParseColumns(
3446 hr = XmlSelectNodes(pixn, L"Column", &pixnl); 3611 hr = XmlSelectNodes(pixn, L"Column", &pixnl);
3447 ThmExitOnFailure(hr, "Failed to select child column nodes."); 3612 ThmExitOnFailure(hr, "Failed to select child column nodes.");
3448 3613
3449 hr = pixnl->get_length(reinterpret_cast<long*>(&pControl->cColumns)); 3614 hr = pixnl->get_length(reinterpret_cast<long*>(&pControl->ListView.cColumns));
3450 ThmExitOnFailure(hr, "Failed to count the number of control columns."); 3615 ThmExitOnFailure(hr, "Failed to count the number of control columns.");
3451 3616
3452 if (0 < pControl->cColumns) 3617 if (0 < pControl->ListView.cColumns)
3453 { 3618 {
3454 hr = MemAllocArray(reinterpret_cast<LPVOID*>(&pControl->ptcColumns), sizeof(THEME_COLUMN), pControl->cColumns); 3619 hr = MemAllocArray(reinterpret_cast<LPVOID*>(&pControl->ListView.ptcColumns), sizeof(THEME_COLUMN), pControl->ListView.cColumns);
3455 ThmExitOnFailure(hr, "Failed to allocate column structs."); 3620 ThmExitOnFailure(hr, "Failed to allocate column structs.");
3456 3621
3457 i = 0; 3622 i = 0;
3458 while (S_OK == (hr = XmlNextElement(pixnl, &pixnChild, NULL))) 3623 while (S_OK == (hr = XmlNextElement(pixnl, &pixnChild, NULL)))
3459 { 3624 {
3460 THEME_COLUMN* pColumn = pControl->ptcColumns + i; 3625 THEME_COLUMN* pColumn = pControl->ListView.ptcColumns + i;
3461 3626
3462 hr = XmlGetText(pixnChild, &bstrText); 3627 hr = XmlGetText(pixnChild, &bstrText);
3463 ThmExitOnFailure(hr, "Failed to get inner text of column element."); 3628 ThmExitOnFailure(hr, "Failed to get inner text of column element.");
@@ -3794,23 +3959,23 @@ static HRESULT ParseNotes(
3794 hr = XmlSelectNodes(pixn, L"Note", &pixnl); 3959 hr = XmlSelectNodes(pixn, L"Note", &pixnl);
3795 ThmExitOnFailure(hr, "Failed to select child Note nodes."); 3960 ThmExitOnFailure(hr, "Failed to select child Note nodes.");
3796 3961
3797 hr = pixnl->get_length(reinterpret_cast<long*>(&pControl->cConditionalNotes)); 3962 hr = pixnl->get_length(reinterpret_cast<long*>(&pControl->CommandLink.cConditionalNotes));
3798 ThmExitOnFailure(hr, "Failed to count the number of Note nodes."); 3963 ThmExitOnFailure(hr, "Failed to count the number of Note nodes.");
3799 3964
3800 if (pfAnyChildren) 3965 if (pfAnyChildren)
3801 { 3966 {
3802 *pfAnyChildren = 0 < pControl->cConditionalNotes; 3967 *pfAnyChildren = 0 < pControl->CommandLink.cConditionalNotes;
3803 } 3968 }
3804 3969
3805 if (0 < pControl->cConditionalNotes) 3970 if (0 < pControl->CommandLink.cConditionalNotes)
3806 { 3971 {
3807 MemAllocArray(reinterpret_cast<LPVOID*>(&pControl->rgConditionalNotes), sizeof(THEME_CONDITIONAL_TEXT), pControl->cConditionalNotes); 3972 MemAllocArray(reinterpret_cast<LPVOID*>(&pControl->CommandLink.rgConditionalNotes), sizeof(THEME_CONDITIONAL_TEXT), pControl->CommandLink.cConditionalNotes);
3808 ThmExitOnNull(pControl->rgConditionalNotes, hr, E_OUTOFMEMORY, "Failed to allocate note THEME_CONDITIONAL_TEXT structs."); 3973 ThmExitOnNull(pControl->CommandLink.rgConditionalNotes, hr, E_OUTOFMEMORY, "Failed to allocate note THEME_CONDITIONAL_TEXT structs.");
3809 3974
3810 i = 0; 3975 i = 0;
3811 while (S_OK == (hr = XmlNextElement(pixnl, &pixnChild, NULL))) 3976 while (S_OK == (hr = XmlNextElement(pixnl, &pixnChild, NULL)))
3812 { 3977 {
3813 THEME_CONDITIONAL_TEXT* pConditionalNote = pControl->rgConditionalNotes + i; 3978 THEME_CONDITIONAL_TEXT* pConditionalNote = pControl->CommandLink.rgConditionalNotes + i;
3814 3979
3815 hr = XmlGetAttributeEx(pixnChild, L"Condition", &pConditionalNote->sczCondition); 3980 hr = XmlGetAttributeEx(pixnChild, L"Condition", &pConditionalNote->sczCondition);
3816 if (E_NOTFOUND == hr) 3981 if (E_NOTFOUND == hr)
@@ -3843,7 +4008,7 @@ static HRESULT ParseNotes(
3843 ThmExitOnFailure(hr, "Failed to copy text to command link control."); 4008 ThmExitOnFailure(hr, "Failed to copy text to command link control.");
3844 4009
3845 // Unconditional note entries aren't stored in the conditional notes list. 4010 // Unconditional note entries aren't stored in the conditional notes list.
3846 --pControl->cConditionalNotes; 4011 --pControl->CommandLink.cConditionalNotes;
3847 } 4012 }
3848 } 4013 }
3849 4014
@@ -3992,57 +4157,43 @@ static HRESULT DrawButton(
3992 ) 4157 )
3993{ 4158{
3994 HRESULT hr = S_OK; 4159 HRESULT hr = S_OK;
3995 THEME_IMAGE_REFERENCE buttonImageRef = { }; 4160 const THEME_IMAGE_REFERENCE* pImageRef = NULL;
3996 const THEME_IMAGE_INSTANCE* pInstance = NULL; 4161 BOOL fDrawFocusRect = FALSE;
3997 int nHeight = pdis->rcItem.bottom - pdis->rcItem.top; 4162 int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
3998 int nWidth = pdis->rcItem.right - pdis->rcItem.left; 4163 int nWidth = pdis->rcItem.right - pdis->rcItem.left;
3999 4164
4000 buttonImageRef.type = THEME_IMAGE_REFERENCE_TYPE_PARTIAL;
4001 buttonImageRef.dwImageInstanceIndex = pControl->imageRef.dwImageInstanceIndex;
4002 GetImageInstance(pTheme, &pControl->imageRef, &pInstance);
4003
4004 if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pControl->imageRef.type)
4005 {
4006 buttonImageRef.nX = pControl->imageRef.nX;
4007 buttonImageRef.nY = pControl->imageRef.nY;
4008 buttonImageRef.nWidth = pControl->imageRef.nWidth;
4009 buttonImageRef.nHeight = pControl->imageRef.nHeight;
4010 }
4011 else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pControl->imageRef.type)
4012 {
4013 buttonImageRef.nX = 0;
4014 buttonImageRef.nY = 0;
4015 buttonImageRef.nWidth = pInstance->pBitmap->GetWidth();
4016 buttonImageRef.nHeight = pInstance->pBitmap->GetHeight() / 4;
4017 }
4018 else
4019 {
4020 AssertSz(FALSE, "Invalid image reference type for drawing");
4021 ExitFunction1(hr = E_INVALIDARG);
4022 }
4023
4024 DWORD_PTR dwStyle = ::GetWindowLongPtrW(pdis->hwndItem, GWL_STYLE);
4025 // "clicked" gets priority 4165 // "clicked" gets priority
4026 if (ODS_SELECTED & pdis->itemState) 4166 if (ODS_SELECTED & pdis->itemState)
4027 { 4167 {
4028 buttonImageRef.nY += buttonImageRef.nHeight * 2; 4168 pImageRef = pControl->Button.rgImageRef + 2;
4029 } 4169 }
4030 // then hover 4170 // then hover
4031 else if (pControl->dwData & THEME_CONTROL_DATA_HOVER) 4171 else if (pControl->dwData & THEME_CONTROL_DATA_HOVER)
4032 { 4172 {
4033 buttonImageRef.nY += buttonImageRef.nHeight; 4173 pImageRef = pControl->Button.rgImageRef + 1;
4034 } 4174 }
4035 // then focused 4175 // then focused
4036 else if ((WS_TABSTOP & dwStyle) && (ODS_FOCUS & pdis->itemState)) 4176 else if ((WS_TABSTOP & ::GetWindowLongPtrW(pdis->hwndItem, GWL_STYLE)) && (ODS_FOCUS & pdis->itemState))
4037 { 4177 {
4038 buttonImageRef.nY += buttonImageRef.nHeight * 3; 4178 if (THEME_IMAGE_REFERENCE_TYPE_NONE != pControl->Button.rgImageRef[3].type)
4179 {
4180 pImageRef = pControl->Button.rgImageRef + 3;
4181 }
4182 else
4183 {
4184 fDrawFocusRect = TRUE;
4185 pImageRef = pControl->Button.rgImageRef;
4186 }
4187 }
4188 else
4189 {
4190 pImageRef = pControl->Button.rgImageRef;
4039 } 4191 }
4040 4192
4041 hr = DrawImageReference(pTheme, &buttonImageRef, pdis->hDC, 0, 0, nWidth, nHeight); 4193 hr = DrawImageReference(pTheme, pImageRef, pdis->hDC, 0, 0, nWidth, nHeight);
4042 4194
4043 DrawControlText(pTheme, pdis, pControl, TRUE, FALSE); 4195 DrawControlText(pTheme, pdis, pControl, TRUE, fDrawFocusRect);
4044 4196
4045LExit:
4046 return hr; 4197 return hr;
4047} 4198}
4048 4199
@@ -4068,47 +4219,44 @@ static void DrawControlText(
4068{ 4219{
4069 HRESULT hr = S_OK; 4220 HRESULT hr = S_OK;
4070 WCHAR wzText[256] = { }; 4221 WCHAR wzText[256] = { };
4071 DWORD cchText = 0;
4072 THEME_FONT* pFont = NULL; 4222 THEME_FONT* pFont = NULL;
4073 THEME_FONT_INSTANCE* pFontInstance = NULL; 4223 THEME_FONT_INSTANCE* pFontInstance = NULL;
4074 HFONT hfPrev = NULL; 4224 HFONT hfPrev = NULL;
4225 DWORD cchText = ::GetWindowTextW(pdis->hwndItem, wzText, countof(wzText));
4075 4226
4076 if (0 == (cchText = ::GetWindowTextW(pdis->hwndItem, wzText, countof(wzText)))) 4227 if (cchText)
4077 { 4228 {
4078 // nothing to do 4229 if (ODS_SELECTED & pdis->itemState)
4079 return; 4230 {
4080 } 4231 pFont = pTheme->rgFonts + (THEME_INVALID_ID != pControl->dwFontSelectedId ? pControl->dwFontSelectedId : pControl->dwFontId);
4232 }
4233 else if (pControl->dwData & THEME_CONTROL_DATA_HOVER)
4234 {
4235 pFont = pTheme->rgFonts + (THEME_INVALID_ID != pControl->dwFontHoverId ? pControl->dwFontHoverId : pControl->dwFontId);
4236 }
4237 else
4238 {
4239 pFont = pTheme->rgFonts + pControl->dwFontId;
4240 }
4081 4241
4082 if (ODS_SELECTED & pdis->itemState) 4242 hr = EnsureFontInstance(pTheme, pFont, &pFontInstance);
4083 { 4243 if (SUCCEEDED(hr))
4084 pFont = pTheme->rgFonts + (THEME_INVALID_ID != pControl->dwFontSelectedId ? pControl->dwFontSelectedId : pControl->dwFontId); 4244 {
4085 } 4245 hfPrev = SelectFont(pdis->hDC, pFontInstance->hFont);
4086 else if (pControl->dwData & THEME_CONTROL_DATA_HOVER) 4246 }
4087 {
4088 pFont = pTheme->rgFonts + (THEME_INVALID_ID != pControl->dwFontHoverId ? pControl->dwFontHoverId : pControl->dwFontId);
4089 }
4090 else
4091 {
4092 pFont = pTheme->rgFonts + pControl->dwFontId;
4093 }
4094 4247
4095 hr = EnsureFontInstance(pTheme, pFont, &pFontInstance); 4248 ::DrawTextExW(pdis->hDC, wzText, cchText, &pdis->rcItem, DT_SINGLELINE | (fCentered ? (DT_CENTER | DT_VCENTER) : 0), NULL);
4096 if (SUCCEEDED(hr))
4097 {
4098 hfPrev = SelectFont(pdis->hDC, pFontInstance->hFont);
4099 }
4100 4249
4101 ::DrawTextExW(pdis->hDC, wzText, cchText, &pdis->rcItem, DT_SINGLELINE | (fCentered ? (DT_CENTER | DT_VCENTER) : 0), NULL); 4250 if (hfPrev)
4251 {
4252 SelectFont(pdis->hDC, hfPrev);
4253 }
4254 }
4102 4255
4103 if (fDrawFocusRect && (WS_TABSTOP & ::GetWindowLongPtrW(pdis->hwndItem, GWL_STYLE)) && (ODS_FOCUS & pdis->itemState)) 4256 if (fDrawFocusRect && (WS_TABSTOP & ::GetWindowLongPtrW(pdis->hwndItem, GWL_STYLE)) && (ODS_FOCUS & pdis->itemState))
4104 { 4257 {
4105 ::DrawFocusRect(pdis->hDC, &pdis->rcItem); 4258 ::DrawFocusRect(pdis->hDC, &pdis->rcItem);
4106 } 4259 }
4107
4108 if (hfPrev)
4109 {
4110 SelectFont(pdis->hDC, hfPrev);
4111 }
4112} 4260}
4113 4261
4114 4262
@@ -4122,7 +4270,7 @@ static HRESULT DrawImage(
4122 int nHeight = pdis->rcItem.bottom - pdis->rcItem.top; 4270 int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
4123 int nWidth = pdis->rcItem.right - pdis->rcItem.left; 4271 int nWidth = pdis->rcItem.right - pdis->rcItem.left;
4124 4272
4125 hr = DrawImageReference(pTheme, &pControl->imageRef, pdis->hDC, 0, 0, nWidth, nHeight); 4273 hr = DrawImageReference(pTheme, &pControl->Image.imageRef, pdis->hDC, 0, 0, nWidth, nHeight);
4126 4274
4127 return hr; 4275 return hr;
4128} 4276}
@@ -4240,8 +4388,9 @@ static HRESULT DrawProgressBar(
4240{ 4388{
4241 const int nSideWidth = 1; 4389 const int nSideWidth = 1;
4242 HRESULT hr = S_OK; 4390 HRESULT hr = S_OK;
4243 WORD wProgressColor = HIWORD(pControl->dwData); 4391 WORD wProgressColorIndex = HIWORD(pControl->dwData);
4244 WORD wProgressPercentage = LOWORD(pControl->dwData); 4392 WORD wProgressPercentage = LOWORD(pControl->dwData);
4393 const THEME_IMAGE_REFERENCE* pImageRef = pControl->ProgressBar.rgImageRef + wProgressColorIndex;
4245 const THEME_IMAGE_INSTANCE* pInstance = NULL; 4394 const THEME_IMAGE_INSTANCE* pInstance = NULL;
4246 int nHeight = pdis->rcItem.bottom - pdis->rcItem.top; 4395 int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
4247 int nSourceHeight = 0; 4396 int nSourceHeight = 0;
@@ -4255,19 +4404,19 @@ static HRESULT DrawProgressBar(
4255 ExitFunction1(hr = S_FALSE); 4404 ExitFunction1(hr = S_FALSE);
4256 } 4405 }
4257 4406
4258 GetImageInstance(pTheme, &pControl->imageRef, &pInstance); 4407 GetImageInstance(pTheme, pImageRef, &pInstance);
4259 4408
4260 if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pControl->imageRef.type) 4409 if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pImageRef->type)
4261 { 4410 {
4262 nSourceHeight = pControl->imageRef.nHeight; 4411 nSourceHeight = pImageRef->nHeight;
4263 nSourceX = pControl->imageRef.nX; 4412 nSourceX = pImageRef->nX;
4264 nSourceY = pControl->imageRef.nY + (wProgressColor * nSourceHeight); 4413 nSourceY = pImageRef->nY;
4265 } 4414 }
4266 else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pControl->imageRef.type) 4415 else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pImageRef->type)
4267 { 4416 {
4268 nSourceHeight = pControl->nDefaultDpiHeight; 4417 nSourceHeight = pInstance->pBitmap->GetHeight();
4269 nSourceX = 0; 4418 nSourceX = 0;
4270 nSourceY = wProgressColor * nSourceHeight; 4419 nSourceY = 0;
4271 } 4420 }
4272 else 4421 else
4273 { 4422 {
@@ -4411,9 +4560,34 @@ static void FreeControl(
4411 ReleaseStr(pControl->sczValue); 4560 ReleaseStr(pControl->sczValue);
4412 ReleaseStr(pControl->sczVariable); 4561 ReleaseStr(pControl->sczVariable);
4413 4562
4414 if (pControl->hImage) 4563 switch (pControl->type)
4415 { 4564 {
4416 ::DeleteBitmap(pControl->hImage); 4565 case THEME_CONTROL_TYPE_COMMANDLINK:
4566 if (pControl->CommandLink.hImage)
4567 {
4568 ::DeleteBitmap(pControl->CommandLink.hImage);
4569 }
4570
4571 if (pControl->CommandLink.hIcon)
4572 {
4573 ::DestroyIcon(pControl->CommandLink.hIcon);
4574 }
4575
4576 for (DWORD i = 0; i < pControl->CommandLink.cConditionalNotes; ++i)
4577 {
4578 FreeConditionalText(pControl->CommandLink.rgConditionalNotes + i);
4579 }
4580
4581 ReleaseMem(pControl->CommandLink.rgConditionalNotes);
4582 break;
4583 case THEME_CONTROL_TYPE_LISTVIEW:
4584 for (DWORD i = 0; i < pControl->ListView.cColumns; ++i)
4585 {
4586 FreeColumn(pControl->ListView.ptcColumns + i);
4587 }
4588
4589 ReleaseMem(pControl->ListView.ptcColumns);
4590 break;
4417 } 4591 }
4418 4592
4419 for (DWORD i = 0; i < pControl->cControls; ++i) 4593 for (DWORD i = 0; i < pControl->cControls; ++i)
@@ -4426,30 +4600,18 @@ static void FreeControl(
4426 FreeAction(&(pControl->rgActions[i])); 4600 FreeAction(&(pControl->rgActions[i]));
4427 } 4601 }
4428 4602
4429 for (DWORD i = 0; i < pControl->cColumns; ++i)
4430 {
4431 FreeColumn(&(pControl->ptcColumns[i]));
4432 }
4433
4434 for (DWORD i = 0; i < pControl->cConditionalText; ++i) 4603 for (DWORD i = 0; i < pControl->cConditionalText; ++i)
4435 { 4604 {
4436 FreeConditionalText(&(pControl->rgConditionalText[i])); 4605 FreeConditionalText(&(pControl->rgConditionalText[i]));
4437 } 4606 }
4438 4607
4439 for (DWORD i = 0; i < pControl->cConditionalNotes; ++i)
4440 {
4441 FreeConditionalText(&(pControl->rgConditionalNotes[i]));
4442 }
4443
4444 for (DWORD i = 0; i < pControl->cTabs; ++i) 4608 for (DWORD i = 0; i < pControl->cTabs; ++i)
4445 { 4609 {
4446 FreeTab(&(pControl->pttTabs[i])); 4610 FreeTab(&(pControl->pttTabs[i]));
4447 } 4611 }
4448 4612
4449 ReleaseMem(pControl->rgActions) 4613 ReleaseMem(pControl->rgActions)
4450 ReleaseMem(pControl->ptcColumns);
4451 ReleaseMem(pControl->rgConditionalText); 4614 ReleaseMem(pControl->rgConditionalText);
4452 ReleaseMem(pControl->rgConditionalNotes);
4453 ReleaseMem(pControl->pttTabs); 4615 ReleaseMem(pControl->pttTabs);
4454 } 4616 }
4455} 4617}
@@ -4945,6 +5107,7 @@ static HRESULT SizeListViewColumns(
4945 RECT rcParent = { }; 5107 RECT rcParent = { };
4946 int cNumExpandingColumns = 0; 5108 int cNumExpandingColumns = 0;
4947 int iExtraAvailableSize; 5109 int iExtraAvailableSize;
5110 THEME_COLUMN* pColumn = NULL;
4948 5111
4949 if (!::GetWindowRect(pControl->hWnd, &rcParent)) 5112 if (!::GetWindowRect(pControl->hWnd, &rcParent))
4950 { 5113 {
@@ -4953,31 +5116,35 @@ static HRESULT SizeListViewColumns(
4953 5116
4954 iExtraAvailableSize = rcParent.right - rcParent.left; 5117 iExtraAvailableSize = rcParent.right - rcParent.left;
4955 5118
4956 for (DWORD i = 0; i < pControl->cColumns; ++i) 5119 for (DWORD i = 0; i < pControl->ListView.cColumns; ++i)
4957 { 5120 {
4958 if (pControl->ptcColumns[i].fExpands) 5121 pColumn = pControl->ListView.ptcColumns + i;
5122
5123 if (pColumn->fExpands)
4959 { 5124 {
4960 ++cNumExpandingColumns; 5125 ++cNumExpandingColumns;
4961 } 5126 }
4962 5127
4963 iExtraAvailableSize -= pControl->ptcColumns[i].nBaseWidth; 5128 iExtraAvailableSize -= pColumn->nBaseWidth;
4964 } 5129 }
4965 5130
4966 // Leave room for a vertical scroll bar just in case. 5131 // Leave room for a vertical scroll bar just in case.
4967 iExtraAvailableSize -= ::GetSystemMetrics(SM_CXVSCROLL); 5132 iExtraAvailableSize -= ::GetSystemMetrics(SM_CXVSCROLL);
4968 5133
4969 for (DWORD i = 0; i < pControl->cColumns; ++i) 5134 for (DWORD i = 0; i < pControl->ListView.cColumns; ++i)
4970 { 5135 {
4971 if (pControl->ptcColumns[i].fExpands) 5136 pColumn = pControl->ListView.ptcColumns + i;
5137
5138 if (pColumn->fExpands)
4972 { 5139 {
4973 pControl->ptcColumns[i].nWidth = pControl->ptcColumns[i].nBaseWidth + (iExtraAvailableSize / cNumExpandingColumns); 5140 pColumn->nWidth = pColumn->nBaseWidth + (iExtraAvailableSize / cNumExpandingColumns);
4974 // In case there is any remainder, use it up the first chance we get. 5141 // In case there is any remainder, use it up the first chance we get.
4975 pControl->ptcColumns[i].nWidth += iExtraAvailableSize % cNumExpandingColumns; 5142 pColumn->nWidth += iExtraAvailableSize % cNumExpandingColumns;
4976 iExtraAvailableSize -= iExtraAvailableSize % cNumExpandingColumns; 5143 iExtraAvailableSize -= iExtraAvailableSize % cNumExpandingColumns;
4977 } 5144 }
4978 else 5145 else
4979 { 5146 {
4980 pControl->ptcColumns[i].nWidth = pControl->ptcColumns[i].nBaseWidth; 5147 pColumn->nWidth = pColumn->nBaseWidth;
4981 } 5148 }
4982 } 5149 }
4983 5150
@@ -5082,22 +5249,25 @@ static HRESULT ShowControl(
5082 } 5249 }
5083 } 5250 }
5084 5251
5085 for (DWORD j = 0; j < pControl->cConditionalNotes; ++j) 5252 if (THEME_CONTROL_TYPE_COMMANDLINK == pControl->type)
5086 { 5253 {
5087 THEME_CONDITIONAL_TEXT* pConditionalNote = pControl->rgConditionalNotes + j; 5254 for (DWORD j = 0; j < pControl->CommandLink.cConditionalNotes; ++j)
5088 wzNote = pConditionalNote->sczText;
5089
5090 if (pConditionalNote->sczCondition)
5091 { 5255 {
5092 BOOL fCondition = FALSE; 5256 THEME_CONDITIONAL_TEXT* pConditionalNote = pControl->CommandLink.rgConditionalNotes + j;
5257 wzNote = pConditionalNote->sczText;
5093 5258
5094 hr = pTheme->pfnEvaluateCondition(pConditionalNote->sczCondition, &fCondition, pTheme->pvVariableContext); 5259 if (pConditionalNote->sczCondition)
5095 ThmExitOnFailure(hr, "Failed to evaluate note condition: %ls", pConditionalNote->sczCondition);
5096
5097 if (fCondition)
5098 { 5260 {
5099 wzNote = pConditionalNote->sczText; 5261 BOOL fCondition = FALSE;
5100 break; 5262
5263 hr = pTheme->pfnEvaluateCondition(pConditionalNote->sczCondition, &fCondition, pTheme->pvVariableContext);
5264 ThmExitOnFailure(hr, "Failed to evaluate note condition: %ls", pConditionalNote->sczCondition);
5265
5266 if (fCondition)
5267 {
5268 wzNote = pConditionalNote->sczText;
5269 break;
5270 }
5101 } 5271 }
5102 } 5272 }
5103 } 5273 }
@@ -5497,7 +5667,6 @@ static HRESULT LoadControls(
5497 LPCWSTR wzWindowClass = NULL; 5667 LPCWSTR wzWindowClass = NULL;
5498 DWORD dwWindowBits = WS_CHILD; 5668 DWORD dwWindowBits = WS_CHILD;
5499 DWORD dwWindowExBits = 0; 5669 DWORD dwWindowExBits = 0;
5500 BOOL fOwnerDrawImage = THEME_IMAGE_REFERENCE_TYPE_NONE != pControl->imageRef.type;
5501 5670
5502 if (fStartNewGroup) 5671 if (fStartNewGroup)
5503 { 5672 {
@@ -5522,7 +5691,7 @@ static HRESULT LoadControls(
5522 __fallthrough; 5691 __fallthrough;
5523 case THEME_CONTROL_TYPE_BUTTON: 5692 case THEME_CONTROL_TYPE_BUTTON:
5524 wzWindowClass = WC_BUTTONW; 5693 wzWindowClass = WC_BUTTONW;
5525 if (fOwnerDrawImage) 5694 if (THEME_IMAGE_REFERENCE_TYPE_NONE != pControl->Button.rgImageRef[0].type)
5526 { 5695 {
5527 dwWindowBits |= BS_OWNERDRAW; 5696 dwWindowBits |= BS_OWNERDRAW;
5528 pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_OWNER_DRAW; 5697 pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_OWNER_DRAW;
@@ -5556,7 +5725,7 @@ static HRESULT LoadControls(
5556 break; 5725 break;
5557 5726
5558 case THEME_CONTROL_TYPE_IMAGE: // images are basically just owner drawn static controls (so we can draw .jpgs and .pngs instead of just bitmaps). 5727 case THEME_CONTROL_TYPE_IMAGE: // images are basically just owner drawn static controls (so we can draw .jpgs and .pngs instead of just bitmaps).
5559 if (fOwnerDrawImage) 5728 if (THEME_IMAGE_REFERENCE_TYPE_NONE != pControl->Image.imageRef.type)
5560 { 5729 {
5561 wzWindowClass = THEME_WC_STATICOWNERDRAW; 5730 wzWindowClass = THEME_WC_STATICOWNERDRAW;
5562 dwWindowBits |= SS_OWNERDRAW; 5731 dwWindowBits |= SS_OWNERDRAW;
@@ -5575,7 +5744,7 @@ static HRESULT LoadControls(
5575 5744
5576 case THEME_CONTROL_TYPE_LISTVIEW: 5745 case THEME_CONTROL_TYPE_LISTVIEW:
5577 // If thmutil is handling the image list for this listview, tell Windows not to free it when the control is destroyed. 5746 // If thmutil is handling the image list for this listview, tell Windows not to free it when the control is destroyed.
5578 if (pControl->rghImageList[0] || pControl->rghImageList[1] || pControl->rghImageList[2] || pControl->rghImageList[3]) 5747 if (pControl->ListView.rghImageList[0] || pControl->ListView.rghImageList[1] || pControl->ListView.rghImageList[2] || pControl->ListView.rghImageList[3])
5579 { 5748 {
5580 pControl->dwStyle |= LVS_SHAREIMAGELISTS; 5749 pControl->dwStyle |= LVS_SHAREIMAGELISTS;
5581 } 5750 }
@@ -5583,7 +5752,7 @@ static HRESULT LoadControls(
5583 break; 5752 break;
5584 5753
5585 case THEME_CONTROL_TYPE_PROGRESSBAR: 5754 case THEME_CONTROL_TYPE_PROGRESSBAR:
5586 if (fOwnerDrawImage) 5755 if (pControl->ProgressBar.cImageRef)
5587 { 5756 {
5588 wzWindowClass = THEME_WC_STATICOWNERDRAW; // no such thing as an owner drawn progress bar so we'll make our own out of a static control. 5757 wzWindowClass = THEME_WC_STATICOWNERDRAW; // no such thing as an owner drawn progress bar so we'll make our own out of a static control.
5589 dwWindowBits |= SS_OWNERDRAW; 5758 dwWindowBits |= SS_OWNERDRAW;
@@ -5721,13 +5890,13 @@ static HRESULT LoadControls(
5721 ::SendMessageW(pControl->hWnd, BCM_SETNOTE, 0, reinterpret_cast<WPARAM>(pControl->sczNote)); 5890 ::SendMessageW(pControl->hWnd, BCM_SETNOTE, 0, reinterpret_cast<WPARAM>(pControl->sczNote));
5722 } 5891 }
5723 5892
5724 if (pControl->hImage) 5893 if (pControl->CommandLink.hImage)
5725 { 5894 {
5726 ::SendMessageW(pControl->hWnd, BM_SETIMAGE, IMAGE_BITMAP, reinterpret_cast<LPARAM>(pControl->hImage)); 5895 ::SendMessageW(pControl->hWnd, BM_SETIMAGE, IMAGE_BITMAP, reinterpret_cast<LPARAM>(pControl->CommandLink.hImage));
5727 } 5896 }
5728 else if (pControl->hIcon) 5897 else if (pControl->CommandLink.hIcon)
5729 { 5898 {
5730 ::SendMessageW(pControl->hWnd, BM_SETIMAGE, IMAGE_ICON, reinterpret_cast<LPARAM>(pControl->hIcon)); 5899 ::SendMessageW(pControl->hWnd, BM_SETIMAGE, IMAGE_ICON, reinterpret_cast<LPARAM>(pControl->CommandLink.hIcon));
5731 } 5900 }
5732 } 5901 }
5733 else if (THEME_CONTROL_TYPE_EDITBOX == pControl->type) 5902 else if (THEME_CONTROL_TYPE_EDITBOX == pControl->type)
@@ -5744,13 +5913,13 @@ static HRESULT LoadControls(
5744 hr = SizeListViewColumns(pControl); 5913 hr = SizeListViewColumns(pControl);
5745 ThmExitOnFailure(hr, "Failed to get size of list view columns."); 5914 ThmExitOnFailure(hr, "Failed to get size of list view columns.");
5746 5915
5747 for (DWORD j = 0; j < pControl->cColumns; ++j) 5916 for (DWORD j = 0; j < pControl->ListView.cColumns; ++j)
5748 { 5917 {
5749 LVCOLUMNW lvc = { }; 5918 LVCOLUMNW lvc = { };
5750 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 5919 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
5751 lvc.cx = pControl->ptcColumns[j].nWidth; 5920 lvc.cx = pControl->ListView.ptcColumns[j].nWidth;
5752 lvc.iSubItem = j; 5921 lvc.iSubItem = j;
5753 lvc.pszText = pControl->ptcColumns[j].pszName; 5922 lvc.pszText = pControl->ListView.ptcColumns[j].pszName;
5754 lvc.fmt = LVCFMT_LEFT; 5923 lvc.fmt = LVCFMT_LEFT;
5755 lvc.cchTextMax = 4; 5924 lvc.cchTextMax = 4;
5756 5925
@@ -5760,21 +5929,21 @@ static HRESULT LoadControls(
5760 } 5929 }
5761 5930
5762 // Return value tells us the old image list, we don't care. 5931 // Return value tells us the old image list, we don't care.
5763 if (pControl->rghImageList[0]) 5932 if (pControl->ListView.rghImageList[0])
5764 { 5933 {
5765 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_NORMAL), reinterpret_cast<LPARAM>(pControl->rghImageList[0])); 5934 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_NORMAL), reinterpret_cast<LPARAM>(pControl->ListView.rghImageList[0]));
5766 } 5935 }
5767 else if (pControl->rghImageList[1]) 5936 else if (pControl->ListView.rghImageList[1])
5768 { 5937 {
5769 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_SMALL), reinterpret_cast<LPARAM>(pControl->rghImageList[1])); 5938 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_SMALL), reinterpret_cast<LPARAM>(pControl->ListView.rghImageList[1]));
5770 } 5939 }
5771 else if (pControl->rghImageList[2]) 5940 else if (pControl->ListView.rghImageList[2])
5772 { 5941 {
5773 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_STATE), reinterpret_cast<LPARAM>(pControl->rghImageList[2])); 5942 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_STATE), reinterpret_cast<LPARAM>(pControl->ListView.rghImageList[2]));
5774 } 5943 }
5775 else if (pControl->rghImageList[3]) 5944 else if (pControl->ListView.rghImageList[3])
5776 { 5945 {
5777 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_GROUPHEADER), reinterpret_cast<LPARAM>(pControl->rghImageList[3])); 5946 ::SendMessageW(pControl->hWnd, LVM_SETIMAGELIST, static_cast<WPARAM>(LVSIL_GROUPHEADER), reinterpret_cast<LPARAM>(pControl->ListView.rghImageList[3]));
5778 } 5947 }
5779 } 5948 }
5780 } 5949 }
@@ -5909,16 +6078,24 @@ static HRESULT LocalizeControl(
5909 ThmExitOnFailure(hr, "Failed to localize conditional text."); 6078 ThmExitOnFailure(hr, "Failed to localize conditional text.");
5910 } 6079 }
5911 6080
5912 for (DWORD j = 0; j < pControl->cConditionalNotes; ++j) 6081 switch (pControl->type)
5913 { 6082 {
5914 hr = LocLocalizeString(pWixLoc, &pControl->rgConditionalNotes[j].sczText); 6083 case THEME_CONTROL_TYPE_COMMANDLINK:
5915 ThmExitOnFailure(hr, "Failed to localize conditional note."); 6084 for (DWORD j = 0; j < pControl->CommandLink.cConditionalNotes; ++j)
5916 } 6085 {
6086 hr = LocLocalizeString(pWixLoc, &pControl->CommandLink.rgConditionalNotes[j].sczText);
6087 ThmExitOnFailure(hr, "Failed to localize conditional note.");
6088 }
5917 6089
5918 for (DWORD j = 0; j < pControl->cColumns; ++j) 6090 break;
5919 { 6091 case THEME_CONTROL_TYPE_LISTVIEW:
5920 hr = LocLocalizeString(pWixLoc, &pControl->ptcColumns[j].pszName); 6092 for (DWORD j = 0; j < pControl->ListView.cColumns; ++j)
5921 ThmExitOnFailure(hr, "Failed to localize column text."); 6093 {
6094 hr = LocLocalizeString(pWixLoc, &pControl->ListView.ptcColumns[j].pszName);
6095 ThmExitOnFailure(hr, "Failed to localize column text.");
6096 }
6097
6098 break;
5922 } 6099 }
5923 6100
5924 for (DWORD j = 0; j < pControl->cTabs; ++j) 6101 for (DWORD j = 0; j < pControl->cTabs; ++j)
@@ -6002,13 +6179,20 @@ static HRESULT LoadControlString(
6002 hr = ResReadString(hResModule, pControl->uStringId, &pControl->sczText); 6179 hr = ResReadString(hResModule, pControl->uStringId, &pControl->sczText);
6003 ThmExitOnFailure(hr, "Failed to load control text."); 6180 ThmExitOnFailure(hr, "Failed to load control text.");
6004 6181
6005 for (DWORD j = 0; j < pControl->cColumns; ++j) 6182 switch (pControl->type)
6006 { 6183 {
6007 if (UINT_MAX != pControl->ptcColumns[j].uStringId) 6184 case THEME_CONTROL_TYPE_LISTVIEW:
6185 for (DWORD j = 0; j < pControl->ListView.cColumns; ++j)
6008 { 6186 {
6009 hr = ResReadString(hResModule, pControl->ptcColumns[j].uStringId, &pControl->ptcColumns[j].pszName); 6187 THEME_COLUMN* pColumn = pControl->ListView.ptcColumns + j;
6010 ThmExitOnFailure(hr, "Failed to load column text."); 6188 if (UINT_MAX != pColumn->uStringId)
6189 {
6190 hr = ResReadString(hResModule, pColumn->uStringId, &pColumn->pszName);
6191 ThmExitOnFailure(hr, "Failed to load column text.");
6192 }
6011 } 6193 }
6194
6195 break;
6012 } 6196 }
6013 6197
6014 for (DWORD j = 0; j < pControl->cTabs; ++j) 6198 for (DWORD j = 0; j < pControl->cTabs; ++j)
@@ -6066,9 +6250,9 @@ static void ResizeControl(
6066 { 6250 {
6067 SizeListViewColumns(pControl); 6251 SizeListViewColumns(pControl);
6068 6252
6069 for (DWORD j = 0; j < pControl->cColumns; ++j) 6253 for (DWORD j = 0; j < pControl->ListView.cColumns; ++j)
6070 { 6254 {
6071 if (-1 == ::SendMessageW(pControl->hWnd, LVM_SETCOLUMNWIDTH, (WPARAM) (int) (j), (LPARAM) (pControl->ptcColumns[j].nWidth))) 6255 if (-1 == ::SendMessageW(pControl->hWnd, LVM_SETCOLUMNWIDTH, (WPARAM) (int) (j), (LPARAM) (pControl->ListView.ptcColumns[j].nWidth)))
6072 { 6256 {
6073 Trace(REPORT_DEBUG, "Failed to resize listview column %u with error %u", j, ::GetLastError()); 6257 Trace(REPORT_DEBUG, "Failed to resize listview column %u with error %u", j, ::GetLastError());
6074 return; 6258 return;
@@ -6167,9 +6351,9 @@ static void ScaleControl(
6167 6351
6168 if (THEME_CONTROL_TYPE_LISTVIEW == pControl->type) 6352 if (THEME_CONTROL_TYPE_LISTVIEW == pControl->type)
6169 { 6353 {
6170 for (DWORD i = 0; i < pControl->cColumns; ++i) 6354 for (DWORD i = 0; i < pControl->ListView.cColumns; ++i)
6171 { 6355 {
6172 THEME_COLUMN* pColumn = pControl->ptcColumns + i; 6356 THEME_COLUMN* pColumn = pControl->ListView.ptcColumns + i;
6173 6357
6174 pColumn->nBaseWidth = DpiuScaleValue(pColumn->nDefaultDpiBaseWidth, nDpi); 6358 pColumn->nBaseWidth = DpiuScaleValue(pColumn->nDefaultDpiBaseWidth, nDpi);
6175 } 6359 }