@joebigelow / wix / commits / dce1c97c

Make thmutil automatically load controls during window creation.

Add control loaded event.

Sean Hall committed Oct 27, 2021 at 15:29 UTC dce1c97c7d3e76c18e4f80d4ffe288d2933a74bc
14 files changed +542 -231
src/api/burn/balutil/inc/BAFunctions.h
+15
@@ -88,6 +88,7 @@ enum BA_FUNCTIONS_MESSAGE
88 BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING,
89 BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMCOMMAND,
90 BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMNOTIFY,
91 + BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADED,
92 };
93
94 typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)(
@@ -115,6 +116,20 @@ struct BA_FUNCTIONS_CREATE_RESULTS
116 LPVOID pvBAFunctionsProcContext;
117 };
118
119 +struct BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS
120 +{
121 + DWORD cbSize;
122 + LPCWSTR wzName;
123 + WORD wId;
124 + HWND hWnd;
125 +};
126 +
127 +struct BA_FUNCTIONS_ONTHEMECONTROLLOADED_RESULTS
128 +{
129 + DWORD cbSize;
130 + BOOL fProcessed;
131 +};
132 +
133 struct BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS
134 {
135 DWORD cbSize;
src/api/burn/balutil/inc/BalBaseBAFunctions.h
+10
@@ -874,6 +874,16 @@ public: // IBAFunctions
874 return S_OK;
875 }
876
877 + virtual STDMETHODIMP OnThemeControlLoaded(
878 + __in LPCWSTR /*wzName*/,
879 + __in WORD /*wId*/,
880 + __in HWND /*hWnd*/,
881 + __inout BOOL* /*pfProcessed*/
882 + )
883 + {
884 + return S_OK;
885 + }
886 +
887 protected:
888 CBalBaseBAFunctions(
889 __in HMODULE hModule,
src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+12
@@ -51,6 +51,15 @@ static HRESULT BalBaseBAFunctionsProcOnThemeControlWmNotify(
51 return pBAFunctions->OnThemeControlWmNotify(pArgs->lParam, pArgs->wzName, pArgs->wId, pArgs->hWnd, &pResults->fProcessed, &pResults->lResult);
52 }
53
54 +static HRESULT BalBaseBAFunctionsProcOnThemeControlLoaded(
55 + __in IBAFunctions* pBAFunctions,
56 + __in BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS* pArgs,
57 + __inout BA_FUNCTIONS_ONTHEMECONTROLLOADED_RESULTS* pResults
58 + )
59 +{
60 + return pBAFunctions->OnThemeControlLoaded(pArgs->wzName, pArgs->wId, pArgs->hWnd, &pResults->fProcessed);
61 +}
62 +
63 /*******************************************************************
64 BalBaseBAFunctionsProc - requires pvContext to be of type IBAFunctions.
65 Provides a default mapping between the message based BAFunctions interface and
@@ -161,6 +170,9 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
170 case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMNOTIFY:
171 hr = BalBaseBAFunctionsProcOnThemeControlWmNotify(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_RESULTS*>(pvResults));
172 break;
173 + case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADED:
174 + hr = BalBaseBAFunctionsProcOnThemeControlLoaded(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADED_RESULTS*>(pvResults));
175 + break;
176 }
177 }
178
src/api/burn/balutil/inc/IBAFunctions.h
+9
@@ -61,4 +61,13 @@ DECLARE_INTERFACE_IID_(IBAFunctions, IBootstrapperApplication, "0FB445ED-17BD-49
61 __inout BOOL* pfProcessed,
62 __inout LRESULT* plResult
63 ) = 0;
64 +
65 + // OnThemeControlLoaded - Called after a control was created for the theme.
66 + //
67 + STDMETHOD(OnThemeControlLoaded)(
68 + __in LPCWSTR wzName,
69 + __in WORD wId,
70 + __in HWND hWnd,
71 + __inout BOOL* pfProcessed
72 + ) = 0;
73 };
src/api/burn/balutil/inc/balutil.h
+2
@@ -11,6 +11,7 @@ extern "C" {
11
12 #define BalExitOnFailureSource(d, x, f, ...) if (FAILED(x)) { BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
13 #define BalExitOnRootFailureSource(d, x, f, ...) if (FAILED(x)) { BalLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
14 +#define BalExitWithRootFailureSource(d, x, e, f, ...) { x = FAILED(e) ? e : E_FAIL; BalLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
15 #define BalExitOnLastErrorSource(d, x, f, ...) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } }
16 #define BalExitOnNullSource(d, p, x, e, f, ...) if (NULL == p) { x = e; BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
17 #define BalExitOnNullWithLastErrorSource(d, p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
@@ -18,6 +19,7 @@ extern "C" {
19
20 #define BalExitOnFailure(x, f, ...) BalExitOnFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
21 #define BalExitOnRootFailure(x, f, ...) BalExitOnRootFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
22 +#define BalExitWithRootFailure(x, e, f, ...) BalExitWithRootFailureSource(DUTIL_SOURCE_DEFAULT, x, e, f, __VA_ARGS__)
23 #define BalExitOnLastError(x, f, ...) BalExitOnLastErrorSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
24 #define BalExitOnNull(p, x, e, f, ...) BalExitOnNullSource(DUTIL_SOURCE_DEFAULT, p, x, e, f, __VA_ARGS__)
25 #define BalExitOnNullWithLastError(p, x, f, ...) BalExitOnNullWithLastErrorSource(DUTIL_SOURCE_DEFAULT, p, x, f, __VA_ARGS__)
src/api/burn/bextutil/inc/bextutil.h
+2
@@ -11,6 +11,7 @@ extern "C" {
11
12 #define BextExitOnFailureSource(d, x, f, ...) if (FAILED(x)) { BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
13 #define BextExitOnRootFailureSource(d, x, f, ...) if (FAILED(x)) { BextLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
14 +#define BextExitWithRootFailureSource(d, x, e, f, ...) { x = FAILED(e) ? e : E_FAIL; BextLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
15 #define BextExitOnLastErrorSource(d, x, f, ...) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } }
16 #define BextExitOnNullSource(d, p, x, e, f, ...) if (NULL == p) { x = e; BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
17 #define BextExitOnNullWithLastErrorSource(d, p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
@@ -18,6 +19,7 @@ extern "C" {
19
20 #define BextExitOnFailure(x, f, ...) BextExitOnFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
21 #define BextExitOnRootFailure(x, f, ...) BextExitOnRootFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
22 +#define BextExitWithRootFailure(x, e, f, ...) BextExitWithRootFailureSource(DUTIL_SOURCE_DEFAULT, x, e, f, __VA_ARGS__)
23 #define BextExitOnLastError(x, f, ...) BextExitOnLastErrorSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
24 #define BextExitOnNull(p, x, e, f, ...) BextExitOnNullSource(DUTIL_SOURCE_DEFAULT, p, x, e, f, __VA_ARGS__)
25 #define BextExitOnNullWithLastError(p, x, f, ...) BextExitOnNullWithLastErrorSource(DUTIL_SOURCE_DEFAULT, p, x, f, __VA_ARGS__)
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+114 -74
@@ -2389,6 +2389,11 @@ private:
2389 hr = ThemeRegisterVariableCallbacks(m_pTheme, EvaluateVariableConditionCallback, FormatVariableStringCallback, GetVariableNumericCallback, SetVariableNumericCallback, GetVariableStringCallback, SetVariableStringCallback, NULL);
2390 BalExitOnFailure(hr, "Failed to register variable theme callbacks.");
2391
2392 + C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames));
2393 + C_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames));
2394 +
2395 + ThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds));
2396 +
2397 hr = ThemeLocalize(m_pTheme, m_pWixLoc);
2398 BalExitOnFailure(hr, "Failed to localize theme: %ls", sczThemePath);
2399
@@ -2697,6 +2702,8 @@ private:
2702 hr = ThemeCreateParentWindow(m_pTheme, 0, wc.lpszClassName, m_pTheme->sczCaption, dwWindowStyle, x, y, HWND_DESKTOP, m_hModule, this, THEME_WINDOW_INITIAL_POSITION_CENTER_MONITOR_FROM_COORDINATES, &m_hWnd);
2703 ExitOnFailure(hr, "Failed to create window.");
2704
2705 + OnThemeLoaded();
2706 +
2707 hr = S_OK;
2708
2709 LExit:
@@ -2831,16 +2838,12 @@ private:
2838 return lres;
2839 }
2840
2834 - case WM_CREATE:
2835 - if (!pBA->OnCreate(hWnd))
2836 - {
2837 - return -1;
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_THMUTIL_LOADED_CONTROL:
2845 + return pBA->OnThemeLoadedControl(reinterpret_cast<THEME_LOADEDCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADEDCONTROL_RESULTS*>(lParam));
2846 +
2847 case WM_QUERYENDSESSION:
2848 fCancel = true;
2849 pBA->OnSystemShutdown(static_cast<DWORD>(lParam), &fCancel);
@@ -2896,74 +2899,14 @@ private:
2899
2900
2901 //
2899 - // OnCreate - finishes loading the theme.
2902 + // OnThemeLoaded - finishes loading the theme.
2903 //
2901 - BOOL OnCreate(
2902 - __in HWND /*hWnd*/
2903 - )
2904 + BOOL OnThemeLoaded()
2905 {
2906 HRESULT hr = S_OK;
2906 - LPWSTR sczLicenseFormatted = NULL;
2907 - LPWSTR sczLicensePath = NULL;
2908 - LPWSTR sczLicenseDirectory = NULL;
2909 - LPWSTR sczLicenseFilename = NULL;
2907 BA_FUNCTIONS_ONTHEMELOADED_ARGS themeLoadedArgs = { };
2908 BA_FUNCTIONS_ONTHEMELOADED_RESULTS themeLoadedResults = { };
2909
2913 - hr = ThemeLoadControls(m_pTheme);
2914 - BalExitOnFailure(hr, "Failed to load theme controls.");
2915 -
2916 - C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames));
2917 - C_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames));
2918 -
2919 - ThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds));
2920 -
2921 - // Load the RTF EULA control with text if the control exists.
2922 - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT))
2923 - {
2924 - hr = (m_sczLicenseFile && *m_sczLicenseFile) ? S_OK : E_INVALIDDATA;
2925 - if (SUCCEEDED(hr))
2926 - {
2927 - hr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0);
2928 - if (SUCCEEDED(hr))
2929 - {
2930 - hr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted);
2931 - if (SUCCEEDED(hr))
2932 - {
2933 - // Assume there is no hidden variables to be formatted
2934 - // so don't worry about securely freeing it.
2935 - hr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted);
2936 - if (SUCCEEDED(hr))
2937 - {
2938 - hr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule);
2939 - if (SUCCEEDED(hr))
2940 - {
2941 - hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory);
2942 - if (SUCCEEDED(hr))
2943 - {
2944 - hr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0);
2945 - if (SUCCEEDED(hr))
2946 - {
2947 - hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath);
2948 - if (SUCCEEDED(hr))
2949 - {
2950 - hr = ThemeLoadRichEditFromFile(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT, sczLicensePath, m_hModule);
2951 - }
2952 - }
2953 - }
2954 - }
2955 - }
2956 - }
2957 - }
2958 - }
2959 -
2960 - if (FAILED(hr))
2961 - {
2962 - BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load file into license richedit control from path '%ls' manifest value: %ls", sczLicensePath, m_sczLicenseFile);
2963 - hr = S_OK;
2964 - }
2965 - }
2966 -
2910 if (m_pfnBAFunctionsProc)
2911 {
2912 themeLoadedArgs.cbSize = sizeof(themeLoadedArgs);
@@ -2975,11 +2918,6 @@ private:
2918 }
2919
2920 LExit:
2978 - ReleaseStr(sczLicenseFilename);
2979 - ReleaseStr(sczLicenseDirectory);
2980 - ReleaseStr(sczLicensePath);
2981 - ReleaseStr(sczLicenseFormatted);
2982 -
2921 return SUCCEEDED(hr);
2922 }
2923
@@ -3034,6 +2972,108 @@ private:
2972 return fProcessed || FAILED(hr);
2973 }
2974
2975 + BOOL OnThemeLoadedControl(
2976 + __in const THEME_LOADEDCONTROL_ARGS* pArgs,
2977 + __in THEME_LOADEDCONTROL_RESULTS* pResults
2978 + )
2979 + {
2980 + HRESULT hr = S_OK;
2981 + BOOL fProcessed = FALSE;
2982 + BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS themeControlLoadedArgs = { };
2983 + BA_FUNCTIONS_ONTHEMECONTROLLOADED_RESULTS themeControlLoadedResults = { };
2984 +
2985 + if (WIXSTDBA_CONTROL_EULA_RICHEDIT == pArgs->pThemeControl->wId)
2986 + {
2987 + // Best effort to load the RTF EULA control with text.
2988 + OnLoadedEulaRtfControl(pArgs->pThemeControl);
2989 + fProcessed = TRUE;
2990 + ExitFunction();
2991 + }
2992 +
2993 + if (m_pfnBAFunctionsProc)
2994 + {
2995 + themeControlLoadedArgs.cbSize = sizeof(themeControlLoadedArgs);
2996 + themeControlLoadedArgs.wzName = pArgs->pThemeControl->sczName;
2997 + themeControlLoadedArgs.wId = pArgs->pThemeControl->wId;
2998 + themeControlLoadedArgs.hWnd = pArgs->pThemeControl->hWnd;
2999 +
3000 + themeControlLoadedResults.cbSize = sizeof(themeControlLoadedResults);
3001 +
3002 + hr = m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADED, &themeControlLoadedArgs, &themeControlLoadedResults, m_pvBAFunctionsProcContext);
3003 +
3004 + if (E_NOTIMPL == hr)
3005 + {
3006 + hr = S_OK;
3007 + }
3008 + else
3009 + {
3010 + BalExitOnFailure(hr, "BAFunctions OnThemeControlLoaded failed.");
3011 +
3012 + if (themeControlLoadedResults.fProcessed)
3013 + {
3014 + fProcessed = TRUE;
3015 + }
3016 + }
3017 + }
3018 +
3019 + LExit:
3020 + pResults->hr = hr;
3021 + return fProcessed || FAILED(hr);
3022 + }
3023 +
3024 + HRESULT OnLoadedEulaRtfControl(
3025 + const THEME_CONTROL* pThemeControl
3026 + )
3027 + {
3028 + HRESULT hr = S_OK;
3029 + LPWSTR sczLicenseFormatted = NULL;
3030 + LPWSTR sczLicensePath = NULL;
3031 + LPWSTR sczLicenseDirectory = NULL;
3032 + LPWSTR sczLicenseFilename = NULL;
3033 +
3034 + if (!m_sczLicenseFile || !*m_sczLicenseFile)
3035 + {
3036 + ExitWithRootFailure(hr, E_INVALIDDATA, "No license file in manifest.");
3037 + }
3038 +
3039 + hr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0);
3040 + ExitOnFailure(hr, "Failed to copy manifest license file.");
3041 +
3042 + hr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted);
3043 + ExitOnFailure(hr, "Failed to localize manifest license file.");
3044 +
3045 + hr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted);
3046 + ExitOnFailure(hr, "Failed to expand localized manifest license file.");
3047 +
3048 + hr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule);
3049 + ExitOnFailure(hr, "Failed to get relative path for license file.");
3050 +
3051 + hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory);
3052 + ExitOnFailure(hr, "Failed to get license file directory.");
3053 +
3054 + hr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0);
3055 + ExitOnFailure(hr, "Failed to copy license file name.");
3056 +
3057 + hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath);
3058 + ExitOnFailure(hr, "Failed to probe for localized license file.");
3059 +
3060 + hr = ThemeLoadRichEditFromFile(m_pTheme, pThemeControl->wId, sczLicensePath, m_hModule);
3061 + ExitOnFailure(hr, "Failed to load license file into richedit control.");
3062 +
3063 + LExit:
3064 + if (FAILED(hr))
3065 + {
3066 + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load file into license richedit control from path '%ls' manifest value: %ls", sczLicensePath, m_sczLicenseFile);
3067 + }
3068 +
3069 + ReleaseStr(sczLicenseFilename);
3070 + ReleaseStr(sczLicenseDirectory);
3071 + ReleaseStr(sczLicensePath);
3072 + ReleaseStr(sczLicenseFormatted);
3073 +
3074 + return hr;
3075 + }
3076 +
3077
3078 //
3079 // OnShowFailure - display the failure page.
src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+23 -20
@@ -6,6 +6,10 @@
6 extern "C" {
7 #endif
8
9 +// forward declare
10 +
11 +typedef struct _THEME THEME;
12 +
13 #define ReleaseTheme(p) if (p) { ThemeFree(p); p = NULL; }
14
15 typedef HRESULT(CALLBACK *PFNTHM_EVALUATE_VARIABLE_CONDITION)(
@@ -111,6 +115,10 @@ typedef enum _WM_THMUTIL
115 // wparam is THEME_CONTROLWMNOTIFY_ARGS* and lparam is THEME_CONTROLWMNOTIFY_RESULTS*.
116 // Return code is TRUE to prevent further processing of the message.
117 WM_THMUTIL_CONTROL_WM_NOTIFY = WM_APP - 3,
118 + // Sent after created a control.
119 + // wparam is THEME_LOADEDCONTROL_ARGS* and lparam is THEME_LOADEDCONTROL_RESULTS*.
120 + // Return code is TRUE if it was processed.
121 + WM_THMUTIL_LOADED_CONTROL = WM_APP - 4,
122 } WM_THMUTIL;
123
124 struct THEME_COLUMN
@@ -287,6 +295,7 @@ struct THEME_CONTROL
295 // state variables that should be ignored
296 HWND hWnd;
297 DWORD dwData; // type specific data
298 + THEME* pTheme;
299 };
300
301
@@ -340,7 +349,7 @@ struct THEME_FONT
349 };
350
351
343 -struct THEME
352 +typedef struct _THEME
353 {
354 WORD wNextControlId;
355
@@ -403,7 +412,7 @@ struct THEME
412 PFNTHM_SET_VARIABLE_STRING pfnSetStringVariable;
413
414 LPVOID pvVariableContext;
406 -};
415 +} THEME;
416
417 typedef struct _THEME_CONTROLWMCOMMAND_ARGS
418 {
@@ -431,6 +440,18 @@ typedef struct _THEME_CONTROLWMNOTIFY_RESULTS
440 LRESULT lResult;
441 } THEME_CONTROLWMNOTIFY_RESULTS;
442
443 +typedef struct _THEME_LOADEDCONTROL_ARGS
444 +{
445 + DWORD cbSize;
446 + const THEME_CONTROL* pThemeControl;
447 +} THEME_LOADEDCONTROL_ARGS;
448 +
449 +typedef struct _THEME_LOADEDCONTROL_RESULTS
450 +{
451 + DWORD cbSize;
452 + HRESULT hr;
453 +} THEME_LOADEDCONTROL_RESULTS;
454 +
455 typedef struct _THEME_LOADINGCONTROL_ARGS
456 {
457 DWORD cbSize;
@@ -527,24 +548,6 @@ HRESULT DAPI ThemeCreateParentWindow(
548 __out_opt HWND* phWnd
549 );
550
530 -/********************************************************************
531 - ThemeLoadControls - creates the windows for all the theme controls
532 - using the window created in ThemeCreateParentWindow.
533 -
534 -*******************************************************************/
535 -HRESULT DAPI ThemeLoadControls(
536 - __in THEME* pTheme
537 - );
538 -
539 -/********************************************************************
540 - ThemeUnloadControls - resets all the theme control windows so the theme
541 - controls can be reloaded.
542 -
543 -*******************************************************************/
544 -void DAPI ThemeUnloadControls(
545 - __in THEME* pTheme
546 - );
547 -
551 /********************************************************************
552 ThemeLocalize - Localizes all of the strings in the theme.
553
src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+95 -42
@@ -205,6 +205,7 @@ static HRESULT ParseControl(
205 __in_opt THEME_PAGE* pPage
206 );
207 static void InitializeThemeControl(
208 + THEME* pTheme,
209 THEME_CONTROL* pControl
210 );
211 static HRESULT ParseActions(
@@ -273,6 +274,12 @@ static HRESULT FindImageList(
274 __in_z LPCWSTR wzImageListName,
275 __out HIMAGELIST *phImageList
276 );
277 +static HRESULT LoadThemeControls(
278 + __in THEME* pTheme
279 + );
280 +static void UnloadThemeControls(
281 + __in THEME* pTheme
282 + );
283 static HRESULT OnLoadingControl(
284 __in THEME* pTheme,
285 __in const THEME_CONTROL* pControl,
@@ -452,6 +459,10 @@ static BOOL OnNotifyEnMsgFilter(
459 __in const THEME_CONTROL* pThemeControl,
460 __in MSGFILTER* msgFilter
461 );
462 +static BOOL OnPanelCreate(
463 + __in THEME_CONTROL* pControl,
464 + __in HWND hWnd
465 + );
466 static BOOL OnWmCommand(
467 __in THEME* pTheme,
468 __in WPARAM wParam,
@@ -888,35 +899,6 @@ LExit:
899 return hr;
900 }
901
891 -
892 -DAPI_(HRESULT) ThemeLoadControls(
893 - __in THEME* pTheme
894 - )
895 -{
896 - HRESULT hr = S_OK;
897 -
898 - if (!pTheme->hwndParent)
899 - {
900 - ThmExitOnFailure(hr = E_INVALIDSTATE, "ThemeLoadControls called before theme parent window created.");
901 - }
902 -
903 - hr = LoadControls(pTheme, NULL);
904 -
905 -LExit:
906 - return hr;
907 -}
908 -
909 -
910 -DAPI_(void) ThemeUnloadControls(
911 - __in THEME* pTheme
912 - )
913 -{
914 - UnloadControls(pTheme->cControls, pTheme->rgControls);
915 -
916 - pTheme->hwndHover = NULL;
917 - pTheme->hwndParent = NULL;
918 -}
919 -
902 DAPI_(HRESULT) ThemeLocalize(
903 __in THEME *pTheme,
904 __in const WIX_LOCALIZATION *pWixLoc
@@ -1089,6 +1071,17 @@ extern "C" LRESULT CALLBACK ThemeDefWindowProc(
1071 }
1072 break;
1073
1074 + case WM_CREATE:
1075 + if (FAILED(LoadThemeControls(pTheme)))
1076 + {
1077 + return -1;
1078 + }
1079 + break;
1080 +
1081 + case WM_DESTROY:
1082 + UnloadThemeControls(pTheme);
1083 + break;
1084 +
1085 case WM_NCHITTEST:
1086 if (pTheme->dwStyle & WS_POPUP)
1087 {
@@ -3406,7 +3399,7 @@ static HRESULT ParseControl(
3399 BOOL fAnyTextChildren = FALSE;
3400 BOOL fAnyNoteChildren = FALSE;
3401
3409 - InitializeThemeControl(pControl);
3402 + InitializeThemeControl(pTheme, pControl);
3403
3404 hr = XmlGetAttributeEx(pixn, L"Name", &pControl->sczName);
3405 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control Name attribute.");
@@ -3715,6 +3708,7 @@ LExit:
3708 }
3709
3710 static void InitializeThemeControl(
3711 + THEME* pTheme,
3712 THEME_CONTROL* pControl
3713 )
3714 {
@@ -3722,6 +3716,7 @@ static void InitializeThemeControl(
3716 pControl->dwFontId = THEME_INVALID_ID;
3717 pControl->dwFontSelectedId = THEME_INVALID_ID;
3718 pControl->uStringId = UINT_MAX;
3719 + pControl->pTheme = pTheme;
3720 }
3721
3722
@@ -3854,7 +3849,7 @@ static HRESULT ParseBillboardPanels(
3849 pControl = pParentControl->rgControls + pParentControl->cControls;
3850 pParentControl->cControls += 1;
3851 pControl->type = THEME_CONTROL_TYPE_PANEL;
3857 - InitializeThemeControl(pControl);
3852 + InitializeThemeControl(pTheme, pControl);
3853
3854 if (pPage)
3855 {
@@ -5400,6 +5395,24 @@ static BOOL OnNotifyEnMsgFilter(
5395 return fProcessed;
5396 }
5397
5398 +static BOOL OnPanelCreate(
5399 + __in THEME_CONTROL* pControl,
5400 + __in HWND hWnd
5401 + )
5402 +{
5403 + HRESULT hr = S_OK;
5404 +
5405 + ThmExitOnNull(pControl, hr, E_INVALIDSTATE, "Null control for OnPanelCreate");
5406 +
5407 + pControl->hWnd = hWnd;
5408 +
5409 + hr = LoadControls(pControl->pTheme, pControl);
5410 + ThmExitOnFailure(hr, "Failed to load panel controls.");
5411 +
5412 +LExit:
5413 + return SUCCEEDED(hr);
5414 +}
5415 +
5416 static BOOL OnWmCommand(
5417 __in THEME* pTheme,
5418 __in WPARAM wParam,
@@ -6017,17 +6030,24 @@ static LRESULT CALLBACK PanelWndProc(
6030 )
6031 {
6032 LRESULT lres = 0;
6020 - THEME* pTheme = reinterpret_cast<THEME*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
6033 + THEME_CONTROL* pControl = reinterpret_cast<THEME_CONTROL*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
6034
6035 switch (uMsg)
6036 {
6037 case WM_NCCREATE:
6038 {
6039 LPCREATESTRUCTW lpcs = reinterpret_cast<LPCREATESTRUCTW>(lParam);
6027 - pTheme = reinterpret_cast<THEME*>(lpcs->lpCreateParams);
6028 - ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pTheme));
6040 + pControl = reinterpret_cast<THEME_CONTROL*>(lpcs->lpCreateParams);
6041 + ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pControl));
6042 + break;
6043 }
6030 - break;
6044 +
6045 + case WM_CREATE:
6046 + if (!OnPanelCreate(pControl, hWnd))
6047 + {
6048 + return -1;
6049 + }
6050 + break;
6051
6052 case WM_NCDESTROY:
6053 lres = ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
@@ -6039,7 +6059,7 @@ static LRESULT CALLBACK PanelWndProc(
6059 break;
6060 }
6061
6042 - return ControlGroupDefWindowProc(pTheme, hWnd, uMsg, wParam, lParam);
6062 + return ControlGroupDefWindowProc(pControl ? pControl->pTheme : NULL, hWnd, uMsg, wParam, lParam);
6063 }
6064
6065 static LRESULT CALLBACK StaticOwnerDrawWndProc(
@@ -6087,6 +6107,30 @@ static HRESULT OnLoadingControl(
6107 return hr;
6108 }
6109
6110 +static HRESULT LoadThemeControls(
6111 + __in THEME* pTheme
6112 + )
6113 +{
6114 + HRESULT hr = S_OK;
6115 +
6116 + ThmExitOnNull(pTheme->hwndParent, hr, E_INVALIDSTATE, "LoadThemeControls called before theme parent window created.");
6117 +
6118 + hr = LoadControls(pTheme, NULL);
6119 +
6120 +LExit:
6121 + return hr;
6122 +}
6123 +
6124 +static void UnloadThemeControls(
6125 + __in THEME* pTheme
6126 + )
6127 +{
6128 + UnloadControls(pTheme->cControls, pTheme->rgControls);
6129 +
6130 + pTheme->hwndHover = NULL;
6131 + pTheme->hwndParent = NULL;
6132 +}
6133 +
6134 static HRESULT LoadControls(
6135 __in THEME* pTheme,
6136 __in_opt THEME_CONTROL* pParentControl
@@ -6103,10 +6147,15 @@ static HRESULT LoadControls(
6147 int h = 0;
6148 int x = 0;
6149 int y = 0;
6150 + THEME_LOADEDCONTROL_ARGS loadedControlArgs = { };
6151 + THEME_LOADEDCONTROL_RESULTS loadedControlResults = { };
6152
6153 GetControls(pTheme, pParentControl, cControls, rgControls);
6154 ::GetClientRect(hwndParent, &rcParent);
6155
6156 + loadedControlArgs.cbSize = sizeof(loadedControlArgs);
6157 + loadedControlResults.cbSize = sizeof(loadedControlResults);
6158 +
6159 for (DWORD i = 0; i < cControls; ++i)
6160 {
6161 THEME_CONTROL* pControl = rgControls + i;
@@ -6124,8 +6173,7 @@ static HRESULT LoadControls(
6173
6174 switch (pControl->type)
6175 {
6127 - case THEME_CONTROL_TYPE_BILLBOARD:
6128 - __fallthrough;
6176 + case THEME_CONTROL_TYPE_BILLBOARD: __fallthrough;
6177 case THEME_CONTROL_TYPE_PANEL:
6178 wzWindowClass = vsczPanelClass;
6179 dwWindowExBits |= WS_EX_CONTROLPARENT;
@@ -6309,7 +6357,7 @@ static HRESULT LoadControls(
6357 pControl->dwStyle &= ~WS_VISIBLE;
6358 }
6359
6312 - pControl->hWnd = ::CreateWindowExW(dwWindowExBits, wzWindowClass, pControl->sczText, pControl->dwStyle | dwWindowBits, x, y, w, h, hwndParent, reinterpret_cast<HMENU>(wControlId), NULL, pTheme);
6360 + pControl->hWnd = ::CreateWindowExW(dwWindowExBits, wzWindowClass, pControl->sczText, pControl->dwStyle | dwWindowBits, x, y, w, h, hwndParent, reinterpret_cast<HMENU>(wControlId), NULL, pControl);
6361 ThmExitOnNullWithLastError(pControl->hWnd, hr, "Failed to create window.");
6362
6363 if (pControl->sczTooltip)
@@ -6445,10 +6493,15 @@ static HRESULT LoadControls(
6493 }
6494 }
6495
6448 - if (pControl->cControls)
6496 + loadedControlArgs.pThemeControl = pControl;
6497 + loadedControlResults.hr = E_NOTIMPL;
6498 + if (::SendMessageW(pTheme->hwndParent, WM_THMUTIL_LOADED_CONTROL, reinterpret_cast<WPARAM>(&loadedControlArgs), reinterpret_cast<LPARAM>(&loadedControlResults)))
6499 {
6450 - hr = LoadControls(pTheme, pControl);
6451 - ThmExitOnFailure(hr, "Failed to load child controls.");
6500 + if (E_NOTIMPL != loadedControlResults.hr)
6501 + {
6502 + hr = loadedControlResults.hr;
6503 + ThmExitOnFailure(hr, "ThmLoadedControl failed");
6504 + }
6505 }
6506 }
6507
src/samples/thmviewer/display.cpp
+25 -33
@@ -21,9 +21,10 @@ static LRESULT CALLBACK DisplayWndProc(
21 __in WPARAM wParam,
22 __in LPARAM lParam
23 );
24 -static BOOL DisplayOnCreate(
24 +static BOOL DisplayOnThmLoadedControl(
25 __in THEME* pTheme,
26 - __in HWND hWnd
26 + __in const THEME_LOADEDCONTROL_ARGS* args,
27 + __in THEME_LOADEDCONTROL_RESULTS* results
28 );
29
30
@@ -270,13 +271,6 @@ static LRESULT CALLBACK DisplayWndProc(
271 }
272 break;
273
273 - case WM_CREATE:
274 - if (!DisplayOnCreate(pHandleTheme->pTheme, hWnd))
275 - {
276 - return -1;
277 - }
278 - break;
279 -
274 case WM_TIMER:
275 if (!lParam && SUCCEEDED(ThemeSetProgressControl(pHandleTheme->pTheme, wParam, dwProgress)))
276 {
@@ -308,47 +302,45 @@ static LRESULT CALLBACK DisplayWndProc(
302 }
303 break;
304
311 - case WM_DESTROY:
312 - ThemeUnloadControls(pHandleTheme->pTheme);
313 - ::PostQuitMessage(0);
314 - break;
315 -
305 case WM_NCDESTROY:
306 DecrementHandleTheme(pHandleTheme);
307 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
308 + ::PostQuitMessage(0);
309 break;
310 +
311 + case WM_THMUTIL_LOADED_CONTROL:
312 + if (pHandleTheme)
313 + {
314 + return DisplayOnThmLoadedControl(pHandleTheme->pTheme, reinterpret_cast<THEME_LOADEDCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADEDCONTROL_RESULTS*>(lParam));
315 + }
316 }
317
318 return ThemeDefWindowProc(pHandleTheme ? pHandleTheme->pTheme : NULL, hWnd, uMsg, wParam, lParam);
319 }
320
325 -static BOOL DisplayOnCreate(
321 +static BOOL DisplayOnThmLoadedControl(
322 __in THEME* pTheme,
327 - __in HWND hWnd
323 + __in const THEME_LOADEDCONTROL_ARGS* args,
324 + __in THEME_LOADEDCONTROL_RESULTS* results
325 )
326 {
327 HRESULT hr = S_OK;
331 -
332 - hr = ThemeLoadControls(pTheme);
333 - ExitOnFailure(hr, "Failed to load theme controls");
328 + const THEME_CONTROL* pControl = args->pThemeControl;
329
330 // Pre-populate some control types with data.
336 - for (DWORD i = 0; i < pTheme->cControls; ++i)
331 + if (THEME_CONTROL_TYPE_RICHEDIT == pControl->type)
332 {
338 - THEME_CONTROL* pControl = pTheme->rgControls + i;
339 - if (THEME_CONTROL_TYPE_RICHEDIT == pControl->type)
340 - {
341 - hr = ThemeLoadRichEditFromResource(pTheme, pControl->wId, MAKEINTRESOURCEA(THMVWR_RES_RICHEDIT_FILE), ::GetModuleHandleW(NULL));
342 - ExitOnFailure(hr, "Failed to load richedit text.");
343 - }
344 - else if (THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
345 - {
346 - DWORD dwId = ::SetTimer(hWnd, pControl->wId, 500, NULL);
347 - dwId = dwId; // prevents warning in "ship" build.
348 - Assert(dwId == pControl->wId);
349 - }
333 + hr = ThemeLoadRichEditFromResource(pTheme, pControl->wId, MAKEINTRESOURCEA(THMVWR_RES_RICHEDIT_FILE), ::GetModuleHandleW(NULL));
334 + ExitOnFailure(hr, "Failed to load richedit text.");
335 + }
336 + else if (THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
337 + {
338 + DWORD dwId = ::SetTimer(pTheme->hwndParent, pControl->wId, 500, NULL);
339 + dwId = dwId; // prevents warning in "ship" build.
340 + Assert(dwId == pControl->wId);
341 }
342
343 LExit:
353 - return SUCCEEDED(hr);
344 + results->hr = hr;
345 + return TRUE;
346 }
src/samples/thmviewer/thmviewer.cpp
+1 -14
@@ -353,16 +353,7 @@ static LRESULT CALLBACK MainWndProc(
353 case WM_NCDESTROY:
354 DecrementHandleTheme(pHandleTheme);
355 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
356 - break;
357 -
358 - case WM_CREATE:
359 - {
360 - HRESULT hr = ThemeLoadControls(vpTheme);
361 - if (FAILED(hr))
362 - {
363 - return -1;
364 - }
365 - }
356 + ::PostQuitMessage(0);
357 break;
358
359 case WM_THMVWR_THEME_LOAD_BEGIN:
@@ -377,10 +368,6 @@ static LRESULT CALLBACK MainWndProc(
368 OnNewTheme(vpTheme, hWnd, reinterpret_cast<HANDLE_THEME*>(lParam));
369 return 0;
370
380 - case WM_DESTROY:
381 - ::PostQuitMessage(0);
382 - break;
383 -
371 case WM_THMUTIL_LOADING_CONTROL:
372 return OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
373
src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
+55 -48
@@ -230,18 +230,14 @@ private:
230 return lres;
231 }
232
233 - case WM_CREATE:
234 - if (!pBaf->OnCreate(hWnd))
235 - {
236 - return -1;
237 - }
238 - break;
239 -
233 case WM_THMUTIL_LOADING_CONTROL:
234 return pBaf->OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
235
236 + case WM_THMUTIL_LOADED_CONTROL:
237 + return pBaf->OnThemeLoadedControl(hWnd, reinterpret_cast<THEME_LOADEDCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADEDCONTROL_RESULTS*>(lParam));
238 +
239 case WM_TIMER:
244 - if (!lParam && pBaf)
240 + if (!lParam && BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE == wParam && pBaf)
241 {
242 pBaf->UpdateProgressBarProgress();
243
@@ -253,33 +249,14 @@ private:
249 return ThemeDefWindowProc(pBaf ? pBaf->m_pBafTheme : NULL, hWnd, uMsg, wParam, lParam);
250 }
251
256 - BOOL OnCreate(
257 - __in HWND hWnd
252 + HRESULT OnCreatedListView(
253 + __in HWND hWndListView
254 )
255 {
256 HRESULT hr = S_OK;
257 LVITEMW lvitem = { };
258 LVGROUP lvgroup = { };
259 static UINT puColumns[] = { 0, 1, 2 };
264 - HWND hwndTopLeft = NULL;
265 - HWND hwndTopRight = NULL;
266 - HWND hwndBottomLeft = NULL;
267 - HWND hwndBottomRight = NULL;
268 -
269 - hr = ThemeLoadControls(m_pBafTheme);
270 - BalExitOnFailure(hr, "Failed to load theme controls.");
271 -
272 - hwndTopLeft = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT);
273 - BalExitOnNull(hwndTopLeft, hr, E_INVALIDSTATE, "Failed to get top left list view hWnd.");
274 -
275 - hwndTopRight = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT);
276 - BalExitOnNull(hwndTopRight, hr, E_INVALIDSTATE, "Failed to get top right list view hWnd.");
277 -
278 - hwndBottomLeft = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_LEFT);
279 - BalExitOnNull(hwndBottomLeft, hr, E_INVALIDSTATE, "Failed to get bottom left list view hWnd.");
280 -
281 - hwndBottomRight = ::GetDlgItem(m_pBafTheme->hwndParent, BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_RIGHT);
282 - BalExitOnNull(hwndBottomRight, hr, E_INVALIDSTATE, "Failed to get bottom right list view hWnd.");
260
261 lvgroup.cbSize = sizeof(LVGROUP);
262 lvgroup.mask = LVGF_GROUPID | LVGF_TITLEIMAGE | LVGF_DESCRIPTIONTOP | LVGF_HEADER;
@@ -295,10 +272,7 @@ private:
272 hr = StrAllocFormatted(&lvgroup.pszHeader, L"Header_%d", i);
273 BalExitOnFailure(hr, "Failed to alloc list view group header.");
274
298 - ListView_InsertGroup(hwndTopLeft, -1, &lvgroup);
299 - ListView_InsertGroup(hwndTopRight, -1, &lvgroup);
300 - ListView_InsertGroup(hwndBottomLeft, -1, &lvgroup);
301 - ListView_InsertGroup(hwndBottomRight, -1, &lvgroup);
275 + ListView_InsertGroup(hWndListView, -1, &lvgroup);
276
277 lvitem.mask = LVIF_COLUMNS | LVIF_GROUPID | LVIF_IMAGE | LVIF_TEXT;
278 lvitem.iItem = i;
@@ -312,10 +286,7 @@ private:
286 lvitem.cColumns = countof(puColumns);
287 lvitem.puColumns = puColumns;
288
315 - ListView_InsertItem(hwndTopLeft, &lvitem);
316 - ListView_InsertItem(hwndTopRight, &lvitem);
317 - ListView_InsertItem(hwndBottomLeft, &lvitem);
318 - ListView_InsertItem(hwndBottomRight, &lvitem);
289 + ListView_InsertItem(hWndListView, &lvitem);
290
291 for (int j = 0; j < 3; ++j)
292 {
@@ -325,23 +296,16 @@ private:
296 hr = StrAllocFormatted(&lvitem.pszText, L"%d_%d", j, i);
297 BalExitOnFailure(hr, "Failed to alloc list view subitem text.");
298
328 - ListView_InsertItem(hwndTopLeft, &lvitem);
329 - ListView_InsertItem(hwndTopRight, &lvitem);
330 - ListView_InsertItem(hwndBottomLeft, &lvitem);
331 - ListView_InsertItem(hwndBottomRight, &lvitem);
299 + ListView_InsertItem(hWndListView, &lvitem);
300 }
301 }
302
335 - ListView_EnableGroupView(hwndTopRight, TRUE);
336 -
337 - ::SetTimer(hWnd, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, 500, NULL);
338 -
303 LExit:
304 ReleaseStr(lvgroup.pszDescriptionTop);
305 ReleaseStr(lvgroup.pszHeader);
306 ReleaseStr(lvitem.pszText);
307
344 - return SUCCEEDED(hr);
308 + return hr;
309 }
310
311 BOOL OnThemeLoadingControl(
@@ -349,17 +313,60 @@ private:
313 __in THEME_LOADINGCONTROL_RESULTS* pResults
314 )
315 {
316 + HRESULT hr = S_OK;
317 + BOOL fProcessed = FALSE;
318 +
319 for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
320 {
321 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
322 {
323 + fProcessed = TRUE;
324 pResults->wId = vrgInitControls[iAssignControl].wId;
325 break;
326 }
327 }
328
361 - pResults->hr = S_OK;
362 - return TRUE;
329 + pResults->hr = hr;
330 + return fProcessed || FAILED(hr);
331 + }
332 +
333 + BOOL OnThemeLoadedControl(
334 + __in HWND hWndParent,
335 + __in const THEME_LOADEDCONTROL_ARGS* pArgs,
336 + __in THEME_LOADEDCONTROL_RESULTS* pResults
337 + )
338 + {
339 + HRESULT hr = S_OK;
340 + BOOL fProcessed = FALSE;
341 +
342 + switch (pArgs->pThemeControl->wId)
343 + {
344 + case BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_LEFT:
345 + case BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT:
346 + case BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_LEFT:
347 + case BAFTHMUTILTESTING_CONTROL_LISTVIEW_BOTTOM_RIGHT:
348 + fProcessed = TRUE;
349 +
350 + hr = OnCreatedListView(pArgs->pThemeControl->hWnd);
351 + ExitOnFailure(hr, "Failed to populate list view.");
352 +
353 + if (BAFTHMUTILTESTING_CONTROL_LISTVIEW_TOP_RIGHT == pArgs->pThemeControl->wId)
354 + {
355 + ListView_EnableGroupView(pArgs->pThemeControl->hWnd, TRUE);
356 + }
357 +
358 + break;
359 +
360 + case BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD:
361 + fProcessed = TRUE;
362 +
363 + ::SetTimer(hWndParent, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, 500, NULL);
364 + break;
365 + }
366 +
367 + LExit:
368 + pResults->hr = hr;
369 + return fProcessed || FAILED(hr);
370 }
371
372 void UpdateProgressBarProgress()
src/test/burn/TestData/Manual/BafThmutilTesting/theme/BafThmUtilTestingTheme.xml
+21
@@ -124,6 +124,27 @@ There are currently four states for a button: default, focus, hover, and selecte
124 <Text>Back</Text>
125 <ChangePageAction Page="Button" />
126 </Button>
127 + <Button Name="BillboardButton" X="-183" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
128 + <Text>Next</Text>
129 + <ChangePageAction Page="Billboard" />
130 + </Button>
131 + </Page>
132 + <Page Name="Billboard">
133 + <Label X="6" Y="6" Width="-6" Height="43" FontId="Default">
134 + This page has a billboard. It loops between two panels every 1.5 seconds. Only one button should be visible at all times (this is currently broken).
135 + </Label>
136 + <Billboard Name="FirstBillboard" X="11" Y="59" Width="-11" Height="-39" Interval="1500" Loop="yes">
137 + <BillboardPanel>
138 + <Button Name="FirstBillboardButton1" X="11" Y="11" Width="75" Height="23" TabStop="yes" FontId="Default">First Panel</Button>
139 + </BillboardPanel>
140 + <BillboardPanel>
141 + <Button Name="FirstBillboardButton2" X="11" Y="39" Width="75" Height="23" TabStop="yes" FontId="Default">Second Panel</Button>
142 + </BillboardPanel>
143 + </Billboard>
144 + <Button Name="BillboardBackButton" X="-269" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
145 + <Text>Back</Text>
146 + <ChangePageAction Page="Progressbar" />
147 + </Button>
148 </Page>
149 <Button Name="StartButton" X="-97" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default" Visible="yes">
150 <Text>Start</Text>
src/test/burn/TestData/Manual/BafThmutilTesting/theme/BafThmUtilTestingThemeLoose.xml new
+158
@@ -0,0 +1,158 @@
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="Default" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
7 + <Image Id="star_transparent.bmp" ImageFile="star_transparent.bmp" />
8 + <Image Id="star_opaque.bmp" ImageFile="star_opaque.bmp" />
9 + <Image Id="star_transparent.png" ImageFile="star_transparent.png" />
10 + <Image Id="square_default" ImageFile="16x16.png">
11 + <AlternateResolution ImageFile="32x32.png" />
12 + <AlternateResolution ImageFile="64x64.png" />
13 + <AlternateResolution ImageFile="128x128.png" />
14 + <AlternateResolution ImageFile="256x256.png" />
15 + </Image>
16 + <Image Id="square_focus" ImageFile="64x64_focus.png">
17 + <AlternateResolution ImageFile="128x128_focus.png" />
18 + <AlternateResolution ImageFile="256x256_focus.png" />
19 + </Image>
20 + <Image Id="square_hover" ImageFile="64x64_hover.png">
21 + <AlternateResolution ImageFile="128x128_hover.png" />
22 + <AlternateResolution ImageFile="256x256_hover.png" />
23 + </Image>
24 + <Image Id="square_selected" ImageFile="64x64_selected.png">
25 + <AlternateResolution ImageFile="128x128_selected.png" />
26 + <AlternateResolution ImageFile="256x256_selected.png" />
27 + </Image>
28 + <Image Id="progressbar" ImageFile="progressbar.bmp" />
29 + <Image Id="progressbar_reverse" ImageFile="progressbar_reverse.bmp" />
30 +
31 + <Window Width="600" Height="450" FontId="Default" Caption="BafThmUtilTestingTheme" HexStyle="10cf0000" AutoResize="yes">
32 + <ImageList Name="Stars">
33 + <ImageListItem ImageFile="star_transparent.bmp" />
34 + <ImageListItem ImageFile="star_opaque.bmp" />
35 + <ImageListItem ImageFile="star_transparent.png" />
36 + </ImageList>
37 + <Page Name="Transparency">
38 + <Label X="6" Y="6" Width="-6" Height="94" FontId="Default">
39 + This page has three versions of an image. The top image is a bitmap with a transparent background, the yellow star should be visible but its black background should not (this is currently broken). The middle image is the same bitmap except the black background is fully opaque so the yellow star should be visible on a black background. The bottom image in a PNG version of the top image and should look exactly the same.
40 + </Label>
41 + <ImageControl X="6" Y="106" Width="64" Height="64" ImageId="star_transparent.bmp" />
42 + <ImageControl X="6" Y="176" Width="64" Height="64" ImageId="star_opaque.bmp" />
43 + <ImageControl X="6" Y="246" Width="64" Height="64" ImageId="star_transparent.png" />
44 + <Button Name="ListViewButton" X="-183" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
45 + <Text>Next</Text>
46 + <ChangePageAction Page="ListView" />
47 + </Button>
48 + </Page>
49 + <Page Name="ListView">
50 + <Label X="6" Y="6" Width="-6" Height="18" FontId="Default">
51 + This page is for testing ListView.
52 + </Label>
53 + <ListView Name="ListViewTopLeft" X="6" Y="30" Width="288" Height="176" FontId="Default" HexStyle="00" ImageList="Stars">
54 + <Column Width="100">TL One</Column>
55 + <Column Width="100">TL Two</Column>
56 + <Column Width="88">TL Three</Column>
57 + </ListView>
58 + <ListView Name="ListViewTopRight" X="300" Y="30" Width="-11" Height="176" FontId="Default" HexStyle="01" ImageListGroupHeader="Stars">
59 + <Column Width="100">TR One</Column>
60 + <Column Width="100">TR Two</Column>
61 + <Column Width="88" Expands="yes">TR Exp</Column>
62 + </ListView>
63 + <ListView Name="ListViewBottomLeft" X="6" Y="212" Width="288" Height="176" FontId="Default" HexStyle="02" ImageListSmall="Stars">
64 + <Column Width="100">BL One</Column>
65 + <Column Width="100">BL Two</Column>
66 + <Column Width="88">BL Three</Column>
67 + </ListView>
68 + <ListView Name="ListViewBottomRight" X="300" Y="212" Width="-11" Height="176" FontId="Default" HexStyle="03">
69 + <Column Width="100">BR One</Column>
70 + <Column Width="100">BR Two</Column>
71 + <Column Width="88" Expands="yes">BR Exp</Column>
72 + </ListView>
73 + <Button Name="ListViewBackButton" X="-269" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
74 + <Text>Back</Text>
75 + <ChangePageAction Page="Transparency" />
76 + </Button>
77 + <Button Name="ButtonButton" X="-183" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
78 + <Text>Next</Text>
79 + <ChangePageAction Page="Button" />
80 + </Button>
81 + </Page>
82 + <Page Name="Button">
83 + <Label X="6" Y="6" Width="-6" Height="132" FontId="Default">
84 + This page is for testing graphical buttons. The left image is 16x16 at 100% scaling, the middle image is 32x32 at 100% scaling. The images for the buttons display their dimensions, so the left should be 16x16 at 100% but 32x32 at 200%. The right button starts at 32x32 at 100%, but grows and shrinks with the window and its image should also change.
85 +
86 +There are currently four states for a button: default, focus, hover, and selected (in that priority order). There should be a different image for each state, although the left button should have a focus rectangle over the default image since it didn't specify an image for the focused state.
87 + </Label>
88 + <Button Name="Square16Button" X="6" Y="140" Width="16" Height="16" FontId="Default" TabStop="yes">
89 + <ButtonImage ImageId="square_default" />
90 + <ButtonHoverImage ImageId="square_hover" />
91 + <ButtonSelectedImage ImageId="square_selected" />
92 + </Button>
93 + <Button Name="Square32Button" X="54" Y="140" Width="32" Height="32" FontId="Default" TabStop="yes">
94 + <ButtonImage ImageId="square_default" />
95 + <ButtonFocusImage ImageId="square_focus" />
96 + <ButtonHoverImage ImageId="square_hover" />
97 + <ButtonSelectedImage ImageId="square_selected" />
98 + </Button>
99 + <Button Name="SquareExpandButton" X="92" Y="140" Width="-476" Height="-278" FontId="Default" TabStop="yes">
100 + <ButtonImage ImageId="square_default" />
101 + <ButtonFocusImage ImageId="square_focus" />
102 + <ButtonHoverImage ImageId="square_hover" />
103 + <ButtonSelectedImage ImageId="square_selected" />
104 + </Button>
105 + <Button Name="ButtonBackButton" X="-269" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
106 + <Text>Back</Text>
107 + <ChangePageAction Page="ListView" />
108 + </Button>
109 + <Button Name="ProgressbarButton" X="-183" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
110 + <Text>Next</Text>
111 + <ChangePageAction Page="Progressbar" />
112 + </Button>
113 + </Page>
114 + <Page Name="Progressbar">
115 + <Label X="6" Y="6" Width="-6" Height="94" FontId="Default">
116 + This page has two progress bars. The top progress bar is a standard control, the bottom one is custom drawn from an image. The bottom one should have its left side one pixel wide as black, the right side one pixel wide as grey, the progress as green, and the remaining as blue. The colors should be reversed when the progress goes backward (this is a way to test different colors, not a standard feature of thmutil).
117 + </Label>
118 + <Progressbar Name="StandardProgressBar" X="6" Y="106" Width="-6" Height="23" />
119 + <Progressbar Name="ImageProgressBar" X="6" Y="141" Width="-6" Height="23">
120 + <ProgressbarImage ImageId="progressbar" />
121 + <ProgressbarImage ImageId="progressbar_reverse" />
122 + </Progressbar>
123 + <Button Name="ProgressbarBackButton" X="-269" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
124 + <Text>Back</Text>
125 + <ChangePageAction Page="Button" />
126 + </Button>
127 + <Button Name="BillboardButton" X="-183" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
128 + <Text>Next</Text>
129 + <ChangePageAction Page="Billboard" />
130 + </Button>
131 + </Page>
132 + <Page Name="Billboard">
133 + <Label X="6" Y="6" Width="-6" Height="43" FontId="Default">
134 + This page has a billboard. It loops between two panels every 1.5 seconds. Only one button should be visible at all times (this is currently broken).
135 + </Label>
136 + <Billboard Name="FirstBillboard" X="11" Y="59" Width="-11" Height="-39" Interval="1500" Loop="yes">
137 + <BillboardPanel>
138 + <Button Name="FirstBillboardButton1" X="11" Y="11" Width="75" Height="23" TabStop="yes" FontId="Default">First Panel</Button>
139 + </BillboardPanel>
140 + <BillboardPanel>
141 + <Button Name="FirstBillboardButton2" X="11" Y="39" Width="75" Height="23" TabStop="yes" FontId="Default">Second Panel</Button>
142 + </BillboardPanel>
143 + </Billboard>
144 + <Button Name="BillboardBackButton" X="-269" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default">
145 + <Text>Back</Text>
146 + <ChangePageAction Page="Progressbar" />
147 + </Button>
148 + </Page>
149 + <Button Name="StartButton" X="-97" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default" Visible="yes">
150 + <Text>Start</Text>
151 + <ChangePageAction Page="Transparency" />
152 + </Button>
153 + <Button Name="CloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="Default" Visible="yes">
154 + <Text>ThemeClose</Text>
155 + <CloseWindowAction />
156 + </Button>
157 + </Window>
158 +</Theme>