@joebigelow / wix-1 / commits / 8fa040da

Allow more customization of control ids in thmutil.

Allow BAFunctions to set control ids. Make sure control ids don't collide.

Sean Hall committed Oct 27, 2021 at 13:55 UTC 8fa040da9d0d3826f5ffda6bcbec4f53abd97452
13 files changed +374 -48
src/api/burn/balutil/inc/BAFunctions.h
+18
@@ -85,6 +85,7 @@ enum BA_FUNCTIONS_MESSAGE
85
86 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
87 BA_FUNCTIONS_MESSAGE_WNDPROC,
88 + BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING,
89 };
90
91 typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)(
@@ -94,6 +95,10 @@ typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)(
95 __in_opt LPVOID pvContext
96 );
97
98 +// Should be the same as THEME_FIRST_ASSIGN_CONTROL_ID.
99 +// BAFunctions must only assign ids in the range [BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID, 0x8000) to avoid collisions.
100 +const WORD BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID = 0x4000;
101 +
102 struct BA_FUNCTIONS_CREATE_ARGS
103 {
104 DWORD cbSize;
@@ -108,6 +113,19 @@ struct BA_FUNCTIONS_CREATE_RESULTS
113 LPVOID pvBAFunctionsProcContext;
114 };
115
116 +struct BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS
117 +{
118 + DWORD cbSize;
119 + LPCWSTR wzName;
120 +};
121 +
122 +struct BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS
123 +{
124 + DWORD cbSize;
125 + BOOL fProcessed;
126 + WORD wId;
127 +};
128 +
129 struct BA_FUNCTIONS_ONTHEMELOADED_ARGS
130 {
131 DWORD cbSize;
src/api/burn/balutil/inc/BalBaseBAFunctions.h
+9
@@ -841,6 +841,15 @@ public: // IBAFunctions
841 return E_NOTIMPL;
842 }
843
844 + virtual STDMETHODIMP OnThemeControlLoading(
845 + __in LPCWSTR /*wzName*/,
846 + __inout BOOL* /*pfProcessed*/,
847 + __inout WORD* /*pwId*/
848 + )
849 + {
850 + return S_OK;
851 + }
852 +
853 protected:
854 CBalBaseBAFunctions(
855 __in HMODULE hModule,
src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+12
@@ -24,6 +24,15 @@ static HRESULT BalBaseBAFunctionsProcWndProc(
24 return pBAFunctions->WndProc(pArgs->pTheme, pArgs->hWnd, pArgs->uMsg, pArgs->wParam, pArgs->lParam, &pResults->lres);
25 }
26
27 +static HRESULT BalBaseBAFunctionsProcOnThemeControlLoading(
28 + __in IBAFunctions* pBAFunctions,
29 + __in BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS* pArgs,
30 + __inout BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS* pResults
31 + )
32 +{
33 + return pBAFunctions->OnThemeControlLoading(pArgs->wzName, &pResults->fProcessed, &pResults->wId);
34 +}
35 +
36 /*******************************************************************
37 BalBaseBAFunctionsProc - requires pvContext to be of type IBAFunctions.
38 Provides a default mapping between the message based BAFunctions interface and
@@ -125,6 +134,9 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
134 case BA_FUNCTIONS_MESSAGE_WNDPROC:
135 hr = BalBaseBAFunctionsProcWndProc(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_WNDPROC_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_WNDPROC_RESULTS*>(pvResults));
136 break;
137 + case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING:
138 + hr = BalBaseBAFunctionsProcOnThemeControlLoading(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS*>(pvResults));
139 + break;
140 }
141 }
142
src/api/burn/balutil/inc/IBAFunctions.h
+8
@@ -31,4 +31,12 @@ DECLARE_INTERFACE_IID_(IBAFunctions, IBootstrapperApplication, "0FB445ED-17BD-49
31 __inout LPVOID pvResults,
32 __in_opt LPVOID pvContext
33 ) = 0;
34 +
35 + // OnThemeControlLoading - Called while creating a control for the theme.
36 + //
37 + STDMETHOD(OnThemeControlLoading)(
38 + __in LPCWSTR wzName,
39 + __inout BOOL* pfProcessed,
40 + __inout WORD* pwId
41 + ) = 0;
42 };
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+62 -3
@@ -77,10 +77,15 @@ static LPCWSTR vrgwzPageNames[] = {
77 L"Failure",
78 };
79
80 +// The range [0, 100) is unused to avoid collisions with system ids,
81 +// the range [100, 0x4000) is unused to avoid collisions with thmutil,
82 +// the range [0x4000, 0x8000) is unused to avoid collisions with BAFunctions.
83 +const WORD WIXSTDBA_FIRST_ASSIGN_CONTROL_ID = 0x8000;
84 +
85 enum WIXSTDBA_CONTROL
86 {
87 // Welcome page
83 - WIXSTDBA_CONTROL_INSTALL_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID,
88 + WIXSTDBA_CONTROL_INSTALL_BUTTON = WIXSTDBA_FIRST_ASSIGN_CONTROL_ID,
89 WIXSTDBA_CONTROL_EULA_RICHEDIT,
90 WIXSTDBA_CONTROL_EULA_LINK,
91 WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX,
@@ -2833,6 +2838,9 @@ private:
2838 }
2839 break;
2840
2841 + case WM_THMUTIL_LOADING_CONTROL:
2842 + return pBA->OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
2843 +
2844 case WM_QUERYENDSESSION:
2845 fCancel = true;
2846 pBA->OnSystemShutdown(static_cast<DWORD>(lParam), &fCancel);
@@ -2956,7 +2964,7 @@ private:
2964 BA_FUNCTIONS_ONTHEMELOADED_ARGS themeLoadedArgs = { };
2965 BA_FUNCTIONS_ONTHEMELOADED_RESULTS themeLoadedResults = { };
2966
2959 - hr = ThemeLoadControls(m_pTheme, vrgInitControls, countof(vrgInitControls));
2967 + hr = ThemeLoadControls(m_pTheme);
2968 BalExitOnFailure(hr, "Failed to load theme controls.");
2969
2970 C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames));
@@ -3029,6 +3037,57 @@ private:
3037 return SUCCEEDED(hr);
3038 }
3039
3040 + BOOL OnThemeLoadingControl(
3041 + __in const THEME_LOADINGCONTROL_ARGS* pArgs,
3042 + __in THEME_LOADINGCONTROL_RESULTS* pResults
3043 + )
3044 + {
3045 + HRESULT hr = S_OK;
3046 + BOOL fProcessed = FALSE;
3047 + BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS themeControlLoadingArgs = { };
3048 + BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS themeControlLoadingResults = { };
3049 +
3050 + for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
3051 + {
3052 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
3053 + {
3054 + fProcessed = TRUE;
3055 + pResults->wId = vrgInitControls[iAssignControl].wId;
3056 + ExitFunction();
3057 + }
3058 + }
3059 +
3060 + if (m_pfnBAFunctionsProc)
3061 + {
3062 + themeControlLoadingArgs.cbSize = sizeof(themeControlLoadingArgs);
3063 + themeControlLoadingArgs.wzName = pArgs->pThemeControl->sczName;
3064 +
3065 + themeControlLoadingResults.cbSize = sizeof(themeControlLoadingResults);
3066 + themeControlLoadingResults.wId = pResults->wId;
3067 +
3068 + hr = m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING, &themeControlLoadingArgs, &themeControlLoadingResults, m_pvBAFunctionsProcContext);
3069 +
3070 + if (E_NOTIMPL == hr)
3071 + {
3072 + hr = S_OK;
3073 + }
3074 + else
3075 + {
3076 + BalExitOnFailure(hr, "BAFunctions OnThemeControlLoading failed.");
3077 +
3078 + if (themeControlLoadingResults.fProcessed)
3079 + {
3080 + fProcessed = TRUE;
3081 + pResults->wId = themeControlLoadingResults.wId;
3082 + }
3083 + }
3084 + }
3085 +
3086 + LExit:
3087 + pResults->hr = hr;
3088 + return fProcessed || FAILED(hr);
3089 + }
3090 +
3091
3092 //
3093 // OnShowFailure - display the failure page.
@@ -3857,7 +3916,7 @@ private:
3916 BalExitOnNullWithLastError(pfnBAFunctionsCreate, hr, "Failed to get BAFunctionsCreate entry-point from: %ls", sczBafPath);
3917
3918 bafCreateArgs.cbSize = sizeof(bafCreateArgs);
3860 - bafCreateArgs.qwBAFunctionsAPIVersion = MAKEQWORDVERSION(0, 0, 0, 2); // TODO: need to decide whether to keep this, and if so when to update it.
3919 + bafCreateArgs.qwBAFunctionsAPIVersion = MAKEQWORDVERSION(2021, 9, 20, 0);
3920 bafCreateArgs.pBootstrapperCreateArgs = &m_createArgs;
3921
3922 bafCreateResults.cbSize = sizeof(bafCreateResults);
src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+30 -5
@@ -95,6 +95,15 @@ typedef enum THEME_WINDOW_INITIAL_POSITION
95 THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES,
96 } THEME_WINDOW_INITIAL_POSITION;
97
98 +// These messages are sent by thmutil to the parent window created in ThemeCreateParentWindow.
99 +// thmutil reserves the last values of WM_USER's range.
100 +typedef enum _WM_THMUTIL
101 +{
102 + // Sent while creating a control.
103 + // wparam is THEME_LOADINGCONTROL_ARGS* and lparam is THEME_LOADINGCONTROL_RESULTS*.
104 + // Return code is TRUE if it was processed.
105 + WM_THMUTIL_LOADING_CONTROL = WM_APP - 1,
106 +} WM_THMUTIL;
107
108 struct THEME_COLUMN
109 {
@@ -171,7 +180,7 @@ struct THEME_ASSIGN_CONTROL_ID
180 LPCWSTR wzName; // name of control to match
181 };
182
174 -const DWORD THEME_FIRST_ASSIGN_CONTROL_ID = 1024; // Recommended first control id to be assigned.
183 +const WORD THEME_FIRST_ASSIGN_CONTROL_ID = 0x4000; // Recommended first control id to be assigned.
184
185 struct THEME_CONTROL
186 {
@@ -325,7 +334,7 @@ struct THEME_FONT
334
335 struct THEME
336 {
328 - WORD wId;
337 + WORD wNextControlId;
338
339 BOOL fAutoResize;
340 BOOL fForceResize;
@@ -388,6 +397,24 @@ struct THEME
397 LPVOID pvVariableContext;
398 };
399
400 +typedef struct _THEME_LOADINGCONTROL_ARGS
401 +{
402 + DWORD cbSize;
403 + const THEME_CONTROL* pThemeControl;
404 +} THEME_LOADINGCONTROL_ARGS;
405 +
406 +typedef struct _THEME_LOADINGCONTROL_RESULTS
407 +{
408 + DWORD cbSize;
409 + HRESULT hr;
410 +
411 + // Used to apply a specific id to the control (usually used for WM_COMMAND).
412 + // If assigning an id, it is recommended to start with THEME_FIRST_ASSIGN_CONTROL_ID to avoid collisions with well known ids such as IDOK and IDCANCEL.
413 + // The values [100, THEME_FIRST_ASSIGN_CONTROL_ID) are reserved for thmutil.
414 + // Due to this value being packed into 16 bits for many system window messages, this is restricted to a WORD.
415 + WORD wId;
416 +} THEME_LOADINGCONTROL_RESULTS;
417 +
418
419 /********************************************************************
420 ThemeInitialize - initialized theme management.
@@ -472,9 +499,7 @@ HRESULT DAPI ThemeCreateParentWindow(
499
500 *******************************************************************/
501 HRESULT DAPI ThemeLoadControls(
475 - __in THEME* pTheme,
476 - __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
477 - __in DWORD cAssignControlIds
502 + __in THEME* pTheme
503 );
504
505 /********************************************************************
src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+51 -24
@@ -39,6 +39,7 @@
39 #define LWS_NOPREFIX 0x0004
40 #endif
41
42 +const WORD THEME_FIRST_AUTO_ASSIGN_CONTROL_ID = 100;
43 const DWORD THEME_INVALID_ID = 0xFFFFFFFF;
44 const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF;
45 const DWORD GROW_FONT_INSTANCES = 3;
@@ -272,11 +273,14 @@ static HRESULT FindImageList(
273 __in_z LPCWSTR wzImageListName,
274 __out HIMAGELIST *phImageList
275 );
276 +static HRESULT OnLoadingControl(
277 + __in THEME* pTheme,
278 + __in const THEME_CONTROL* pControl,
279 + __inout WORD* pwId
280 + );
281 static HRESULT LoadControls(
282 __in THEME* pTheme,
277 - __in_opt THEME_CONTROL* pParentControl,
278 - __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
279 - __in DWORD cAssignControlIds
283 + __in_opt THEME_CONTROL* pParentControl
284 );
285 static HRESULT ShowControl(
286 __in THEME* pTheme,
@@ -871,9 +875,7 @@ LExit:
875
876
877 DAPI_(HRESULT) ThemeLoadControls(
874 - __in THEME* pTheme,
875 - __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
876 - __in DWORD cAssignControlIds
878 + __in THEME* pTheme
879 )
880 {
881 HRESULT hr = S_OK;
@@ -883,7 +885,7 @@ DAPI_(HRESULT) ThemeLoadControls(
885 ThmExitOnFailure(hr = E_INVALIDSTATE, "ThemeLoadControls called before theme parent window created.");
886 }
887
886 - hr = LoadControls(pTheme, NULL, rgAssignControlIds, cAssignControlIds);
888 + hr = LoadControls(pTheme, NULL);
889
890 LExit:
891 return hr;
@@ -1844,8 +1846,6 @@ static HRESULT ParseTheme(
1846 __out THEME** ppTheme
1847 )
1848 {
1847 - static WORD wThemeId = 0;
1848 -
1849 HRESULT hr = S_OK;
1850 THEME* pTheme = NULL;
1851 IXMLDOMElement *pThemeElement = NULL;
@@ -1858,8 +1858,8 @@ static HRESULT ParseTheme(
1858 pTheme = static_cast<THEME*>(MemAlloc(sizeof(THEME), TRUE));
1859 ThmExitOnNull(pTheme, hr, E_OUTOFMEMORY, "Failed to allocate memory for theme.");
1860
1861 - pTheme->wId = ++wThemeId;
1861 pTheme->nDpi = USER_DEFAULT_SCREEN_DPI;
1862 + pTheme->wNextControlId = THEME_FIRST_AUTO_ASSIGN_CONTROL_ID;
1863
1864 // Parse the optional background resource image.
1865 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pThemeElement, &pBitmap);
@@ -5248,7 +5248,7 @@ static BOOL OnButtonClicked(
5248 LExit:
5249 return fHandled;
5250 }
5251 -
5251 +
5252 static BOOL OnDpiChanged(
5253 __in THEME* pTheme,
5254 __in WPARAM wParam,
@@ -5934,11 +5934,38 @@ static LRESULT CALLBACK StaticOwnerDrawWndProc(
5934 }
5935 }
5936
5937 +static HRESULT OnLoadingControl(
5938 + __in THEME* pTheme,
5939 + __in const THEME_CONTROL* pControl,
5940 + __inout WORD* pwId
5941 + )
5942 +{
5943 + HRESULT hr = S_OK;
5944 + THEME_LOADINGCONTROL_ARGS loadingControlArgs = { };
5945 + THEME_LOADINGCONTROL_RESULTS loadingControlResults = { };
5946 +
5947 + loadingControlArgs.cbSize = sizeof(loadingControlArgs);
5948 + loadingControlArgs.pThemeControl = pControl;
5949 +
5950 + loadingControlResults.cbSize = sizeof(loadingControlResults);
5951 + loadingControlResults.hr = E_NOTIMPL;
5952 + loadingControlResults.wId = *pwId;
5953 +
5954 + if (::SendMessageW(pTheme->hwndParent, WM_THMUTIL_LOADING_CONTROL, reinterpret_cast<WPARAM>(&loadingControlArgs), reinterpret_cast<LPARAM>(&loadingControlResults)))
5955 + {
5956 + hr = loadingControlResults.hr;
5957 + if (SUCCEEDED(hr))
5958 + {
5959 + *pwId = loadingControlResults.wId;
5960 + }
5961 + }
5962 +
5963 + return hr;
5964 +}
5965 +
5966 static HRESULT LoadControls(
5967 __in THEME* pTheme,
5939 - __in_opt THEME_CONTROL* pParentControl,
5940 - __in_ecount_opt(cAssignControlIds) const THEME_ASSIGN_CONTROL_ID* rgAssignControlIds,
5941 - __in DWORD cAssignControlIds
5968 + __in_opt THEME_CONTROL* pParentControl
5969 )
5970 {
5971 HRESULT hr = S_OK;
@@ -6101,16 +6128,16 @@ static HRESULT LoadControls(
6128 }
6129 ThmExitOnNull(wzWindowClass, hr, E_INVALIDDATA, "Failed to configure control %u because of unknown type: %u", i, pControl->type);
6130
6104 - // Default control ids to the theme id and its index in the control array, unless there
6105 - // is a specific id to assign to a named control.
6106 - WORD wControlId = MAKEWORD(i, pTheme->wId);
6107 - for (DWORD iAssignControl = 0; pControl->sczName && iAssignControl < cAssignControlIds; ++iAssignControl)
6131 + // Default control ids to the next id, unless there is a specific id to assign to a control.
6132 + WORD wControlId = THEME_FIRST_AUTO_ASSIGN_CONTROL_ID;
6133 + hr = OnLoadingControl(pTheme, pControl, &wControlId);
6134 + ThmExitOnFailure(hr, "ThmLoadingControl failed.");
6135 +
6136 + // This range is reserved for thmutil. The process will run out of available window handles before reaching the end of the range.
6137 + if (THEME_FIRST_AUTO_ASSIGN_CONTROL_ID <= wControlId && THEME_FIRST_ASSIGN_CONTROL_ID > wControlId)
6138 {
6109 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pControl->sczName, -1, rgAssignControlIds[iAssignControl].wzName, -1))
6110 - {
6111 - wControlId = rgAssignControlIds[iAssignControl].wId;
6112 - break;
6113 - }
6139 + wControlId = pTheme->wNextControlId;
6140 + pTheme->wNextControlId += 1;
6141 }
6142
6143 pControl->wId = wControlId;
@@ -6296,7 +6323,7 @@ static HRESULT LoadControls(
6323
6324 if (pControl->cControls)
6325 {
6299 - hr = LoadControls(pTheme, pControl, rgAssignControlIds, cAssignControlIds);
6326 + hr = LoadControls(pTheme, pControl);
6327 ThmExitOnFailure(hr, "Failed to load child controls.");
6328 }
6329 }
src/samples/thmviewer/display.cpp
+1 -1
@@ -329,7 +329,7 @@ static BOOL DisplayOnCreate(
329 {
330 HRESULT hr = S_OK;
331
332 - hr = ThemeLoadControls(pTheme, NULL, 0);
332 + hr = ThemeLoadControls(pTheme);
333 ExitOnFailure(hr, "Failed to load theme controls");
334
335 // Pre-populate some control types with data.
src/samples/thmviewer/thmviewer.cpp
+22 -5
@@ -14,10 +14,6 @@ enum THMVWR_CONTROL
14 THMVWR_CONTROL_TREE = THEME_FIRST_ASSIGN_CONTROL_ID,
15 };
16
17 -static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
18 - { THMVWR_CONTROL_TREE, L"Tree" },
19 -};
20 -
17 // Internal functions
18
19 static HRESULT ProcessCommandLine(
@@ -52,6 +48,10 @@ static void OnNewTheme(
48 __in HWND hWnd,
49 __in HANDLE_THEME* pHandle
50 );
51 +static BOOL OnThemeLoadingControl(
52 + __in const THEME_LOADINGCONTROL_ARGS* pArgs,
53 + __in THEME_LOADINGCONTROL_RESULTS* pResults
54 + );
55 static void CALLBACK ThmviewerTraceError(
56 __in_z LPCSTR szFile,
57 __in int iLine,
@@ -353,7 +353,7 @@ static LRESULT CALLBACK MainWndProc(
353
354 case WM_CREATE:
355 {
356 - HRESULT hr = ThemeLoadControls(vpTheme, vrgInitControls, countof(vrgInitControls));
356 + HRESULT hr = ThemeLoadControls(vpTheme);
357 if (FAILED(hr))
358 {
359 return -1;
@@ -400,6 +400,9 @@ static LRESULT CALLBACK MainWndProc(
400 }
401 }
402 break;
403 +
404 + case WM_THMUTIL_LOADING_CONTROL:
405 + return OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
406 }
407
408 return ThemeDefWindowProc(vpTheme, hWnd, uMsg, wParam, lParam);
@@ -541,3 +544,17 @@ static void OnNewTheme(
544 ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_SELECTITEM, TVGN_CARET, reinterpret_cast<LPARAM>(htiSelected));
545 }
546 }
547 +
548 +static BOOL OnThemeLoadingControl(
549 + __in const THEME_LOADINGCONTROL_ARGS* pArgs,
550 + __in THEME_LOADINGCONTROL_RESULTS* pResults
551 + )
552 +{
553 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, L"Tree", -1))
554 + {
555 + pResults->wId = THMVWR_CONTROL_TREE;
556 + }
557 +
558 + pResults->hr = S_OK;
559 + return TRUE;
560 +}
src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
+51 -8
@@ -6,6 +6,11 @@
6
7 static const LPCWSTR BAFTHMUTILTESTING_WINDOW_CLASS = L"BafThmUtilTesting";
8
9 +enum BAF_CONTROL
10 +{
11 + BAF_CONTROL_INSTALL_TEST_BUTTON = BAFUNCTIONS_FIRST_ASSIGN_CONTROL_ID,
12 +};
13 +
14 enum BAFTHMUTILTESTING_CONTROL
15 {
16 BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT = THEME_FIRST_ASSIGN_CONTROL_ID,
@@ -59,24 +64,41 @@ public: // IBAFunctions
64 __inout LRESULT* plRes
65 )
66 {
62 - HRESULT hr = S_OK;
63 -
64 - __super::WndProc(pTheme, hWnd, uMsg, wParam, lParam, plRes);
65 -
66 - // Show our window when any button is clicked.
67 switch (uMsg)
68 {
69 case WM_COMMAND:
70 switch (HIWORD(wParam))
71 {
72 case BN_CLICKED:
73 - OnShowTheme();
73 + switch (LOWORD(wParam))
74 + {
75 + case BAF_CONTROL_INSTALL_TEST_BUTTON:
76 + OnShowTheme();
77 + *plRes = 0;
78 + return S_OK;
79 + }
80 +
81 break;
82 }
83 break;
84 }
85
79 - return hr;
86 + return __super::WndProc(pTheme, hWnd, uMsg, wParam, lParam, plRes);
87 + }
88 +
89 + virtual STDMETHODIMP OnThemeControlLoading(
90 + __in LPCWSTR wzName,
91 + __inout BOOL* pfProcessed,
92 + __inout WORD* pwId
93 + )
94 + {
95 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzName, -1, L"InstallTestButton", -1))
96 + {
97 + *pfProcessed = TRUE;
98 + *pwId = BAF_CONTROL_INSTALL_TEST_BUTTON;
99 + }
100 +
101 + return S_OK;
102 }
103
104 private:
@@ -229,6 +251,9 @@ private:
251 }
252 break;
253
254 + case WM_THMUTIL_LOADING_CONTROL:
255 + return pBaf->OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
256 +
257 case WM_TIMER:
258 if (!lParam && pBaf)
259 {
@@ -255,7 +280,7 @@ private:
280 HWND hwndBottomLeft = NULL;
281 HWND hwndBottomRight = NULL;
282
258 - hr = ThemeLoadControls(m_pBafTheme, vrgInitControls, countof(vrgInitControls));
283 + hr = ThemeLoadControls(m_pBafTheme);
284 BalExitOnFailure(hr, "Failed to load theme controls.");
285
286 hwndTopLeft = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT);
@@ -333,6 +358,24 @@ private:
358 return SUCCEEDED(hr);
359 }
360
361 + BOOL OnThemeLoadingControl(
362 + __in const THEME_LOADINGCONTROL_ARGS* pArgs,
363 + __in THEME_LOADINGCONTROL_RESULTS* pResults
364 + )
365 + {
366 + for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
367 + {
368 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
369 + {
370 + pResults->wId = vrgInitControls[iAssignControl].wId;
371 + break;
372 + }
373 + }
374 +
375 + pResults->hr = S_OK;
376 + return TRUE;
377 + }
378 +
379 void UpdateProgressBarProgress()
380 {
381 static DWORD dwProgress = 0;
src/test/burn/TestData/Manual/BundleA/BundleA.wixproj
+1 -1
@@ -2,7 +2,7 @@
2 <Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <OutputType>Bundle</OutputType>
5 - <BA>hyperlinkLicense</BA>
5 + <BA>customHyperlinkLicense</BA>
6 <UpgradeCode>{98ACBCF6-B54A-46AF-8990-DFB8795B965B}</UpgradeCode>
7 </PropertyGroup>
8 <ItemGroup>
src/test/burn/TestData/Manual/BundleA/BundleA.wxs
+2 -1
@@ -3,7 +3,8 @@
3
4 <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
5 <Fragment>
6 - <BootstrapperApplication>
6 + <BootstrapperApplication Id="customHyperlinkLicense">
7 + <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" ThemeFile="CustomHyperlinkTheme.xml" />
8 <Payload SourceFile="$(var.BafThmUtilTesting.TargetPath)" bal:BAFunctions="yes" />
9 </BootstrapperApplication>
10 <PackageGroup Id="BundlePackages">
src/test/burn/TestData/Manual/BundleA/CustomHyperlinkTheme.xml new
+107
@@ -0,0 +1,107 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 +
4 +
5 +<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
6 + <Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
7 + <Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
8 + <Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
9 + <Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
10 +
11 + <Window Width="485" Height="300" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)">
12 + <ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" Visible="yes"/>
13 + <Label X="80" Y="11" Width="-11" Height="64" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Label>
14 +
15 + <Page Name="Help">
16 + <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
17 + <Label X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
18 + <Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
19 + <Text>#(loc.HelpCloseButton)</Text>
20 + <CloseWindowAction />
21 + </Button>
22 + </Page>
23 + <Page Name="Install">
24 + <Hypertext Name="EulaHyperlink" X="11" Y="121" Width="-11" Height="51" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallLicenseLinkText)</Hypertext>
25 + <Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="260" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
26 + <Button Name="InstallTestButton" X="-251" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">Test</Button>
27 + <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" VisibleCondition="NOT WixStdBASuppressOptionsUI">
28 + <Text>#(loc.InstallOptionsButton)</Text>
29 + <ChangePageAction Page="Options" />
30 + </Button>
31 + <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
32 + <Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
33 + <Text>#(loc.InstallCancelButton)</Text>
34 + <CloseWindowAction />
35 + </Button>
36 + </Page>
37 + <Page Name="Options">
38 + <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Label>
39 + <Label X="11" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Label>
40 + <Editbox Name="InstallFolder" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
41 + <Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">
42 + <Text>#(loc.OptionsBrowseButton)</Text>
43 + <BrowseDirectoryAction VariableName="InstallFolder" />
44 + </Button>
45 + <Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
46 + <Text>#(loc.OptionsOkButton)</Text>
47 + <ChangePageAction Page="Install" />
48 + </Button>
49 + <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
50 + <Text>#(loc.OptionsCancelButton)</Text>
51 + <ChangePageAction Page="Install" Cancel="yes" />
52 + </Button>
53 + </Page>
54 + <Page Name="Progress">
55 + <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
56 + <Label X="11" Y="121" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
57 + <Label Name="OverallProgressPackageText" X="85" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Label>
58 + <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="143" Width="-11" Height="15" />
59 + <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
60 + </Page>
61 + <Page Name="Modify">
62 + <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Label>
63 + <Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
64 + <Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
65 + <Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
66 + <Text>#(loc.ModifyCancelButton)</Text>
67 + <CloseWindowAction />
68 + </Button>
69 + </Page>
70 + <Page Name="Success">
71 + <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">
72 + <Text>#(loc.SuccessHeader)</Text>
73 + <Text Condition="WixBundleAction = 2">#(loc.SuccessLayoutHeader)</Text>
74 + <Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallHeader)</Text>
75 + <Text Condition="WixBundleAction = 5">#(loc.SuccessInstallHeader)</Text>
76 + <Text Condition="WixBundleAction = 7">#(loc.SuccessRepairHeader)</Text>
77 + </Label>
78 + <Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
79 + <Label X="-11" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">
80 + <Text>#(loc.SuccessRestartText)</Text>
81 + <Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallRestartText)</Text>
82 + </Label>
83 + <Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
84 + <Button Name="SuccessCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
85 + <Text>#(loc.SuccessCloseButton)</Text>
86 + <CloseWindowAction />
87 + </Button>
88 + </Page>
89 + <Page Name="Failure">
90 + <Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">
91 + <Text>#(loc.FailureHeader)</Text>
92 + <Text Condition="WixBundleAction = 2">#(loc.FailureLayoutHeader)</Text>
93 + <Text Condition="WixBundleAction = 3">#(loc.FailureUninstallHeader)</Text>
94 + <Text Condition="WixBundleAction = 5">#(loc.FailureInstallHeader)</Text>
95 + <Text Condition="WixBundleAction = 7">#(loc.FailureRepairHeader)</Text>
96 + </Label>
97 + <Hypertext Name="FailureLogFileLink" X="11" Y="121" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
98 + <Hypertext Name="FailureMessageText" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
99 + <Label X="-11" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
100 + <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
101 + <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
102 + <Text>#(loc.FailureCloseButton)</Text>
103 + <CloseWindowAction />
104 + </Button>
105 + </Page>
106 + </Window>
107 +</Theme>