Add THEME_IMAGE_REFERENCE to thmutil.
Sean Hall committed
Jun 4, 2021 at 13:15 UTC
b22a62fd6eed5bb7a2c04d51828438daa621db6c
2 files changed
+293
-70
src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+29
-6
@@ -75,6 +75,13 @@ typedef enum THEME_CONTROL_TYPE
75
THEME_CONTROL_TYPE_TAB,
76
} THEME_CONTROL_TYPE;
77
78
+typedef enum THEME_IMAGE_REFERENCE_TYPE
79
+{
80
+ THEME_IMAGE_REFERENCE_TYPE_NONE,
81
+ THEME_IMAGE_REFERENCE_TYPE_PARTIAL,
82
+ THEME_IMAGE_REFERENCE_TYPE_COMPLETE,
83
+} THEME_IMAGE_REFERENCE_TYPE;
84
+
85
typedef enum THEME_SHOW_PAGE_REASON
86
{
87
THEME_SHOW_PAGE_REASON_DEFAULT,
@@ -100,6 +107,22 @@ struct THEME_COLUMN
107
};
108
109
110
+struct THEME_IMAGE_REFERENCE
111
+{
112
+ THEME_IMAGE_REFERENCE_TYPE type;
113
+ DWORD dwImageInstanceIndex;
114
+ int nX;
115
+ int nY;
116
+ int nHeight;
117
+ int nWidth;
118
+};
119
+
120
+struct THEME_IMAGE_INSTANCE
121
+{
122
+ Gdiplus::Bitmap* pBitmap;
123
+};
124
+
125
+
126
struct THEME_TAB
127
{
128
LPWSTR pszName;
@@ -159,15 +182,13 @@ struct THEME_CONTROL
182
int nY;
183
int nHeight;
184
int nWidth;
162
- int nSourceX;
163
- int nSourceY;
185
UINT uStringId;
186
187
LPWSTR sczEnableCondition;
188
LPWSTR sczVisibleCondition;
189
BOOL fDisableVariableFunctionality;
190
170
- Gdiplus::Bitmap* pBitmap;
191
+ THEME_IMAGE_REFERENCE imageRef;
192
HBITMAP hImage;
193
HICON hIcon;
194
@@ -293,15 +314,17 @@ struct THEME
314
int nMinimumWidth;
315
int nWindowHeight;
316
int nWindowWidth;
296
- int nSourceX;
297
- int nSourceY;
317
UINT uStringId;
318
300
- Gdiplus::Bitmap* pBitmap;
319
+ DWORD dwSourceImageInstanceIndex;
320
+ THEME_IMAGE_REFERENCE windowImageRef;
321
322
DWORD cFonts;
323
THEME_FONT* rgFonts;
324
325
+ DWORD cStandaloneImages;
326
+ THEME_IMAGE_INSTANCE* rgStandaloneImages;
327
+
328
DWORD cPages;
329
THEME_PAGE* rgPages;
330
src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+264
-64
@@ -42,6 +42,7 @@
42
const DWORD THEME_INVALID_ID = 0xFFFFFFFF;
43
const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF;
44
const DWORD GROW_FONT_INSTANCES = 3;
45
+const DWORD GROW_IMAGE_INSTANCES = 5;
46
const DWORD GROW_WINDOW_TEXT = 250;
47
const LPCWSTR THEME_WC_HYPERLINK = L"ThemeHyperLink";
48
const LPCWSTR THEME_WC_PANEL = L"ThemePanel";
@@ -87,6 +88,11 @@ static HRESULT ParseTheme(
88
__in IXMLDOMDocument* pixd,
89
__out THEME** ppTheme
90
);
91
+static HRESULT AddStandaloneImage(
92
+ __in THEME* pTheme,
93
+ __in Gdiplus::Bitmap** ppBitmap,
94
+ __out DWORD* pdwIndex
95
+ );
96
static HRESULT GetAttributeImageFileOrResource(
97
__in_opt HMODULE hModule,
98
__in_z_opt LPCWSTR wzRelativePath,
@@ -118,9 +124,10 @@ static HRESULT GetAttributeFontId(
124
);
125
static HRESULT ParseSourceXY(
126
__in IXMLDOMNode* pixn,
121
- __in BOOL fAllowed,
122
- __inout int* pnX,
123
- __inout int* pnY
127
+ __in THEME* pTheme,
128
+ __in int nWidth,
129
+ __in int nHeight,
130
+ __inout THEME_IMAGE_REFERENCE* pReference
131
);
132
static HRESULT ParseWindow(
133
__in_opt HMODULE hModule,
@@ -281,6 +288,20 @@ static HRESULT DrawImage(
288
__in DRAWITEMSTRUCT* pdis,
289
__in const THEME_CONTROL* pControl
290
);
291
+static void GetImageInstance(
292
+ __in THEME* pTheme,
293
+ __in const THEME_IMAGE_REFERENCE* pReference,
294
+ __out const THEME_IMAGE_INSTANCE** ppInstance
295
+ );
296
+static HRESULT DrawImageReference(
297
+ __in THEME* pTheme,
298
+ __in const THEME_IMAGE_REFERENCE* pReference,
299
+ __in HDC hdc,
300
+ __in int destX,
301
+ __in int destY,
302
+ __in int destWidth,
303
+ __in int destHeight
304
+ );
305
static HRESULT DrawGdipBitmap(
306
__in HDC hdc,
307
__in int destX,
@@ -300,7 +321,7 @@ static HRESULT DrawProgressBar(
321
);
322
static HRESULT DrawProgressBarImage(
323
__in THEME* pTheme,
303
- __in Gdiplus::Bitmap* pBitmap,
324
+ __in const THEME_IMAGE_INSTANCE* pImageInstance,
325
__in int srcX,
326
__in int srcY,
327
__in int srcWidth,
@@ -333,6 +354,9 @@ static void FreeFontInstance(
354
static void FreeFont(
355
__in THEME_FONT* pFont
356
);
357
+static void FreeImageInstance(
358
+ __in THEME_IMAGE_INSTANCE* pImageInstance
359
+ );
360
static void FreePage(
361
__in THEME_PAGE* pPage
362
);
@@ -644,6 +668,11 @@ DAPI_(void) ThemeFree(
668
FreeFont(pTheme->rgFonts + i);
669
}
670
671
+ for (DWORD i = 0; i < pTheme->cStandaloneImages; ++i)
672
+ {
673
+ FreeImageInstance(pTheme->rgStandaloneImages + i);
674
+ }
675
+
676
for (DWORD i = 0; i < pTheme->cPages; ++i)
677
{
678
FreePage(pTheme->rgPages + i);
@@ -661,13 +690,9 @@ DAPI_(void) ThemeFree(
690
691
ReleaseMem(pTheme->rgControls);
692
ReleaseMem(pTheme->rgPages);
693
+ ReleaseMem(pTheme->rgStandaloneImages);
694
ReleaseMem(pTheme->rgFonts);
695
666
- if (pTheme->pBitmap)
667
- {
668
- delete pTheme->pBitmap;
669
- }
670
-
696
ReleaseStr(pTheme->sczCaption);
697
ReleaseMem(pTheme);
698
}
@@ -1305,9 +1330,9 @@ DAPI_(HRESULT) ThemeDrawBackground(
1330
{
1331
HRESULT hr = S_FALSE;
1332
1308
- if (pTheme->pBitmap && 0 <= pTheme->nSourceX && 0 <= pTheme->nSourceY && pps->fErase)
1333
+ if (pps->fErase && THEME_IMAGE_REFERENCE_TYPE_NONE != pTheme->windowImageRef.type)
1334
{
1310
- hr = DrawGdipBitmap(pps->hdc, 0, 0, pTheme->nWidth, pTheme->nHeight, pTheme->pBitmap, pTheme->nSourceX, pTheme->nSourceY, pTheme->nDefaultDpiWidth, pTheme->nDefaultDpiHeight);
1335
+ hr = DrawImageReference(pTheme, &pTheme->windowImageRef, pps->hdc, 0, 0, pTheme->nWidth, pTheme->nHeight);
1336
}
1337
1338
return hr;
@@ -1743,6 +1768,7 @@ static HRESULT ParseTheme(
1768
HRESULT hr = S_OK;
1769
THEME* pTheme = NULL;
1770
IXMLDOMElement *pThemeElement = NULL;
1771
+ Gdiplus::Bitmap* pBitmap = NULL;
1772
BOOL fXmlFound = FALSE;
1773
1774
hr = pixd->get_documentElement(&pThemeElement);
@@ -1755,9 +1781,19 @@ static HRESULT ParseTheme(
1781
pTheme->nDpi = USER_DEFAULT_SCREEN_DPI;
1782
1783
// Parse the optional background resource image.
1758
- hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pThemeElement, &pTheme->pBitmap);
1784
+ hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pThemeElement, &pBitmap);
1785
ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing theme image.");
1786
1787
+ if (fXmlFound)
1788
+ {
1789
+ hr = AddStandaloneImage(pTheme, &pBitmap, &pTheme->dwSourceImageInstanceIndex);
1790
+ ThmExitOnFailure(hr, "Failed to store theme image.");
1791
+ }
1792
+ else
1793
+ {
1794
+ pTheme->dwSourceImageInstanceIndex = THEME_INVALID_ID;
1795
+ }
1796
+
1797
// Parse the fonts.
1798
hr = ParseFonts(pThemeElement, pTheme);
1799
ThmExitOnFailure(hr, "Failed to parse theme fonts.");
@@ -1772,6 +1808,11 @@ static HRESULT ParseTheme(
1808
LExit:
1809
ReleaseObject(pThemeElement);
1810
1811
+ if (pBitmap)
1812
+ {
1813
+ delete pBitmap;
1814
+ }
1815
+
1816
if (pTheme)
1817
{
1818
ThemeFree(pTheme);
@@ -1780,6 +1821,30 @@ LExit:
1821
return hr;
1822
}
1823
1824
+static HRESULT AddStandaloneImage(
1825
+ __in THEME* pTheme,
1826
+ __in Gdiplus::Bitmap** ppBitmap,
1827
+ __out DWORD* pdwIndex
1828
+ )
1829
+{
1830
+ HRESULT hr = S_OK;
1831
+ THEME_IMAGE_INSTANCE* pInstance = NULL;
1832
+
1833
+ hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pTheme->rgStandaloneImages), pTheme->cStandaloneImages, 1, sizeof(THEME_IMAGE_INSTANCE), GROW_IMAGE_INSTANCES);
1834
+ ThmExitOnFailure(hr, "Failed to allocate memory for image instances.");
1835
+
1836
+ *pdwIndex = pTheme->cStandaloneImages;
1837
+ ++pTheme->cStandaloneImages;
1838
+
1839
+ pInstance = pTheme->rgStandaloneImages + *pdwIndex;
1840
+
1841
+ pInstance->pBitmap = *ppBitmap;
1842
+ *ppBitmap = NULL;
1843
+
1844
+LExit:
1845
+ return hr;
1846
+}
1847
+
1848
static HRESULT GetAttributeImageFileOrResource(
1849
__in_opt HMODULE hModule,
1850
__in_z_opt LPCWSTR wzRelativePath,
@@ -1864,17 +1929,23 @@ static HRESULT ParseOwnerDrawImage(
1929
HRESULT hr = S_OK;
1930
BOOL fXmlFound = FALSE;
1931
BOOL fFoundImage = FALSE;
1932
+ Gdiplus::Bitmap* pBitmap = NULL;
1933
1934
// Parse the optional background resource image.
1869
- hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pControl->pBitmap);
1935
+ hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pBitmap);
1936
ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing control image.");
1937
1938
if (fXmlFound)
1939
{
1940
+ hr = AddStandaloneImage(pTheme, &pBitmap, &pControl->imageRef.dwImageInstanceIndex);
1941
+ ThmExitOnFailure(hr, "Failed to store owner draw image.");
1942
+
1943
+ pControl->imageRef.type = THEME_IMAGE_REFERENCE_TYPE_COMPLETE;
1944
+
1945
fFoundImage = TRUE;
1946
}
1947
1877
- hr = ParseSourceXY(pElement, NULL != pTheme->pBitmap, &pControl->nSourceX, &pControl->nSourceY);
1948
+ hr = ParseSourceXY(pElement, pTheme, pControl->nWidth, pControl->nHeight, &pControl->imageRef);
1949
ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get control SourceX and SourceY attributes.");
1950
1951
if (fXmlFound)
@@ -1897,6 +1968,11 @@ static HRESULT ParseOwnerDrawImage(
1968
}
1969
1970
LExit:
1971
+ if (pBitmap)
1972
+ {
1973
+ delete pBitmap;
1974
+ }
1975
+
1976
return hr;
1977
}
1978
@@ -2042,35 +2118,50 @@ LExit:
2118
2119
static HRESULT ParseSourceXY(
2120
__in IXMLDOMNode* pixn,
2045
- __in BOOL fAllowed,
2046
- __inout int* pnX,
2047
- __inout int* pnY
2121
+ __in THEME* pTheme,
2122
+ __in int nWidth,
2123
+ __in int nHeight,
2124
+ __inout THEME_IMAGE_REFERENCE* pReference
2125
)
2126
{
2127
HRESULT hr = S_OK;
2128
BOOL fXFound = FALSE;
2129
BOOL fYFound = FALSE;
2053
-
2054
- hr = GetAttributeCoordinateOrDimension(pixn, L"SourceX", pnX);
2130
+ int nX = 0;
2131
+ int nY = 0;
2132
+ DWORD dwImageInstanceIndex = pTheme->dwSourceImageInstanceIndex;
2133
+ THEME_IMAGE_INSTANCE* pInstance = THEME_INVALID_ID != dwImageInstanceIndex ? pTheme->rgStandaloneImages + dwImageInstanceIndex : NULL;
2134
+ int nSourceWidth = pInstance ? pInstance->pBitmap->GetWidth() : 0;
2135
+ int nSourceHeight = pInstance ? pInstance->pBitmap->GetHeight() : 0;
2136
+
2137
+ hr = GetAttributeCoordinateOrDimension(pixn, L"SourceX", &nX);
2138
ThmExitOnOptionalXmlQueryFailure(hr, fXFound, "Failed to get SourceX attribute.");
2139
2140
if (!fXFound)
2141
{
2059
- *pnX = -1;
2142
+ nX = -1;
2143
}
2144
else
2145
{
2063
- if (!fAllowed)
2146
+ if (!pInstance)
2147
{
2148
ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceX cannot be specified without an image specified on Theme.");
2149
}
2067
- else if (0 > *pnX)
2150
+ else if (0 > nX)
2151
{
2152
ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceX must be non-negative.");
2153
}
2154
+ else if (nSourceWidth <= nX)
2155
+ {
2156
+ ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceX (%i) must be less than the image width: %i.", nX, nSourceWidth);
2157
+ }
2158
+ else if (nSourceWidth <= (nX + nWidth))
2159
+ {
2160
+ ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceX (%i) with width %i must be less than the image width: %i.", nX, nWidth, nSourceWidth);
2161
+ }
2162
}
2163
2073
- hr = GetAttributeCoordinateOrDimension(pixn, L"SourceY", pnY);
2164
+ hr = GetAttributeCoordinateOrDimension(pixn, L"SourceY", &nY);
2165
ThmExitOnOptionalXmlQueryFailure(hr, fYFound, "Failed to get SourceY attribute.");
2166
2167
if (!fYFound)
@@ -2080,12 +2171,11 @@ static HRESULT ParseSourceXY(
2171
ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY must be specified with SourceX.");
2172
}
2173
2083
- *pnY = -1;
2084
- hr = E_NOTFOUND;
2174
+ ExitFunction1(hr = E_NOTFOUND);
2175
}
2176
else
2177
{
2088
- if (!fAllowed)
2178
+ if (!pInstance)
2179
{
2180
ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY cannot be specified without an image specified on Theme.");
2181
}
@@ -2093,12 +2183,27 @@ static HRESULT ParseSourceXY(
2183
{
2184
ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY must be specified with SourceX.");
2185
}
2096
- else if (0 > *pnY)
2186
+ else if (0 > nY)
2187
{
2188
ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY must be non-negative.");
2189
}
2190
+ else if (nSourceHeight <= nY)
2191
+ {
2192
+ ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY (%i) must be less than the image height: %i.", nY, nSourceHeight);
2193
+ }
2194
+ else if (nSourceHeight <= (nY + nHeight))
2195
+ {
2196
+ ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY (%i) with height %i must be less than the image height: %i.", nY, nHeight, nSourceHeight);
2197
+ }
2198
}
2199
2200
+ pReference->type = THEME_IMAGE_REFERENCE_TYPE_PARTIAL;
2201
+ pReference->dwImageInstanceIndex = dwImageInstanceIndex;
2202
+ pReference->nX = nX;
2203
+ pReference->nY = nY;
2204
+ pReference->nWidth = nWidth;
2205
+ pReference->nHeight = nHeight;
2206
+
2207
LExit:
2208
return hr;
2209
}
@@ -2220,7 +2325,7 @@ static HRESULT ParseWindow(
2325
ReleaseNullBSTR(bstr);
2326
}
2327
2223
- hr = ParseSourceXY(pixn, NULL != pTheme->pBitmap, &pTheme->nSourceX, &pTheme->nSourceY);
2328
+ hr = ParseSourceXY(pixn, pTheme, pTheme->nDefaultDpiWidth, pTheme->nDefaultDpiHeight, &pTheme->windowImageRef);
2329
ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window SourceX and SourceY attributes.");
2330
2331
// Parse the optional window style.
@@ -2230,7 +2335,7 @@ static HRESULT ParseWindow(
2335
if (!fXmlFound)
2336
{
2337
pTheme->dwStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION;
2233
- pTheme->dwStyle |= (0 <= pTheme->nSourceX && 0 <= pTheme->nSourceY) ? WS_POPUP : WS_OVERLAPPED;
2338
+ pTheme->dwStyle |= (THEME_IMAGE_REFERENCE_TYPE_NONE != pTheme->windowImageRef.type) ? WS_POPUP : WS_OVERLAPPED;
2339
}
2340
2341
hr = XmlGetAttributeUInt32(pixn, L"StringId", reinterpret_cast<DWORD*>(&pTheme->uStringId));
@@ -3171,8 +3276,6 @@ static void InitializeThemeControl(
3276
pControl->dwFontHoverId = THEME_INVALID_ID;
3277
pControl->dwFontId = THEME_INVALID_ID;
3278
pControl->dwFontSelectedId = THEME_INVALID_ID;
3174
- pControl->nSourceX = -1;
3175
- pControl->nSourceY = -1;
3279
pControl->uStringId = UINT_MAX;
3280
}
3281
@@ -3889,35 +3992,57 @@ static HRESULT DrawButton(
3992
)
3993
{
3994
HRESULT hr = S_OK;
3892
- int nSourceX = pControl->pBitmap ? 0 : pControl->nSourceX;
3893
- int nSourceY = pControl->pBitmap ? 0 : pControl->nSourceY;
3894
- int nSourceWidth = pControl->pBitmap ? pControl->pBitmap->GetWidth() : pControl->nDefaultDpiWidth;
3895
- int nSourceHeight = pControl->pBitmap ? pControl->pBitmap->GetHeight() / 4 : pControl->nDefaultDpiHeight;
3896
- Gdiplus::Bitmap* pBitmap = pControl->pBitmap ? pControl->pBitmap : pTheme->pBitmap;
3995
+ THEME_IMAGE_REFERENCE buttonImageRef = { };
3996
+ const THEME_IMAGE_INSTANCE* pInstance = NULL;
3997
int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
3998
int nWidth = pdis->rcItem.right - pdis->rcItem.left;
3999
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
4026
if (ODS_SELECTED & pdis->itemState)
4027
{
3904
- nSourceY += nSourceHeight * 2;
4028
+ buttonImageRef.nY += buttonImageRef.nHeight * 2;
4029
}
4030
// then hover
4031
else if (pControl->dwData & THEME_CONTROL_DATA_HOVER)
4032
{
3909
- nSourceY += nSourceHeight;
4033
+ buttonImageRef.nY += buttonImageRef.nHeight;
4034
}
4035
// then focused
4036
else if ((WS_TABSTOP & dwStyle) && (ODS_FOCUS & pdis->itemState))
4037
{
3914
- nSourceY += nSourceHeight * 3;
4038
+ buttonImageRef.nY += buttonImageRef.nHeight * 3;
4039
}
4040
3917
- hr = DrawGdipBitmap(pdis->hDC, 0, 0, nWidth, nHeight, pBitmap, nSourceX, nSourceY, nSourceWidth, nSourceHeight);
4041
+ hr = DrawImageReference(pTheme, &buttonImageRef, pdis->hDC, 0, 0, nWidth, nHeight);
4042
4043
DrawControlText(pTheme, pdis, pControl, TRUE, FALSE);
4044
4045
+LExit:
4046
return hr;
4047
}
4048
@@ -3996,17 +4121,65 @@ static HRESULT DrawImage(
4121
HRESULT hr = S_OK;
4122
int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
4123
int nWidth = pdis->rcItem.right - pdis->rcItem.left;
3999
- int nSourceX = pControl->pBitmap ? 0 : pControl->nSourceX;
4000
- int nSourceY = pControl->pBitmap ? 0 : pControl->nSourceY;
4001
- int nSourceWidth = pControl->pBitmap ? pControl->pBitmap->GetWidth() : pControl->nDefaultDpiWidth;
4002
- int nSourceHeight = pControl->pBitmap ? pControl->pBitmap->GetHeight() : pControl->nDefaultDpiHeight;
4003
- Gdiplus::Bitmap* pBitmap = pControl->pBitmap ? pControl->pBitmap : pTheme->pBitmap;
4124
4005
- hr = DrawGdipBitmap(pdis->hDC, 0, 0, nWidth, nHeight, pBitmap, nSourceX, nSourceY, nSourceWidth, nSourceHeight);
4125
+ hr = DrawImageReference(pTheme, &pControl->imageRef, pdis->hDC, 0, 0, nWidth, nHeight);
4126
4127
return hr;
4128
}
4129
4130
+static void GetImageInstance(
4131
+ __in THEME* pTheme,
4132
+ __in const THEME_IMAGE_REFERENCE* pReference,
4133
+ __out const THEME_IMAGE_INSTANCE** ppInstance
4134
+ )
4135
+{
4136
+ *ppInstance = pTheme->rgStandaloneImages + pReference->dwImageInstanceIndex;
4137
+}
4138
+
4139
+static HRESULT DrawImageReference(
4140
+ __in THEME* pTheme,
4141
+ __in const THEME_IMAGE_REFERENCE* pReference,
4142
+ __in HDC hdc,
4143
+ __in int destX,
4144
+ __in int destY,
4145
+ __in int destWidth,
4146
+ __in int destHeight
4147
+ )
4148
+{
4149
+ HRESULT hr = S_OK;
4150
+ const THEME_IMAGE_INSTANCE* pImageInstance = NULL;
4151
+ int nX = 0;
4152
+ int nY = 0;
4153
+ int nWidth = 0;
4154
+ int nHeight = 0;
4155
+
4156
+ GetImageInstance(pTheme, pReference, &pImageInstance);
4157
+ if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pReference->type)
4158
+ {
4159
+ nX = pReference->nX;
4160
+ nY = pReference->nY;
4161
+ nWidth = pReference->nWidth;
4162
+ nHeight = pReference->nHeight;
4163
+ }
4164
+ else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pReference->type)
4165
+ {
4166
+ nX = 0;
4167
+ nY = 0;
4168
+ nWidth = pImageInstance->pBitmap->GetWidth();
4169
+ nHeight = pImageInstance->pBitmap->GetHeight();
4170
+ }
4171
+ else
4172
+ {
4173
+ AssertSz(FALSE, "Invalid image reference type for drawing");
4174
+ ExitFunction1(hr = E_INVALIDARG);
4175
+ }
4176
+
4177
+ hr = DrawGdipBitmap(hdc, destX, destY, destWidth, destHeight, pImageInstance->pBitmap, nX, nY, nWidth, nHeight);
4178
+
4179
+LExit:
4180
+ return hr;
4181
+}
4182
+
4183
static HRESULT DrawGdipBitmap(
4184
__in HDC hdc,
4185
__in int destX,
@@ -4069,36 +4242,56 @@ static HRESULT DrawProgressBar(
4242
HRESULT hr = S_OK;
4243
WORD wProgressColor = HIWORD(pControl->dwData);
4244
WORD wProgressPercentage = LOWORD(pControl->dwData);
4245
+ const THEME_IMAGE_INSTANCE* pInstance = NULL;
4246
int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
4073
- int nSourceHeight = pControl->nDefaultDpiHeight;
4074
- int nSourceX = pControl->pBitmap ? 0 : pControl->nSourceX;
4075
- int nSourceY = (pControl->pBitmap ? 0 : pControl->nSourceY) + (wProgressColor * nSourceHeight);
4247
+ int nSourceHeight = 0;
4248
+ int nSourceX = 0;
4249
+ int nSourceY = 0;
4250
int nFillableWidth = pdis->rcItem.right - 2 * nSideWidth;
4251
int nCenter = nFillableWidth > 0 ? nFillableWidth * wProgressPercentage / 100 : 0;
4078
- Gdiplus::Bitmap* pBitmap = pControl->pBitmap ? pControl->pBitmap : pTheme->pBitmap;
4252
4253
if (0 > nFillableWidth)
4254
{
4255
ExitFunction1(hr = S_FALSE);
4256
}
4257
4258
+ GetImageInstance(pTheme, &pControl->imageRef, &pInstance);
4259
+
4260
+ if (THEME_IMAGE_REFERENCE_TYPE_PARTIAL == pControl->imageRef.type)
4261
+ {
4262
+ nSourceHeight = pControl->imageRef.nHeight;
4263
+ nSourceX = pControl->imageRef.nX;
4264
+ nSourceY = pControl->imageRef.nY + (wProgressColor * nSourceHeight);
4265
+ }
4266
+ else if (THEME_IMAGE_REFERENCE_TYPE_COMPLETE == pControl->imageRef.type)
4267
+ {
4268
+ nSourceHeight = pControl->nDefaultDpiHeight;
4269
+ nSourceX = 0;
4270
+ nSourceY = wProgressColor * nSourceHeight;
4271
+ }
4272
+ else
4273
+ {
4274
+ AssertSz(FALSE, "Invalid image reference type for drawing");
4275
+ ExitFunction1(hr = E_INVALIDARG);
4276
+ }
4277
+
4278
// Draw the left side of the progress bar.
4086
- hr = DrawProgressBarImage(pTheme, pBitmap, nSourceX, nSourceY, 1, nSourceHeight, pdis->hDC, 0, 0, nSideWidth, nHeight);
4279
+ hr = DrawProgressBarImage(pTheme, pInstance, nSourceX, nSourceY, 1, nSourceHeight, pdis->hDC, 0, 0, nSideWidth, nHeight);
4280
4281
// Draw the filled side of the progress bar, if there is any.
4282
if (0 < nCenter)
4283
{
4091
- hr = DrawProgressBarImage(pTheme, pBitmap, nSourceX + 1, nSourceY, 1, nSourceHeight, pdis->hDC, nSideWidth, 0, nCenter, nHeight);
4284
+ hr = DrawProgressBarImage(pTheme, pInstance, nSourceX + 1, nSourceY, 1, nSourceHeight, pdis->hDC, nSideWidth, 0, nCenter, nHeight);
4285
}
4286
4287
// Draw the unfilled side of the progress bar, if there is any.
4288
if (nCenter < nFillableWidth)
4289
{
4097
- hr = DrawProgressBarImage(pTheme, pBitmap, nSourceX + 2, nSourceY, 1, nSourceHeight, pdis->hDC, nSideWidth + nCenter, 0, pdis->rcItem.right - nCenter - nSideWidth, nHeight);
4290
+ hr = DrawProgressBarImage(pTheme, pInstance, nSourceX + 2, nSourceY, 1, nSourceHeight, pdis->hDC, nSideWidth + nCenter, 0, pdis->rcItem.right - nCenter - nSideWidth, nHeight);
4291
}
4292
4293
// Draw the right side of the progress bar.
4101
- hr = DrawProgressBarImage(pTheme, pBitmap, nSourceX + 3, nSourceY, 1, nSourceHeight, pdis->hDC, pdis->rcItem.right - nSideWidth, 0, nSideWidth, nHeight);
4294
+ hr = DrawProgressBarImage(pTheme, pInstance, nSourceX + 3, nSourceY, 1, nSourceHeight, pdis->hDC, pdis->rcItem.right - nSideWidth, 0, nSideWidth, nHeight);
4295
4296
LExit:
4297
return hr;
@@ -4106,7 +4299,7 @@ LExit:
4299
4300
static HRESULT DrawProgressBarImage(
4301
__in THEME* /*pTheme*/,
4109
- __in Gdiplus::Bitmap* pBitmap,
4302
+ __in const THEME_IMAGE_INSTANCE* pImageInstance,
4303
__in int srcX,
4304
__in int srcY,
4305
__in int srcWidth,
@@ -4125,7 +4318,7 @@ static HRESULT DrawProgressBarImage(
4318
graphics.SetCompositingMode(Gdiplus::CompositingMode::CompositingModeSourceCopy);
4319
4320
// Isolate the source rectangle into a temporary bitmap because otherwise GDI+ would use pixels outside of that rectangle when stretching.
4128
- Gdiplus::Status gs = graphics.DrawImage(pBitmap, dest, srcX, srcY, srcWidth, srcHeight, Gdiplus::Unit::UnitPixel);
4321
+ Gdiplus::Status gs = graphics.DrawImage(pImageInstance->pBitmap, dest, srcX, srcY, srcWidth, srcHeight, Gdiplus::Unit::UnitPixel);
4322
hr = GdipHresultFromStatus(gs);
4323
if (SUCCEEDED(hr))
4324
{
@@ -4218,11 +4411,6 @@ static void FreeControl(
4411
ReleaseStr(pControl->sczValue);
4412
ReleaseStr(pControl->sczVariable);
4413
4221
- if (pControl->pBitmap)
4222
- {
4223
- delete pControl->pBitmap;
4224
- }
4225
-
4414
if (pControl->hImage)
4415
{
4416
::DeleteBitmap(pControl->hImage);
@@ -4351,6 +4539,17 @@ static void FreeFont(
4539
}
4540
4541
4542
+static void FreeImageInstance(
4543
+ __in THEME_IMAGE_INSTANCE* pImageInstance
4544
+ )
4545
+{
4546
+ if (pImageInstance->pBitmap)
4547
+ {
4548
+ delete pImageInstance->pBitmap;
4549
+ }
4550
+}
4551
+
4552
+
4553
static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
4554
__in DWORD_PTR dwCookie,
4555
__in_bcount(cb) LPBYTE pbBuff,
@@ -5298,6 +5497,7 @@ static HRESULT LoadControls(
5497
LPCWSTR wzWindowClass = NULL;
5498
DWORD dwWindowBits = WS_CHILD;
5499
DWORD dwWindowExBits = 0;
5500
+ BOOL fOwnerDrawImage = THEME_IMAGE_REFERENCE_TYPE_NONE != pControl->imageRef.type;
5501
5502
if (fStartNewGroup)
5503
{
@@ -5322,7 +5522,7 @@ static HRESULT LoadControls(
5522
__fallthrough;
5523
case THEME_CONTROL_TYPE_BUTTON:
5524
wzWindowClass = WC_BUTTONW;
5325
- if (pControl->pBitmap || (pTheme->pBitmap && 0 <= pControl->nSourceX && 0 <= pControl->nSourceY))
5525
+ if (fOwnerDrawImage)
5526
{
5527
dwWindowBits |= BS_OWNERDRAW;
5528
pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_OWNER_DRAW;
@@ -5356,7 +5556,7 @@ static HRESULT LoadControls(
5556
break;
5557
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).
5359
- if (pControl->pBitmap || (pTheme->pBitmap && 0 <= pControl->nSourceX && 0 <= pControl->nSourceY))
5559
+ if (fOwnerDrawImage)
5560
{
5561
wzWindowClass = THEME_WC_STATICOWNERDRAW;
5562
dwWindowBits |= SS_OWNERDRAW;
@@ -5383,7 +5583,7 @@ static HRESULT LoadControls(
5583
break;
5584
5585
case THEME_CONTROL_TYPE_PROGRESSBAR:
5386
- if (pControl->pBitmap || (pTheme->pBitmap && 0 <= pControl->nSourceX && 0 <= pControl->nSourceY))
5586
+ if (fOwnerDrawImage)
5587
{
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.
5589
dwWindowBits |= SS_OWNERDRAW;