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>