Add thmutil Image element to allow specifying multiple resolutions. Rename previous Image element to ImageListItem.
Add thmutil Image element to allow specifying multiple resolutions. Rename previous Image element to ImageListItem. Last partial fix for #6155
Sean Hall committed
Jun 4, 2021 at 13:37 UTC
700b48c723531bfc38bab185f237d932144f3b26
2 files changed
+371
-25
src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+14
@@ -110,6 +110,7 @@ struct THEME_COLUMN
110
struct THEME_IMAGE_REFERENCE
111
{
112
THEME_IMAGE_REFERENCE_TYPE type;
113
+ DWORD dwImageIndex;
114
DWORD dwImageInstanceIndex;
115
int nX;
116
int nY;
@@ -122,6 +123,15 @@ struct THEME_IMAGE_INSTANCE
123
Gdiplus::Bitmap* pBitmap;
124
};
125
126
+struct THEME_IMAGE
127
+{
128
+ LPWSTR sczId;
129
+ DWORD dwIndex;
130
+
131
+ DWORD cImageInstances;
132
+ THEME_IMAGE_INSTANCE* rgImageInstances;
133
+};
134
+
135
136
struct THEME_TAB
137
{
@@ -342,6 +352,9 @@ struct THEME
352
DWORD cFonts;
353
THEME_FONT* rgFonts;
354
355
+ DWORD cImages;
356
+ THEME_IMAGE* rgImages;
357
+
358
DWORD cStandaloneImages;
359
THEME_IMAGE_INSTANCE* rgStandaloneImages;
360
@@ -356,6 +369,7 @@ struct THEME
369
370
// internal state variables -- do not use outside ThmUtil.cpp
371
STRINGDICT_HANDLE sdhFontDictionary;
372
+ STRINGDICT_HANDLE sdhImageDictionary;
373
HWND hwndParent; // parent for loaded controls
374
HWND hwndHover; // current hwnd hovered over
375
DWORD dwCurrentPageId;
src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+357
-25
@@ -139,6 +139,12 @@ static HRESULT GetAttributeFontId(
139
__in LPCWSTR wzAttribute,
140
__inout DWORD* pdwValue
141
);
142
+static HRESULT GetAttributeImageId(
143
+ __in THEME* pTheme,
144
+ __in IXMLDOMNode* pixn,
145
+ __in LPCWSTR wzAttribute,
146
+ __inout DWORD* pdwValue
147
+ );
148
static HRESULT ParseSourceXY(
149
__in IXMLDOMNode* pixn,
150
__in THEME* pTheme,
@@ -162,6 +168,12 @@ static HRESULT ParseFonts(
168
__in IXMLDOMElement* pElement,
169
__in THEME* pTheme
170
);
171
+static HRESULT ParseImages(
172
+ __in_opt HMODULE hModule,
173
+ __in_opt LPCWSTR wzRelativePath,
174
+ __in IXMLDOMElement* pElement,
175
+ __in THEME* pTheme
176
+ );
177
static HRESULT ParsePages(
178
__in_opt HMODULE hModule,
179
__in_opt LPCWSTR wzRelativePath,
@@ -371,6 +383,9 @@ static void FreeFontInstance(
383
static void FreeFont(
384
__in THEME_FONT* pFont
385
);
386
+static void FreeImage(
387
+ __in THEME_IMAGE* pImage
388
+ );
389
static void FreeImageInstance(
390
__in THEME_IMAGE_INSTANCE* pImageInstance
391
);
@@ -486,11 +501,13 @@ static HRESULT LoadControlString(
501
__in HMODULE hResModule
502
);
503
static void ResizeControls(
504
+ __in THEME* pTheme,
505
__in DWORD cControls,
506
__in THEME_CONTROL* rgControls,
507
__in const RECT* prcParent
508
);
509
static void ResizeControl(
510
+ __in THEME* pTheme,
511
__in THEME_CONTROL* pControl,
512
__in const RECT* prcParent
513
);
@@ -532,6 +549,12 @@ static void GetControls(
549
__out DWORD& cControls,
550
__out THEME_CONTROL*& rgControls
551
);
552
+static void ScaleImageReference(
553
+ __in THEME* pTheme,
554
+ __in THEME_IMAGE_REFERENCE* pImageRef,
555
+ __in int nDestWidth,
556
+ __in int nDestHeight
557
+ );
558
static void UnloadControls(
559
__in DWORD cControls,
560
__in THEME_CONTROL* rgControls
@@ -685,6 +708,11 @@ DAPI_(void) ThemeFree(
708
FreeFont(pTheme->rgFonts + i);
709
}
710
711
+ for (DWORD i = 0; i < pTheme->cImages; ++i)
712
+ {
713
+ FreeImage(pTheme->rgImages + i);
714
+ }
715
+
716
for (DWORD i = 0; i < pTheme->cStandaloneImages; ++i)
717
{
718
FreeImageInstance(pTheme->rgStandaloneImages + i);
@@ -708,10 +736,12 @@ DAPI_(void) ThemeFree(
736
ReleaseMem(pTheme->rgControls);
737
ReleaseMem(pTheme->rgPages);
738
ReleaseMem(pTheme->rgStandaloneImages);
739
+ ReleaseMem(pTheme->rgImages);
740
ReleaseMem(pTheme->rgFonts);
741
742
ReleaseStr(pTheme->sczCaption);
743
ReleaseDict(pTheme->sdhFontDictionary);
744
+ ReleaseDict(pTheme->sdhImageDictionary);
745
ReleaseMem(pTheme);
746
}
747
}
@@ -1063,7 +1093,8 @@ extern "C" LRESULT CALLBACK ThemeDefWindowProc(
1093
{
1094
pTheme->fForceResize = FALSE;
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);
1098
return 0;
1099
}
1100
break;
@@ -1819,6 +1850,10 @@ static HRESULT ParseTheme(
1850
hr = ParseFonts(pThemeElement, pTheme);
1851
ThmExitOnFailure(hr, "Failed to parse theme fonts.");
1852
1853
+ // Parse the images.
1854
+ hr = ParseImages(hModule, wzRelativePath, pThemeElement, pTheme);
1855
+ ThmExitOnFailure(hr, "Failed to parse theme images.");
1856
+
1857
// Parse the window element.
1858
hr = ParseWindow(hModule, wzRelativePath, pThemeElement, pTheme);
1859
ThmExitOnFailure(hr, "Failed to parse theme window element.");
@@ -1950,16 +1985,37 @@ static HRESULT ParseOwnerDrawImage(
1985
)
1986
{
1987
HRESULT hr = S_OK;
1988
+ DWORD dwValue = 0;
1989
BOOL fXmlFound = FALSE;
1990
BOOL fFoundImage = FALSE;
1991
Gdiplus::Bitmap* pBitmap = NULL;
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
+
2008
// Parse the optional background resource image.
2009
hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pBitmap);
2010
ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing control image.");
2011
2012
if (fXmlFound)
2013
{
2014
+ if (fFoundImage)
2015
+ {
2016
+ ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected image attribute with ImageId attribute.");
2017
+ }
2018
+
2019
hr = AddStandaloneImage(pTheme, &pBitmap, &pImageRef->dwImageInstanceIndex);
2020
ThmExitOnFailure(hr, "Failed to store owner draw image.");
2021
@@ -2284,6 +2340,41 @@ LExit:
2340
return hr;
2341
}
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
+
2378
static HRESULT ParseSourceXY(
2379
__in IXMLDOMNode* pixn,
2380
__in THEME* pTheme,
@@ -2366,6 +2457,7 @@ static HRESULT ParseSourceXY(
2457
}
2458
2459
pReference->type = THEME_IMAGE_REFERENCE_TYPE_PARTIAL;
2460
+ pReference->dwImageIndex = THEME_INVALID_ID;
2461
pReference->dwImageInstanceIndex = dwImageInstanceIndex;
2462
pReference->nX = nX;
2463
pReference->nY = nY;
@@ -2747,6 +2839,131 @@ LExit:
2839
return hr;
2840
}
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
+
2967
static HRESULT ParsePages(
2968
__in_opt HMODULE hModule,
2969
__in_opt LPCWSTR wzRelativePath,
@@ -2853,8 +3070,8 @@ static HRESULT ParseImageLists(
3070
hr = XmlGetAttributeEx(pixnImageList, L"Name", &pThemeImageList->sczName);
3071
ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find ImageList/@Name attribute.");
3072
2856
- hr = XmlSelectNodes(pixnImageList, L"Image", &pixnlImages);
2857
- ThmExitOnFailure(hr, "Failed to select child Image nodes.");
3073
+ hr = XmlSelectNodes(pixnImageList, L"ImageListItem", &pixnlImages);
3074
+ ThmExitOnFailure(hr, "Failed to select child ImageListItem nodes.");
3075
3076
hr = pixnlImages->get_length(reinterpret_cast<long*>(&dwImageCount));
3077
ThmExitOnFailure(hr, "Failed to count the number of images in list.");
@@ -4300,7 +4517,24 @@ static void GetImageInstance(
4517
__out const THEME_IMAGE_INSTANCE** ppInstance
4518
)
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
+ }
4538
}
4539
4540
static HRESULT DrawImageReference(
@@ -4321,24 +4555,24 @@ static HRESULT DrawImageReference(
4555
int nHeight = 0;
4556
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)
4561
{
4562
+ case THEME_IMAGE_REFERENCE_TYPE_PARTIAL:
4563
nX = pReference->nX;
4564
nY = pReference->nY;
4565
nWidth = pReference->nWidth;
4566
nHeight = pReference->nHeight;
4330
- }
4331
- else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pReference->type)
4332
- {
4567
+ break;
4568
+ case THEME_IMAGE_REFERENCE_TYPE_COMPLETE:
4569
nX = 0;
4570
nY = 0;
4571
nWidth = pImageInstance->pBitmap->GetWidth();
4572
nHeight = pImageInstance->pBitmap->GetHeight();
4337
- }
4338
- else
4339
- {
4340
- AssertSz(FALSE, "Invalid image reference type for drawing");
4341
- ExitFunction1(hr = E_INVALIDARG);
4573
+ break;
4574
+ default:
4575
+ ExitFunction1(hr = E_INVALIDARG); // This should be unreachable because GetImageInstance should have returned null.
4576
}
4577
4578
hr = DrawGdipBitmap(hdc, destX, destY, destWidth, destHeight, pImageInstance->pBitmap, nX, nY, nWidth, nHeight);
@@ -4424,23 +4658,22 @@ static HRESULT DrawProgressBar(
4658
}
4659
4660
GetImageInstance(pTheme, pImageRef, &pInstance);
4661
+ ExitOnNull(pInstance, hr, E_INVALIDARG, "Invalid image reference for drawing.");
4662
4428
- if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pImageRef->type)
4663
+ switch (pImageRef->type)
4664
{
4665
+ case THEME_IMAGE_REFERENCE_TYPE_PARTIAL:
4666
nSourceHeight = pImageRef->nHeight;
4667
nSourceX = pImageRef->nX;
4668
nSourceY = pImageRef->nY;
4433
- }
4434
- else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pImageRef->type)
4435
- {
4669
+ break;
4670
+ case THEME_IMAGE_REFERENCE_TYPE_COMPLETE:
4671
nSourceHeight = pInstance->pBitmap->GetHeight();
4672
nSourceX = 0;
4673
nSourceY = 0;
4439
- }
4440
- else
4441
- {
4442
- AssertSz(FALSE, "Invalid image reference type for drawing");
4443
- ExitFunction1(hr = E_INVALIDARG);
4674
+ break;
4675
+ default:
4676
+ ExitFunction1(hr = E_INVALIDARG); // This should be unreachable because GetImageInstance should have returned null.
4677
}
4678
4679
// Draw the left side of the progress bar.
@@ -4721,6 +4954,21 @@ static void FreeFont(
4954
}
4955
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
+
4972
static void FreeImageInstance(
4973
__in THEME_IMAGE_INSTANCE* pImageInstance
4974
)
@@ -6232,6 +6480,7 @@ LExit:
6480
}
6481
6482
static void ResizeControls(
6483
+ __in THEME* pTheme,
6484
__in DWORD cControls,
6485
__in THEME_CONTROL* rgControls,
6486
__in const RECT* prcParent
@@ -6240,11 +6489,12 @@ static void ResizeControls(
6489
for (DWORD i = 0; i < cControls; ++i)
6490
{
6491
THEME_CONTROL* pControl = rgControls + i;
6243
- ResizeControl(pControl, prcParent);
6492
+ ResizeControl(pTheme, pControl, prcParent);
6493
}
6494
}
6495
6496
static void ResizeControl(
6497
+ __in THEME* pTheme,
6498
__in THEME_CONTROL* pControl,
6499
__in const RECT* prcParent
6500
)
@@ -6266,8 +6516,20 @@ static void ResizeControl(
6516
}
6517
#endif
6518
6269
- if (THEME_CONTROL_TYPE_LISTVIEW == pControl->type)
6519
+
6520
+ switch (pControl->type)
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:
6533
SizeListViewColumns(pControl);
6534
6535
for (DWORD j = 0; j < pControl->ListView.cColumns; ++j)
@@ -6278,12 +6540,21 @@ static void ResizeControl(
6540
return;
6541
}
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;
6552
}
6553
6554
if (pControl->cControls)
6555
{
6556
::GetClientRect(pControl->hWnd, &rcControl);
6286
- ResizeControls(pControl->cControls, pControl->rgControls, &rcControl);
6557
+ ResizeControls(pTheme, pControl->cControls, pControl->rgControls, &rcControl);
6558
}
6559
}
6560
@@ -6390,6 +6661,67 @@ static void ScaleControl(
6661
}
6662
}
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
+
6725
static void UnloadControls(
6726
__in DWORD cControls,
6727
__in THEME_CONTROL* rgControls