@joebigelow / wix / commits / 7e60078d

Avoid using control ids inside of thmutil.

Sean Hall committed Oct 31, 2021 at 14:20 UTC 7e60078d4a7fe748a39c135def9e84a2421ab474
14 files changed +845 -551
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+241 -73
@@ -80,7 +80,7 @@ static LPCWSTR vrgwzPageNames[] = {
80 // The range [0, 100) is unused to avoid collisions with system ids,
81 // the range [100, 0x4000) is unused to avoid collisions with thmutil,
82 // the range [0x4000, 0x8000) is unused to avoid collisions with BAFunctions.
83 -const WORD WIXSTDBA_FIRST_ASSIGN_CONTROL_ID = 0x8000;
83 +const WORD WIXSTDBA_FIRST_ASSIGN_CONTROL_ID = 0x8000;
84
85 enum WIXSTDBA_CONTROL
86 {
@@ -119,36 +119,8 @@ enum WIXSTDBA_CONTROL
119 WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK,
120 WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT,
121 WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON,
122 -};
122
124 -static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
125 - { WIXSTDBA_CONTROL_INSTALL_BUTTON, L"InstallButton" },
126 - { WIXSTDBA_CONTROL_EULA_RICHEDIT, L"EulaRichedit" },
127 - { WIXSTDBA_CONTROL_EULA_LINK, L"EulaHyperlink" },
128 - { WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, L"EulaAcceptCheckbox" },
129 -
130 - { WIXSTDBA_CONTROL_REPAIR_BUTTON, L"RepairButton" },
131 - { WIXSTDBA_CONTROL_UNINSTALL_BUTTON, L"UninstallButton" },
132 -
133 - { WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"CacheProgressPackageText" },
134 - { WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, L"CacheProgressbar" },
135 - { WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, L"CacheProgressText" },
136 - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"ExecuteProgressPackageText" },
137 - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, L"ExecuteProgressbar" },
138 - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, L"ExecuteProgressText" },
139 - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"ExecuteProgressActionDataText"},
140 - { WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"OverallProgressPackageText" },
141 - { WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, L"OverallProgressbar" },
142 - { WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, L"OverallCalculatedProgressbar" },
143 - { WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, L"OverallProgressText" },
144 - { WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, L"ProgressCancelButton" },
145 -
146 - { WIXSTDBA_CONTROL_LAUNCH_BUTTON, L"LaunchButton" },
147 - { WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, L"SuccessRestartButton" },
148 -
149 - { WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, L"FailureLogFileLink" },
150 - { WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, L"FailureMessageText" },
151 - { WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, L"FailureRestartButton" },
123 + LAST_WIXSTDBA_CONTROL,
124 };
125
126 typedef struct _WIXSTDBA_PACKAGE_INFO
@@ -589,7 +561,7 @@ public: // IBootstrapperApplication
561
562 wz = sczFormattedString ? sczFormattedString : L"Pausing Windows automatic updates";
563
592 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);
564 + ThemeSetTextControl(m_pControlOverallProgressPackageText, wz);
565
566 ReleaseStr(sczFormattedString);
567 return hr;
@@ -615,7 +587,7 @@ public: // IBootstrapperApplication
587
588 wz = sczFormattedString ? sczFormattedString : L"Creating system restore point";
589
618 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);
590 + ThemeSetTextControl(m_pControlOverallProgressPackageText, wz);
591
592 ReleaseStr(sczFormattedString);
593 return hr;
@@ -635,12 +607,12 @@ public: // IBootstrapperApplication
607 HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
608 LPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId;
609
638 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, wz);
610 + ThemeSetTextControl(m_pControlCacheProgressPackageText, wz);
611
612 // If something started executing, leave it in the overall progress text.
613 if (!m_fStartedExecution)
614 {
643 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);
615 + ThemeSetTextControl(m_pControlOverallProgressPackageText, wz);
616 }
617 }
618
@@ -778,7 +750,7 @@ public: // IBootstrapperApplication
750 )
751 {
752 UpdateCacheProgress(SUCCEEDED(hrStatus) ? 100 : 0);
781 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"");
753 + ThemeSetTextControl(m_pControlCacheProgressPackageText, L"");
754 SetState(WIXSTDBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error.
755 return __super::OnCacheComplete(hrStatus);
756 }
@@ -891,7 +863,7 @@ public: // IBootstrapperApplication
863
864 if (INSTALLMESSAGE_ACTIONSTART == messageType)
865 {
894 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzMessage);
866 + ThemeSetTextControl(m_pControlExecuteProgressActionDataText, wzMessage);
867 }
868
869 return __super::OnExecuteMsiMessage(wzPackageId, messageType, dwUIHint, wzMessage, cData, rgwzData, nRecommendation, pResult);
@@ -911,9 +883,9 @@ public: // IBootstrapperApplication
883 #endif
884
885 ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage);
914 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, wzProgress);
886 + ThemeSetTextControl(m_pControlOverallProgressText, wzProgress);
887
916 - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage);
888 + ThemeSetProgressControl(m_pControlOverallProgressbar, dwOverallProgressPercentage);
889 SetTaskbarButtonProgress(dwOverallProgressPercentage);
890
891 return __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage, pfCancel);
@@ -972,8 +944,8 @@ public: // IBootstrapperApplication
944
945 fShowingInternalUiThisPackage = INSTALLUILEVEL_NONE != (INSTALLUILEVEL_NONE & uiLevel);
946
975 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, wz);
976 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz);
947 + ThemeSetTextControl(m_pControlExecuteProgressPackageText, wz);
948 + ThemeSetTextControl(m_pControlOverallProgressPackageText, wz);
949 }
950
951 ::EnterCriticalSection(&m_csShowingInternalUiThisPackage);
@@ -1000,12 +972,12 @@ public: // IBootstrapperApplication
972 #endif
973
974 ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage);
1003 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, wzProgress);
975 + ThemeSetTextControl(m_pControlExecuteProgressText, wzProgress);
976
1005 - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage);
977 + ThemeSetProgressControl(m_pControlExecuteProgressbar, dwOverallProgressPercentage);
978
979 m_dwCalculatedExecuteProgress = dwOverallProgressPercentage * (100 - WIXSTDBA_ACQUIRE_PERCENTAGE) / 100;
1008 - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
980 + ThemeSetProgressControl(m_pControlOverallCalculatedProgressbar, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
981
982 SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
983
@@ -1051,10 +1023,10 @@ public: // IBootstrapperApplication
1023 {
1024 HRESULT hr = S_OK;
1025
1054 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"");
1055 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"");
1056 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"");
1057 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel.
1026 + ThemeSetTextControl(m_pControlExecuteProgressPackageText, L"");
1027 + ThemeSetTextControl(m_pControlExecuteProgressActionDataText, L"");
1028 + ThemeSetTextControl(m_pControlOverallProgressPackageText, L"");
1029 + ThemeControlEnable(m_pControlProgressCancelButton, FALSE); // no more cancel.
1030 m_fShowingInternalUiThisPackage = FALSE;
1031
1032 SetState(WIXSTDBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error.
@@ -2933,12 +2905,27 @@ private:
2905 BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS themeControlLoadingArgs = { };
2906 BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS themeControlLoadingResults = { };
2907
2936 - for (DWORD iAssignControl = 0; iAssignControl < countof(vrgInitControls); ++iAssignControl)
2908 + for (DWORD iAssignControl = 0; iAssignControl < countof(m_rgInitControls); ++iAssignControl)
2909 {
2938 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, vrgInitControls[iAssignControl].wzName, -1))
2910 + THEME_ASSIGN_CONTROL_ID* pAssignControl = m_rgInitControls + iAssignControl;
2911 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pArgs->pThemeControl->sczName, -1, pAssignControl->wzName, -1))
2912 {
2913 + if (!pAssignControl->ppControl)
2914 + {
2915 + BalExitWithRootFailure(hr, E_INVALIDSTATE, "Control '%ls' has no member variable", pAssignControl->wzName);
2916 + }
2917 +
2918 + if (*pAssignControl->ppControl)
2919 + {
2920 + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Duplicate control name: %ls", pAssignControl->wzName);
2921 + }
2922 + else
2923 + {
2924 + *pAssignControl->ppControl = pArgs->pThemeControl;
2925 + }
2926 +
2927 fProcessed = TRUE;
2941 - pResults->wId = vrgInitControls[iAssignControl].wId;
2928 + pResults->wId = pAssignControl->wId;
2929 ExitFunction();
2930 }
2931 }
@@ -3059,7 +3046,7 @@ private:
3046 hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath);
3047 ExitOnFailure(hr, "Failed to probe for localized license file.");
3048
3062 - hr = ThemeLoadRichEditFromFile(m_pTheme, pThemeControl->wId, sczLicensePath, m_hModule);
3049 + hr = ThemeLoadRichEditFromFile(pThemeControl, sczLicensePath, m_hModule);
3050 ExitOnFailure(hr, "Failed to load license file into richedit control.");
3051
3052 LExit:
@@ -3178,7 +3165,7 @@ private:
3165 hr = m_pEngine->Apply(m_hWnd);
3166 BalExitOnFailure(hr, "Failed to start applying packages.");
3167
3181 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting.
3168 + ThemeControlEnable(m_pControlProgressCancelButton, TRUE); // ensure the cancel button is enabled before starting.
3169
3170 LExit:
3171 if (FAILED(hr))
@@ -3229,22 +3216,22 @@ private:
3216 {
3217 BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated);
3218 }
3232 - ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated));
3219 + ThemeControlElevates(m_pControlInstallButton, (m_Bundle.fPerMachine && !llElevated));
3220
3221 // If the EULA control exists, show it only if a license URL is provided as well.
3235 - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK))
3222 + if (m_pControlEulaHyperlink)
3223 {
3224 BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl);
3238 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink);
3239 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink);
3225 + ThemeControlEnable(m_pControlEulaHyperlink, fEulaLink);
3226 + ThemeControlEnable(m_pControlEulaAcceptCheckbox, fEulaLink);
3227 }
3228
3242 - BOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
3243 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
3229 + BOOL fAcceptedLicense = !m_pControlEulaAcceptCheckbox || !ThemeControlEnabled(m_pControlEulaAcceptCheckbox) || ThemeIsControlChecked(m_pControlEulaAcceptCheckbox);
3230 + ThemeControlEnable(m_pControlInstallButton, fAcceptedLicense);
3231 }
3232 else if (m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId)
3233 {
3247 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REPAIR_BUTTON, !m_fSuppressRepair);
3234 + ThemeControlEnable(m_pControlRepairButton, !m_fSuppressRepair);
3235 }
3236 else if (m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS] == dwNewPageId) // on the "Success" page, check if the restart or launch button should be enabled.
3237 {
@@ -3257,13 +3244,13 @@ private:
3244 fEnableRestartButton = TRUE;
3245 }
3246 }
3260 - else if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON))
3247 + else if (m_pControlLaunchButton)
3248 {
3249 fLaunchTargetExists = BalVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH);
3250 }
3251
3265 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction);
3266 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, fEnableRestartButton);
3252 + ThemeControlEnable(m_pControlLaunchButton, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction);
3253 + ThemeControlEnable(m_pControlSuccessRestartButton, fEnableRestartButton);
3254 }
3255 else if (m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE] == dwNewPageId) // on the "Failure" page, show error message and check if the restart button should be enabled.
3256 {
@@ -3347,7 +3334,7 @@ private:
3334 StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText);
3335 }
3336
3350 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, sczText);
3337 + ThemeSetTextControl(m_pControlFailureMessageText, sczText);
3338 fShowErrorMessage = TRUE;
3339 }
3340
@@ -3359,9 +3346,9 @@ private:
3346 }
3347 }
3348
3362 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, fShowLogLink);
3363 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, fShowErrorMessage);
3364 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, fEnableRestartButton);
3349 + ThemeControlEnable(m_pControlFailureLogFileLink, fShowLogLink);
3350 + ThemeControlEnable(m_pControlFailureMessageText, fShowErrorMessage);
3351 + ThemeControlEnable(m_pControlFailureRestartButton, fEnableRestartButton);
3352 }
3353
3354 HRESULT hr = ThemeShowPage(m_pTheme, dwOldPageId, SW_HIDE);
@@ -3379,7 +3366,7 @@ private:
3366 // On the install page set the focus to the install button or the next enabled control if install is disabled.
3367 if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId)
3368 {
3382 - ThemeSetFocus(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON);
3369 + ThemeSetFocus(m_pControlInstallButton);
3370 }
3371 }
3372 }
@@ -3423,7 +3410,7 @@ private:
3410 // If we canceled, disable cancel button since clicking it again is silly.
3411 if (fClose)
3412 {
3426 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE);
3413 + ThemeControlEnable(m_pControlProgressCancelButton, FALSE);
3414 }
3415
3416 fClose = FALSE;
@@ -3447,8 +3434,8 @@ private:
3434 //
3435 void OnClickAcceptCheckbox()
3436 {
3450 - BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX);
3451 - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense);
3437 + BOOL fAcceptedLicense = ThemeIsControlChecked(m_pControlEulaAcceptCheckbox);
3438 + ThemeControlEnable(m_pControlInstallButton, fAcceptedLicense);
3439 }
3440
3441
@@ -3954,12 +3941,12 @@ LExit:
3941 WCHAR wzProgress[5] = { };
3942
3943 ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallPercentage);
3957 - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, wzProgress);
3944 + ThemeSetTextControl(m_pControlCacheProgressText, wzProgress);
3945
3959 - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, dwOverallPercentage);
3946 + ThemeSetProgressControl(m_pControlCacheProgressbar, dwOverallPercentage);
3947
3948 m_dwCalculatedCacheProgress = dwOverallPercentage * WIXSTDBA_ACQUIRE_PERCENTAGE / 100;
3962 - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
3949 + ThemeSetProgressControl(m_pControlOverallCalculatedProgressbar, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
3950
3951 SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress);
3952 }
@@ -4088,6 +4075,8 @@ public:
4075 __in IBootstrapperEngine* pEngine
4076 ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000)
4077 {
4078 + THEME_ASSIGN_CONTROL_ID* pAssignControl = NULL;
4079 +
4080 m_hModule = hModule;
4081 m_command = { };
4082 m_createArgs = { };
@@ -4141,6 +4130,148 @@ public:
4130 m_hBAFModule = NULL;
4131 m_pfnBAFunctionsProc = NULL;
4132 m_pvBAFunctionsProcContext = NULL;
4133 +
4134 + C_ASSERT(0 == WIXSTDBA_CONTROL_INSTALL_BUTTON - WIXSTDBA_FIRST_ASSIGN_CONTROL_ID);
4135 + pAssignControl = m_rgInitControls;
4136 +
4137 + pAssignControl->wId = WIXSTDBA_CONTROL_INSTALL_BUTTON;
4138 + pAssignControl->wzName = L"InstallButton";
4139 + pAssignControl->ppControl = &m_pControlInstallButton;
4140 + m_pControlInstallButton = NULL;
4141 + ++pAssignControl;
4142 +
4143 + pAssignControl->wId = WIXSTDBA_CONTROL_EULA_RICHEDIT;
4144 + pAssignControl->wzName = L"EulaRichedit";
4145 + pAssignControl->ppControl = &m_pControlEulaRichedit;
4146 + m_pControlEulaRichedit = NULL;
4147 + ++pAssignControl;
4148 +
4149 + pAssignControl->wId = WIXSTDBA_CONTROL_EULA_LINK;
4150 + pAssignControl->wzName = L"EulaHyperlink";
4151 + pAssignControl->ppControl = &m_pControlEulaHyperlink;
4152 + m_pControlEulaHyperlink = NULL;
4153 + ++pAssignControl;
4154 +
4155 + pAssignControl->wId = WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX;
4156 + pAssignControl->wzName = L"EulaAcceptCheckbox";
4157 + pAssignControl->ppControl = &m_pControlEulaAcceptCheckbox;
4158 + m_pControlEulaAcceptCheckbox = NULL;
4159 + ++pAssignControl;
4160 +
4161 + pAssignControl->wId = WIXSTDBA_CONTROL_REPAIR_BUTTON;
4162 + pAssignControl->wzName = L"RepairButton";
4163 + pAssignControl->ppControl = &m_pControlRepairButton;
4164 + m_pControlRepairButton = NULL;
4165 + ++pAssignControl;
4166 +
4167 + pAssignControl->wId = WIXSTDBA_CONTROL_UNINSTALL_BUTTON;
4168 + pAssignControl->wzName = L"UninstallButton";
4169 + pAssignControl->ppControl = &m_pControlUninstallButton;
4170 + m_pControlUninstallButton = NULL;
4171 + ++pAssignControl;
4172 +
4173 + pAssignControl->wId = WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT;
4174 + pAssignControl->wzName = L"CacheProgressPackageText";
4175 + pAssignControl->ppControl = &m_pControlCacheProgressPackageText;
4176 + m_pControlCacheProgressPackageText = NULL;
4177 + ++pAssignControl;
4178 +
4179 + pAssignControl->wId = WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR;
4180 + pAssignControl->wzName = L"CacheProgressbar";
4181 + pAssignControl->ppControl = &m_pControlCacheProgressbar;
4182 + m_pControlCacheProgressbar = NULL;
4183 + ++pAssignControl;
4184 +
4185 + pAssignControl->wId = WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT;
4186 + pAssignControl->wzName = L"CacheProgressText";
4187 + pAssignControl->ppControl = &m_pControlCacheProgressText;
4188 + m_pControlCacheProgressText = NULL;
4189 + ++pAssignControl;
4190 +
4191 + pAssignControl->wId = WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT;
4192 + pAssignControl->wzName = L"ExecuteProgressPackageText";
4193 + pAssignControl->ppControl = &m_pControlExecuteProgressPackageText;
4194 + m_pControlExecuteProgressPackageText = NULL;
4195 + ++pAssignControl;
4196 +
4197 + pAssignControl->wId = WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR;
4198 + pAssignControl->wzName = L"ExecuteProgressbar";
4199 + pAssignControl->ppControl = &m_pControlExecuteProgressbar;
4200 + m_pControlExecuteProgressbar = NULL;
4201 + ++pAssignControl;
4202 +
4203 + pAssignControl->wId = WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT;
4204 + pAssignControl->wzName = L"ExecuteProgressText";
4205 + pAssignControl->ppControl = &m_pControlExecuteProgressText;
4206 + m_pControlExecuteProgressText = NULL;
4207 + ++pAssignControl;
4208 +
4209 + pAssignControl->wId = WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT;
4210 + pAssignControl->wzName = L"ExecuteProgressActionDataText";
4211 + pAssignControl->ppControl = &m_pControlExecuteProgressActionDataText;
4212 + m_pControlExecuteProgressActionDataText = NULL;
4213 + ++pAssignControl;
4214 +
4215 + pAssignControl->wId = WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT;
4216 + pAssignControl->wzName = L"OverallProgressPackageText";
4217 + pAssignControl->ppControl = &m_pControlOverallProgressPackageText;
4218 + m_pControlOverallProgressPackageText = NULL;
4219 + ++pAssignControl;
4220 +
4221 + pAssignControl->wId = WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR;
4222 + pAssignControl->wzName = L"OverallProgressbar";
4223 + pAssignControl->ppControl = &m_pControlOverallProgressbar;
4224 + m_pControlOverallProgressbar = NULL;
4225 + ++pAssignControl;
4226 +
4227 + pAssignControl->wId = WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR;
4228 + pAssignControl->wzName = L"OverallCalculatedProgressbar";
4229 + pAssignControl->ppControl = &m_pControlOverallCalculatedProgressbar;
4230 + m_pControlOverallCalculatedProgressbar = NULL;
4231 + ++pAssignControl;
4232 +
4233 + pAssignControl->wId = WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT;
4234 + pAssignControl->wzName = L"OverallProgressText";
4235 + pAssignControl->ppControl = &m_pControlOverallProgressText;
4236 + m_pControlOverallProgressText = NULL;
4237 + ++pAssignControl;
4238 +
4239 + pAssignControl->wId = WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON;
4240 + pAssignControl->wzName = L"ProgressCancelButton";
4241 + pAssignControl->ppControl = &m_pControlProgressCancelButton;
4242 + m_pControlProgressCancelButton = NULL;
4243 + ++pAssignControl;
4244 +
4245 + pAssignControl->wId = WIXSTDBA_CONTROL_LAUNCH_BUTTON;
4246 + pAssignControl->wzName = L"LaunchButton";
4247 + pAssignControl->ppControl = &m_pControlLaunchButton;
4248 + m_pControlLaunchButton = NULL;
4249 + ++pAssignControl;
4250 +
4251 + pAssignControl->wId = WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON;
4252 + pAssignControl->wzName = L"SuccessRestartButton";
4253 + pAssignControl->ppControl = &m_pControlSuccessRestartButton;
4254 + m_pControlSuccessRestartButton = NULL;
4255 + ++pAssignControl;
4256 +
4257 + pAssignControl->wId = WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK;
4258 + pAssignControl->wzName = L"FailureLogFileLink";
4259 + pAssignControl->ppControl = &m_pControlFailureLogFileLink;
4260 + m_pControlFailureLogFileLink = NULL;
4261 + ++pAssignControl;
4262 +
4263 + pAssignControl->wId = WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT;
4264 + pAssignControl->wzName = L"FailureMessageText";
4265 + pAssignControl->ppControl = &m_pControlFailureMessageText;
4266 + m_pControlFailureMessageText = NULL;
4267 + ++pAssignControl;
4268 +
4269 + pAssignControl->wId = WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON;
4270 + pAssignControl->wzName = L"FailureRestartButton";
4271 + pAssignControl->ppControl = &m_pControlFailureRestartButton;
4272 + m_pControlFailureRestartButton = NULL;
4273 +
4274 + C_ASSERT(LAST_WIXSTDBA_CONTROL == WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON + 1);
4275 }
4276
4277
@@ -4201,11 +4332,48 @@ private:
4332
4333 LPWSTR m_sczLanguage;
4334 THEME* m_pTheme;
4335 + THEME_ASSIGN_CONTROL_ID m_rgInitControls[LAST_WIXSTDBA_CONTROL - WIXSTDBA_FIRST_ASSIGN_CONTROL_ID];
4336 DWORD m_rgdwPageIds[countof(vrgwzPageNames)];
4337 HANDLE m_hUiThread;
4338 BOOL m_fRegistered;
4339 HWND m_hWnd;
4340
4341 + // Welcome page
4342 + const THEME_CONTROL* m_pControlInstallButton;
4343 + const THEME_CONTROL* m_pControlEulaRichedit;
4344 + const THEME_CONTROL* m_pControlEulaHyperlink;
4345 + const THEME_CONTROL* m_pControlEulaAcceptCheckbox;
4346 +
4347 + // Modify page
4348 + const THEME_CONTROL* m_pControlRepairButton;
4349 + const THEME_CONTROL* m_pControlUninstallButton;
4350 +
4351 + // Progress page
4352 + const THEME_CONTROL* m_pControlCacheProgressPackageText;
4353 + const THEME_CONTROL* m_pControlCacheProgressbar;
4354 + const THEME_CONTROL* m_pControlCacheProgressText;
4355 +
4356 + const THEME_CONTROL* m_pControlExecuteProgressPackageText;
4357 + const THEME_CONTROL* m_pControlExecuteProgressbar;
4358 + const THEME_CONTROL* m_pControlExecuteProgressText;
4359 + const THEME_CONTROL* m_pControlExecuteProgressActionDataText;
4360 +
4361 + const THEME_CONTROL* m_pControlOverallProgressPackageText;
4362 + const THEME_CONTROL* m_pControlOverallProgressbar;
4363 + const THEME_CONTROL* m_pControlOverallCalculatedProgressbar;
4364 + const THEME_CONTROL* m_pControlOverallProgressText;
4365 +
4366 + const THEME_CONTROL* m_pControlProgressCancelButton;
4367 +
4368 + // Success page
4369 + const THEME_CONTROL* m_pControlLaunchButton;
4370 + const THEME_CONTROL* m_pControlSuccessRestartButton;
4371 +
4372 + // Failure page
4373 + const THEME_CONTROL* m_pControlFailureLogFileLink;
4374 + const THEME_CONTROL* m_pControlFailureMessageText;
4375 + const THEME_CONTROL* m_pControlFailureRestartButton;
4376 +
4377 WIXSTDBA_STATE m_state;
4378 HRESULT m_hrFinal;
4379
src/ext/Bal/wixstdba/precomp.h
+1
@@ -29,6 +29,7 @@
29 #include "resrutil.h"
30 #include "shelutil.h"
31 #include "strutil.h"
32 +#include "wndutil.h"
33 #include "thmutil.h"
34 #include "verutil.h"
35 #include "uriutil.h"
src/libs/dutil/WixToolset.DUtil/dutil.vcxproj
+2
@@ -107,6 +107,7 @@
107 <ClCompile Include="userutil.cpp" />
108 <ClCompile Include="verutil.cpp" />
109 <ClCompile Include="wiutil.cpp" />
110 + <ClCompile Include="wndutil.cpp" />
111 <ClCompile Include="wuautil.cpp" />
112 <ClCompile Include="xmlutil.cpp" />
113 </ItemGroup>
@@ -164,6 +165,7 @@
165 <ClInclude Include="inc\userutil.h" />
166 <ClInclude Include="inc\verutil.h" />
167 <ClInclude Include="inc\wiutil.h" />
168 + <ClInclude Include="inc\wndutil.h" />
169 <ClInclude Include="inc\wuautil.h" />
170 <ClInclude Include="inc\xmlutil.h" />
171 <ClInclude Include="precomp.h" />
src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters
+6
@@ -165,6 +165,9 @@
165 <ClCompile Include="wiutil.cpp">
166 <Filter>Source Files</Filter>
167 </ClCompile>
168 + <ClCompile Include="wndutil.cpp">
169 + <Filter>Source Files</Filter>
170 + </ClCompile>
171 <ClCompile Include="xmlutil.cpp">
172 <Filter>Source Files</Filter>
173 </ClCompile>
@@ -338,6 +341,9 @@
341 <ClInclude Include="inc\wiutil.h">
342 <Filter>Header Files</Filter>
343 </ClInclude>
344 + <ClInclude Include="inc\wndutil.h">
345 + <Filter>Header Files</Filter>
346 + </ClInclude>
347 <ClInclude Include="inc\xmlutil.h">
348 <Filter>Header Files</Filter>
349 </ClInclude>
src/libs/dutil/WixToolset.DUtil/inc/dutilsources.h
+1
@@ -61,6 +61,7 @@ typedef enum DUTIL_SOURCE
61 DUTIL_SOURCE_WUAUTIL,
62 DUTIL_SOURCE_XMLUTIL,
63 DUTIL_SOURCE_VERUTIL,
64 + DUTIL_SOURCE_WNDUTIL,
65
66 DUTIL_SOURCE_EXTERNAL = 256,
67 } DUTIL_SOURCE;
src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+33 -84
@@ -8,6 +8,7 @@ extern "C" {
8
9 // forward declare
10
11 +typedef struct _THEME_CONTROL THEME_CONTROL;
12 typedef struct _THEME THEME;
13
14 #define ReleaseTheme(p) if (p) { ThemeFree(p); p = NULL; }
@@ -194,11 +195,12 @@ struct THEME_ASSIGN_CONTROL_ID
195 {
196 WORD wId; // id to apply to control
197 LPCWSTR wzName; // name of control to match
198 + const THEME_CONTROL** ppControl;
199 };
200
201 const WORD THEME_FIRST_ASSIGN_CONTROL_ID = 0x4000; // Recommended first control id to be assigned.
202
201 -struct THEME_CONTROL
203 +typedef struct _THEME_CONTROL
204 {
205 THEME_CONTROL_TYPE type;
206
@@ -296,7 +298,7 @@ struct THEME_CONTROL
298 HWND hWnd;
299 DWORD dwData; // type specific data
300 THEME* pTheme;
299 -};
301 +} THEME_CONTROL;
302
303
304 struct THEME_IMAGELIST
@@ -580,8 +582,7 @@ HRESULT DAPI ThemeLoadStrings(
582
583 *******************************************************************/
584 HRESULT DAPI ThemeLoadRichEditFromFile(
583 - __in THEME* pTheme,
584 - __in DWORD dwControl,
585 + __in const THEME_CONTROL* pThemeControl,
586 __in_z LPCWSTR wzFileName,
587 __in HMODULE hModule
588 );
@@ -591,19 +592,7 @@ HRESULT DAPI ThemeLoadRichEditFromFile(
592
593 *******************************************************************/
594 HRESULT DAPI ThemeLoadRichEditFromResource(
594 - __in THEME* pTheme,
595 - __in DWORD dwControl,
596 - __in_z LPCSTR szResourceName,
597 - __in HMODULE hModule
598 - );
599 -
600 -/********************************************************************
601 - ThemeLoadRichEditFromResourceToHWnd - Attach a richedit control (by
602 - HWND) to resource data.
603 -
604 - *******************************************************************/
605 -HRESULT DAPI ThemeLoadRichEditFromResourceToHWnd(
606 - __in HWND hWnd,
595 + __in const THEME_CONTROL* pThemeControl,
596 __in_z LPCSTR szResourceName,
597 __in HMODULE hModule
598 );
@@ -682,18 +671,28 @@ ThemeShowChild - shows a control's specified child control, hiding the rest.
671
672 *******************************************************************/
673 void DAPI ThemeShowChild(
685 - __in THEME* pTheme,
674 __in THEME_CONTROL* pParentControl,
675 __in DWORD dwIndex
676 );
677
678 /********************************************************************
691 - ThemeControlExists - check if a control with the specified id exists.
679 + ThemeControlExistsByHwnd - check if a control with the specified hWnd exists.
680 +
681 + *******************************************************************/
682 +BOOL DAPI ThemeControlExistsByHWnd(
683 + __in const THEME* pTheme,
684 + __in HWND hWnd,
685 + __out_opt const THEME_CONTROL** ppThemeControl
686 + );
687 +
688 +/********************************************************************
689 + ThemeControlExistsById - check if a control with the specified id exists.
690
691 *******************************************************************/
694 -BOOL DAPI ThemeControlExists(
692 +BOOL DAPI ThemeControlExistsById(
693 __in const THEME* pTheme,
696 - __in DWORD dwControl
694 + __in WORD wId,
695 + __out_opt const THEME_CONTROL** ppThemeControl
696 );
697
698 /********************************************************************
@@ -701,8 +700,7 @@ BOOL DAPI ThemeControlExists(
700
701 *******************************************************************/
702 void DAPI ThemeControlEnable(
704 - __in THEME* pTheme,
705 - __in DWORD dwControl,
703 + __in const THEME_CONTROL* pThemeControl,
704 __in BOOL fEnable
705 );
706
@@ -711,8 +709,7 @@ void DAPI ThemeControlEnable(
709
710 *******************************************************************/
711 BOOL DAPI ThemeControlEnabled(
714 - __in THEME* pTheme,
715 - __in DWORD dwControl
712 + __in const THEME_CONTROL* pThemeControl
713 );
714
715 /********************************************************************
@@ -720,8 +717,7 @@ BOOL DAPI ThemeControlEnabled(
717
718 *******************************************************************/
719 void DAPI ThemeControlElevates(
723 - __in THEME* pTheme,
724 - __in DWORD dwControl,
720 + __in const THEME_CONTROL* pThemeControl,
721 __in BOOL fElevates
722 );
723
@@ -730,8 +726,7 @@ void DAPI ThemeControlElevates(
726
727 *******************************************************************/
728 void DAPI ThemeShowControl(
733 - __in THEME* pTheme,
734 - __in DWORD dwControl,
729 + __in const THEME_CONTROL* pThemeControl,
730 __in int nCmdShow
731 );
732
@@ -741,8 +736,7 @@ conditional text and notes.
736
737 *******************************************************************/
738 void DAPI ThemeShowControlEx(
744 - __in THEME* pTheme,
745 - __in DWORD dwControl,
739 + __in const THEME_CONTROL* pThemeControl,
740 __in int nCmdShow
741 );
742
@@ -751,24 +745,7 @@ void DAPI ThemeShowControlEx(
745
746 *******************************************************************/
747 BOOL DAPI ThemeControlVisible(
754 - __in THEME* pTheme,
755 - __in DWORD dwControl
756 - );
757 -
758 -BOOL DAPI ThemePostControlMessage(
759 - __in THEME* pTheme,
760 - __in DWORD dwControl,
761 - __in UINT Msg,
762 - __in WPARAM wParam,
763 - __in LPARAM lParam
764 - );
765 -
766 -LRESULT DAPI ThemeSendControlMessage(
767 - __in const THEME* pTheme,
768 - __in DWORD dwControl,
769 - __in UINT Msg,
770 - __in WPARAM wParam,
771 - __in LPARAM lParam
748 + __in const THEME_CONTROL* pThemeControl
749 );
750
751 /********************************************************************
@@ -789,35 +766,13 @@ HRESULT DAPI ThemeDrawControl(
766 __in DRAWITEMSTRUCT* pdis
767 );
768
792 -/********************************************************************
793 - ThemeHoverControl - mark a control as hover.
794 -
795 -*******************************************************************/
796 -BOOL DAPI ThemeHoverControl(
797 - __in THEME* pTheme,
798 - __in HWND hwndParent,
799 - __in HWND hwndControl
800 - );
801 -
769 /********************************************************************
770 ThemeIsControlChecked - gets whether a control is checked. Only
771 really useful for checkbox controls.
772
773 *******************************************************************/
774 BOOL DAPI ThemeIsControlChecked(
808 - __in THEME* pTheme,
809 - __in DWORD dwControl
810 - );
811 -
812 -/********************************************************************
813 - ThemeSetControlColor - sets the color of text for a control.
814 -
815 -*******************************************************************/
816 -BOOL DAPI ThemeSetControlColor(
817 - __in THEME* pTheme,
818 - __in HDC hdc,
819 - __in HWND hWnd,
820 - __out HBRUSH* phBackgroundBrush
775 + __in const THEME_CONTROL* pThemeControl
776 );
777
778 /********************************************************************
@@ -826,8 +781,7 @@ BOOL DAPI ThemeSetControlColor(
781
782 *******************************************************************/
783 HRESULT DAPI ThemeSetProgressControl(
829 - __in THEME* pTheme,
830 - __in DWORD dwControl,
784 + __in const THEME_CONTROL* pThemeControl,
785 __in DWORD dwProgressPercentage
786 );
787
@@ -837,8 +791,7 @@ HRESULT DAPI ThemeSetProgressControl(
791
792 *******************************************************************/
793 HRESULT DAPI ThemeSetProgressControlColor(
840 - __in THEME* pTheme,
841 - __in DWORD dwControl,
794 + __in const THEME_CONTROL* pThemeControl,
795 __in DWORD dwColorIndex
796 );
797
@@ -847,8 +800,7 @@ HRESULT DAPI ThemeSetProgressControlColor(
800
801 *******************************************************************/
802 HRESULT DAPI ThemeSetTextControl(
850 - __in const THEME* pTheme,
851 - __in DWORD dwControl,
803 + __in const THEME_CONTROL* pThemeControl,
804 __in_z_opt LPCWSTR wzText
805 );
806
@@ -858,8 +810,7 @@ ThemeSetTextControl - sets the text of a control and optionally
810
811 *******************************************************************/
812 HRESULT DAPI ThemeSetTextControlEx(
861 - __in const THEME* pTheme,
862 - __in DWORD dwControl,
813 + __in const THEME_CONTROL* pThemeControl,
814 __in BOOL fUpdate,
815 __in_z_opt LPCWSTR wzText
816 );
@@ -869,8 +820,7 @@ HRESULT DAPI ThemeSetTextControlEx(
820
821 *******************************************************************/
822 HRESULT DAPI ThemeGetTextControl(
872 - __in const THEME* pTheme,
873 - __in DWORD dwControl,
823 + __in const THEME_CONTROL* pThemeControl,
824 __inout_z LPWSTR* psczText
825 );
826
@@ -889,8 +839,7 @@ HRESULT DAPI ThemeUpdateCaption(
839
840 *******************************************************************/
841 void DAPI ThemeSetFocus(
892 - __in THEME* pTheme,
893 - __in DWORD dwControl
842 + __in const THEME_CONTROL* pThemeControl
843 );
844
845 #ifdef __cplusplus
src/libs/dutil/WixToolset.DUtil/inc/wndutil.h new
+41
@@ -0,0 +1,41 @@
1 +#pragma once
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 +#ifdef __cplusplus
6 +extern "C" {
7 +#endif
8 +
9 +/********************************************************************
10 + WnduLoadRichEditFromFile - Attach a richedit control to a RTF file.
11 +
12 + *******************************************************************/
13 +HRESULT DAPI WnduLoadRichEditFromFile(
14 + __in HWND hWnd,
15 + __in_z LPCWSTR wzFileName,
16 + __in HMODULE hModule
17 + );
18 +
19 +/********************************************************************
20 + WnduLoadRichEditFromResource - Attach a richedit control to resource data.
21 +
22 + *******************************************************************/
23 +HRESULT DAPI WnduLoadRichEditFromResource(
24 + __in HWND hWnd,
25 + __in_z LPCSTR szResourceName,
26 + __in HMODULE hModule
27 + );
28 +
29 +/********************************************************************
30 + WnduGetControlText - gets the text of a control.
31 +
32 +*******************************************************************/
33 +HRESULT DAPI WnduGetControlText(
34 + __in HWND hWnd,
35 + __inout_z LPWSTR* psczText
36 + );
37 +
38 +#ifdef __cplusplus
39 +}
40 +#endif
41 +
src/libs/dutil/WixToolset.DUtil/precomp.h
+1
@@ -87,6 +87,7 @@
87 #include "strutil.h"
88 #include "timeutil.h"
89 #include "timeutil.h"
90 +#include "wndutil.h"
91 #include "thmutil.h"
92 #include "uncutil.h"
93 #include "uriutil.h"
src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+275 -375
@@ -44,7 +44,6 @@ const DWORD THEME_INVALID_ID = 0xFFFFFFFF;
44 const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF;
45 const DWORD GROW_FONT_INSTANCES = 3;
46 const DWORD GROW_IMAGE_INSTANCES = 5;
47 -const DWORD GROW_WINDOW_TEXT = 250;
47
48 static Gdiplus::GdiplusStartupInput vgsi;
49 static Gdiplus::GdiplusStartupOutput vgso = { };
@@ -70,16 +69,29 @@ enum INTERNAL_CONTROL_STYLE
69 INTERNAL_CONTROL_STYLE_OWNER_DRAW = 0x0010,
70 };
71
73 -struct MEMBUFFER_FOR_RICHEDIT
74 -{
75 - BYTE* rgbData;
76 - DWORD cbData;
72
78 - DWORD iData;
79 -};
73 +// prototypes
74 +/********************************************************************
75 + ThemeHoverControl - mark a control as hover.
76 +
77 +*******************************************************************/
78 +static BOOL ThemeHoverControl(
79 + __in THEME* pTheme,
80 + __in HWND hwndParent,
81 + __in HWND hwndControl
82 + );
83
84 +/********************************************************************
85 + ThemeSetControlColor - sets the color of text for a control.
86 +
87 +*******************************************************************/
88 +static BOOL ThemeSetControlColor(
89 + __in THEME* pTheme,
90 + __in HDC hdc,
91 + __in HWND hWnd,
92 + __out HBRUSH* phBackgroundBrush
93 + );
94
82 -// prototypes
95 static HRESULT RegisterWindowClasses(
96 __in_opt HMODULE hModule
97 );
@@ -258,11 +270,11 @@ static HRESULT ParseNotes(
270 );
271 static HRESULT StopBillboard(
272 __in THEME* pTheme,
261 - __in DWORD dwControl
273 + __in THEME_CONTROL* pControl
274 );
275 static HRESULT StartBillboard(
276 __in THEME* pTheme,
265 - __in DWORD dwControl
277 + __in THEME_CONTROL* pControl
278 );
279 static HRESULT EnsureFontInstance(
280 __in THEME* pTheme,
@@ -290,7 +302,6 @@ static HRESULT LoadControls(
302 __in_opt THEME_CONTROL* pParentControl
303 );
304 static HRESULT ShowControl(
293 - __in THEME* pTheme,
305 __in THEME_CONTROL* pControl,
306 __in int nCmdShow,
307 __in BOOL fSaveEditboxes,
@@ -376,18 +387,6 @@ static BOOL DrawHoverControl(
387 __in THEME* pTheme,
388 __in BOOL fHover
389 );
379 -static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
380 - __in DWORD_PTR dwCookie,
381 - __in_bcount(cb) LPBYTE pbBuff,
382 - __in LONG cb,
383 - __in LONG *pcb
384 - );
385 -static DWORD CALLBACK RichEditStreamFromMemoryCallback(
386 - __in DWORD_PTR dwCookie,
387 - __in_bcount(cb) LPBYTE pbBuff,
388 - __in LONG cb,
389 - __in LONG *pcb
390 - );
390 static void FreeFontInstance(
391 __in THEME_FONT_INSTANCE* pFontInstance
392 );
@@ -475,6 +474,11 @@ static BOOL OnWmNotify(
474 __in const THEME_CONTROL* pThemeControl,
475 __inout LRESULT* plResult
476 );
477 +static const THEME_CONTROL* FindControlFromId(
478 + __in const THEME* pTheme,
479 + __in WORD wId,
480 + __in_opt const THEME_CONTROL* pParentControl = NULL
481 + );
482 static const THEME_CONTROL* FindControlFromHWnd(
483 __in const THEME* pTheme,
484 __in HWND hWnd,
@@ -974,83 +978,39 @@ LExit:
978
979
980 DAPI_(HRESULT) ThemeLoadRichEditFromFile(
977 - __in THEME* pTheme,
978 - __in DWORD dwControl,
981 + __in const THEME_CONTROL* pThemeControl,
982 __in_z LPCWSTR wzFileName,
983 __in HMODULE hModule
984 )
985 {
983 - HRESULT hr = S_OK;
984 - LPWSTR sczFile = NULL;
985 - HANDLE hFile = INVALID_HANDLE_VALUE;
986 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
987 -
988 - hr = PathRelativeToModule(&sczFile, wzFileName, hModule);
989 - ThmExitOnFailure(hr, "Failed to read resource data.");
986 + HRESULT hr = E_INVALIDARG;
987
991 - hFile = ::CreateFileW(sczFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
992 - if (INVALID_HANDLE_VALUE == hFile)
988 + if (pThemeControl)
989 {
994 - ThmExitWithLastError(hr, "Failed to open RTF file.");
995 - }
996 - else
997 - {
998 - LONGLONG llRtfSize;
999 - hr = FileSizeByHandle(hFile, &llRtfSize);
1000 - if (SUCCEEDED(hr))
1001 - {
1002 - ::SendMessageW(hWnd, EM_EXLIMITTEXT, 0, static_cast<LPARAM>(llRtfSize));
1003 - }
1004 -
1005 - EDITSTREAM es = { };
1006 - es.pfnCallback = RichEditStreamFromFileHandleCallback;
1007 - es.dwCookie = reinterpret_cast<DWORD_PTR>(hFile);
990 + AssertSz(THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type, "ThemeLoadRichEditFromFile called for non-RichEdit control.");
991
1009 - ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es));
1010 - hr = es.dwError;
1011 - ThmExitOnFailure(hr, "Failed to update RTF stream.");
992 + hr = WnduLoadRichEditFromFile(pThemeControl->hWnd, wzFileName, hModule);
993 }
994
1014 -LExit:
1015 - ReleaseStr(sczFile);
1016 - ReleaseFile(hFile);
1017 -
995 return hr;
996 }
997
998
999 DAPI_(HRESULT) ThemeLoadRichEditFromResource(
1023 - __in THEME* pTheme,
1024 - __in DWORD dwControl,
1025 - __in_z LPCSTR szResourceName,
1026 - __in HMODULE hModule
1027 - )
1028 -{
1029 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1030 - return ThemeLoadRichEditFromResourceToHWnd(hWnd, szResourceName, hModule);
1031 -}
1032 -
1033 -DAPI_(HRESULT) ThemeLoadRichEditFromResourceToHWnd(
1034 - __in HWND hWnd,
1000 + __in const THEME_CONTROL* pThemeControl,
1001 __in_z LPCSTR szResourceName,
1002 __in HMODULE hModule
1003 )
1004 {
1039 - HRESULT hr = S_OK;
1040 - MEMBUFFER_FOR_RICHEDIT buffer = { };
1041 - EDITSTREAM es = { };
1042 -
1043 - hr = ResReadData(hModule, szResourceName, reinterpret_cast<LPVOID*>(&buffer.rgbData), &buffer.cbData);
1044 - ThmExitOnFailure(hr, "Failed to read resource data.");
1005 + HRESULT hr = E_INVALIDARG;
1006
1046 - es.pfnCallback = RichEditStreamFromMemoryCallback;
1047 - es.dwCookie = reinterpret_cast<DWORD_PTR>(&buffer);
1007 + if (pThemeControl)
1008 + {
1009 + AssertSz(THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type, "ThemeLoadRichEditFromResource called for non-RichEdit control.");
1010
1049 - ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es));
1050 - hr = es.dwError;
1051 - ThmExitOnFailure(hr, "Failed to update RTF stream.");
1011 + hr = WnduLoadRichEditFromResource(pThemeControl->hWnd, szResourceName, hModule);
1012 + }
1013
1053 -LExit:
1014 return hr;
1015 }
1016
@@ -1293,141 +1253,127 @@ LExit:
1253 }
1254
1255
1296 -DAPI_(BOOL) ThemeControlExists(
1256 +DAPI_(BOOL) ThemeControlExistsByHWnd(
1257 __in const THEME* pTheme,
1298 - __in DWORD dwControl
1258 + __in HWND hWnd,
1259 + __out_opt const THEME_CONTROL** ppThemeControl
1260 )
1261 {
1301 - BOOL fExists = FALSE;
1302 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1303 - if (hWnd)
1262 + const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd);
1263 +
1264 + if (ppThemeControl)
1265 {
1305 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd);
1306 - fExists = (pControl && hWnd == pControl->hWnd);
1266 + *ppThemeControl = pControl;
1267 }
1268
1309 - return fExists;
1269 + return NULL != pControl;
1270 +}
1271 +
1272 +
1273 +DAPI_(BOOL) ThemeControlExistsById(
1274 + __in const THEME* pTheme,
1275 + __in WORD wId,
1276 + __out_opt const THEME_CONTROL** ppThemeControl
1277 + )
1278 +{
1279 + const THEME_CONTROL* pControl = FindControlFromId(pTheme, wId);
1280 +
1281 + if (ppThemeControl)
1282 + {
1283 + *ppThemeControl = pControl;
1284 + }
1285 +
1286 + return NULL != pControl;
1287 }
1288
1289
1290 DAPI_(void) ThemeControlEnable(
1314 - __in THEME* pTheme,
1315 - __in DWORD dwControl,
1291 + __in const THEME_CONTROL* pThemeControl,
1292 __in BOOL fEnable
1293 )
1294 {
1319 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1320 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
1321 - if (pControl)
1295 + if (pThemeControl)
1296 {
1297 + THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl);
1298 pControl->dwInternalStyle = fEnable ? (pControl->dwInternalStyle & ~INTERNAL_CONTROL_STYLE_DISABLED) : (pControl->dwInternalStyle | INTERNAL_CONTROL_STYLE_DISABLED);
1324 - ::EnableWindow(hWnd, fEnable);
1299 + ::EnableWindow(pControl->hWnd, fEnable);
1300
1301 if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_HIDE_WHEN_DISABLED)
1302 {
1328 - ::ShowWindow(hWnd, fEnable ? SW_SHOW : SW_HIDE);
1303 + ::ShowWindow(pControl->hWnd, fEnable ? SW_SHOW : SW_HIDE);
1304 }
1305 }
1306 }
1307
1308
1309 DAPI_(BOOL) ThemeControlEnabled(
1335 - __in THEME* pTheme,
1336 - __in DWORD dwControl
1310 + __in const THEME_CONTROL* pThemeControl
1311 )
1312 {
1339 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1340 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd);
1341 - return pControl && !(pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_DISABLED);
1313 + BOOL fEnabled = FALSE;
1314 +
1315 + if (pThemeControl)
1316 + {
1317 + fEnabled = !(pThemeControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_DISABLED);
1318 + }
1319 +
1320 + return fEnabled;
1321 }
1322
1323
1324 DAPI_(void) ThemeControlElevates(
1346 - __in THEME* pTheme,
1347 - __in DWORD dwControl,
1325 + __in const THEME_CONTROL* pThemeControl,
1326 __in BOOL fElevates
1327 )
1328 {
1351 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1352 - ::SendMessageW(hWnd, BCM_SETSHIELD, 0, fElevates);
1329 + if (pThemeControl)
1330 + {
1331 + ::SendMessageW(pThemeControl->hWnd, BCM_SETSHIELD, 0, fElevates);
1332 + }
1333 }
1334
1335
1336 DAPI_(void) ThemeShowControl(
1357 - __in THEME* pTheme,
1358 - __in DWORD dwControl,
1337 + __in const THEME_CONTROL* pThemeControl,
1338 __in int nCmdShow
1339 )
1340 {
1362 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1363 - ::ShowWindow(hWnd, nCmdShow);
1364 -
1365 - // Save the control's visible state.
1366 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
1367 - if (pControl)
1341 + if (pThemeControl)
1342 {
1343 + THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl);
1344 + ::ShowWindow(pControl->hWnd, nCmdShow);
1345 +
1346 + // Save the control's visible state.
1347 pControl->dwInternalStyle = (SW_HIDE == nCmdShow) ? (pControl->dwInternalStyle | INTERNAL_CONTROL_STYLE_HIDDEN) : (pControl->dwInternalStyle & ~INTERNAL_CONTROL_STYLE_HIDDEN);
1348 }
1349 }
1350
1351
1352 DAPI_(void) ThemeShowControlEx(
1375 - __in THEME* pTheme,
1376 - __in DWORD dwControl,
1353 + __in const THEME_CONTROL* pThemeControl,
1354 __in int nCmdShow
1355 )
1356 {
1380 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1381 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
1382 - if (pControl)
1357 + if (pThemeControl)
1358 {
1384 - ShowControl(pTheme, pControl, nCmdShow, THEME_CONTROL_TYPE_EDITBOX == pControl->type, THEME_SHOW_PAGE_REASON_REFRESH, 0, NULL);
1359 + THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl);
1360 + ShowControl(pControl, nCmdShow, THEME_CONTROL_TYPE_EDITBOX == pControl->type, THEME_SHOW_PAGE_REASON_REFRESH, 0, NULL);
1361 }
1362 }
1363
1364
1365 DAPI_(BOOL) ThemeControlVisible(
1390 - __in THEME* pTheme,
1391 - __in DWORD dwControl
1366 + __in const THEME_CONTROL* pThemeControl
1367 )
1368 {
1394 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1395 - return ::IsWindowVisible(hWnd);
1396 -}
1397 -
1369 + BOOL fVisible = FALSE;
1370
1399 -DAPI_(BOOL) ThemePostControlMessage(
1400 - __in THEME* pTheme,
1401 - __in DWORD dwControl,
1402 - __in UINT Msg,
1403 - __in WPARAM wParam,
1404 - __in LPARAM lParam
1405 - )
1406 -{
1407 - HRESULT hr = S_OK;
1408 - UINT er = ERROR_SUCCESS;
1409 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1410 -
1411 - if (!::PostMessageW(hWnd, Msg, wParam, lParam))
1371 + if (pThemeControl)
1372 {
1413 - er = ::GetLastError();
1414 - hr = HRESULT_FROM_WIN32(er);
1373 + fVisible = ::IsWindowVisible(pThemeControl->hWnd);
1374 }
1375
1417 - return SUCCEEDED(hr);
1418 -}
1419 -
1420 -
1421 -DAPI_(LRESULT) ThemeSendControlMessage(
1422 - __in const THEME* pTheme,
1423 - __in DWORD dwControl,
1424 - __in UINT Msg,
1425 - __in WPARAM wParam,
1426 - __in LPARAM lParam
1427 - )
1428 -{
1429 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1430 - return ::SendMessageW(hWnd, Msg, wParam, lParam);
1376 + return fVisible;
1377 }
1378
1379
@@ -1453,9 +1399,15 @@ DAPI_(HRESULT) ThemeDrawControl(
1399 )
1400 {
1401 HRESULT hr = S_OK;
1456 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, pdis->hwndItem);
1402 + const THEME_CONTROL* pControl = NULL;
1403 + BOOL fExists = ThemeControlExistsByHWnd(pTheme, pdis->hwndItem, &pControl);
1404 +
1405 + AssertSz(fExists, "Expected control window from owner draw window.");
1406 + if (!fExists)
1407 + {
1408 + ExitFunction1(hr = E_INVALIDARG);
1409 + }
1410
1458 - AssertSz(pControl, "Expected control window from owner draw window.");
1411 AssertSz(pControl->hWnd == pdis->hwndItem, "Expected control window to match owner draw window.");
1412 AssertSz(pControl->nWidth < 1 || pControl->nWidth == pdis->rcItem.right - pdis->rcItem.left, "Expected control window width to match owner draw window width.");
1413 AssertSz(pControl->nHeight < 1 || pControl->nHeight == pdis->rcItem.bottom - pdis->rcItem.top, "Expected control window height to match owner draw window height.");
@@ -1492,7 +1444,7 @@ LExit:
1444 }
1445
1446
1495 -DAPI_(BOOL) ThemeHoverControl(
1447 +static BOOL ThemeHoverControl(
1448 __in THEME* pTheme,
1449 __in HWND hwndParent,
1450 __in HWND hwndControl
@@ -1519,16 +1471,21 @@ DAPI_(BOOL) ThemeHoverControl(
1471
1472
1473 DAPI_(BOOL) ThemeIsControlChecked(
1522 - __in THEME* pTheme,
1523 - __in DWORD dwControl
1474 + __in const THEME_CONTROL* pThemeControl
1475 )
1476 {
1526 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1527 - return BST_CHECKED == ::SendMessageW(hWnd, BM_GETCHECK, 0, 0);
1477 + BOOL fChecked = FALSE;
1478 +
1479 + if (pThemeControl)
1480 + {
1481 + fChecked = BST_CHECKED == ::SendMessageW(pThemeControl->hWnd, BM_GETCHECK, 0, 0);
1482 + }
1483 +
1484 + return fChecked;
1485 }
1486
1487
1531 -DAPI_(BOOL) ThemeSetControlColor(
1488 +static BOOL ThemeSetControlColor(
1489 __in THEME* pTheme,
1490 __in HDC hdc,
1491 __in HWND hWnd,
@@ -1537,6 +1494,7 @@ DAPI_(BOOL) ThemeSetControlColor(
1494 {
1495 THEME_FONT* pFont = NULL;
1496 BOOL fHasBackground = FALSE;
1497 + const THEME_CONTROL* pControl = NULL;
1498
1499 *phBackgroundBrush = NULL;
1500
@@ -1544,10 +1502,9 @@ DAPI_(BOOL) ThemeSetControlColor(
1502 {
1503 pFont = (THEME_INVALID_ID == pTheme->dwFontId) ? NULL : pTheme->rgFonts + pTheme->dwFontId;
1504 }
1547 - else
1505 + else if (ThemeControlExistsByHWnd(pTheme, hWnd, &pControl))
1506 {
1549 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd);
1550 - pFont = (!pControl || THEME_INVALID_ID == pControl->dwFontId) ? NULL : pTheme->rgFonts + pControl->dwFontId;
1507 + pFont = THEME_INVALID_ID == pControl->dwFontId ? NULL : pTheme->rgFonts + pControl->dwFontId;
1508 }
1509
1510 if (pFont)
@@ -1577,44 +1534,40 @@ DAPI_(BOOL) ThemeSetControlColor(
1534
1535
1536 DAPI_(HRESULT) ThemeSetProgressControl(
1580 - __in THEME* pTheme,
1581 - __in DWORD dwControl,
1537 + __in const THEME_CONTROL* pThemeControl,
1538 __in DWORD dwProgressPercentage
1539 )
1540 {
1585 - HRESULT hr = E_NOTFOUND;
1586 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1541 + HRESULT hr = E_INVALIDARG;
1542
1588 - if (hWnd)
1543 + if (pThemeControl && THEME_CONTROL_TYPE_PROGRESSBAR == pThemeControl->type)
1544 {
1590 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
1591 - if (pControl && THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
1545 + THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl);
1546 +
1547 + DWORD dwCurrentProgress = LOWORD(pControl->dwData);
1548 +
1549 + if (dwCurrentProgress != dwProgressPercentage)
1550 {
1593 - DWORD dwCurrentProgress = LOWORD(pControl->dwData);
1551 + DWORD dwColor = HIWORD(pControl->dwData);
1552 + pControl->dwData = MAKEDWORD(dwProgressPercentage, dwColor);
1553
1595 - if (dwCurrentProgress != dwProgressPercentage)
1554 + if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW)
1555 {
1597 - DWORD dwColor = HIWORD(pControl->dwData);
1598 - pControl->dwData = MAKEDWORD(dwProgressPercentage, dwColor);
1599 -
1600 - if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW)
1556 + if (!::InvalidateRect(pControl->hWnd, NULL, FALSE))
1557 {
1602 - if (!::InvalidateRect(hWnd, NULL, FALSE))
1603 - {
1604 - ThmExitWithLastError(hr, "Failed to invalidate progress bar window.");
1605 - }
1606 - }
1607 - else
1608 - {
1609 - ::SendMessageW(hWnd, PBM_SETPOS, dwProgressPercentage, 0);
1558 + ThmExitWithLastError(hr, "Failed to invalidate progress bar window.");
1559 }
1611 -
1612 - hr = S_OK;
1560 }
1561 else
1562 {
1616 - hr = S_FALSE;
1563 + ::SendMessageW(pControl->hWnd, PBM_SETPOS, dwProgressPercentage, 0);
1564 }
1565 +
1566 + hr = S_OK;
1567 + }
1568 + else
1569 + {
1570 + hr = S_FALSE;
1571 }
1572 }
1573
@@ -1624,37 +1577,37 @@ LExit:
1577
1578
1579 DAPI_(HRESULT) ThemeSetProgressControlColor(
1627 - __in THEME* pTheme,
1628 - __in DWORD dwControl,
1580 + __in const THEME_CONTROL* pThemeControl,
1581 __in DWORD dwColorIndex
1582 )
1583 {
1632 - HRESULT hr = S_FALSE;
1633 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1634 - if (hWnd)
1584 + HRESULT hr = E_INVALIDARG;
1585 +
1586 + // Only set color on owner draw progress bars.
1587 + if (pThemeControl && THEME_CONTROL_TYPE_PROGRESSBAR == pThemeControl->type && (pThemeControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW))
1588 {
1636 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
1589 + THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl);
1590
1638 - // Only set color on owner draw progress bars.
1639 - if (pControl && (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW) && THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
1591 + if (pControl->ProgressBar.cImageRef <= dwColorIndex)
1592 {
1641 - if (pControl->ProgressBar.cImageRef <= dwColorIndex)
1642 - {
1643 - ThmExitWithRootFailure(hr, E_INVALIDARG, "Invalid progress bar color index: %u", dwColorIndex);
1644 - }
1645 -
1646 - if (HIWORD(pControl->dwData) != dwColorIndex)
1647 - {
1648 - DWORD dwCurrentProgress = LOWORD(pControl->dwData);
1649 - pControl->dwData = MAKEDWORD(dwCurrentProgress, dwColorIndex);
1593 + ThmExitWithRootFailure(hr, E_INVALIDARG, "Invalid progress bar color index: %u", dwColorIndex);
1594 + }
1595
1651 - if (!::InvalidateRect(hWnd, NULL, FALSE))
1652 - {
1653 - ThmExitWithLastError(hr, "Failed to invalidate progress bar window.");
1654 - }
1596 + if (HIWORD(pControl->dwData) != dwColorIndex)
1597 + {
1598 + DWORD dwCurrentProgress = LOWORD(pControl->dwData);
1599 + pControl->dwData = MAKEDWORD(dwCurrentProgress, dwColorIndex);
1600
1656 - hr = S_OK;
1601 + if (!::InvalidateRect(pControl->hWnd, NULL, FALSE))
1602 + {
1603 + ThmExitWithLastError(hr, "Failed to invalidate progress bar window.");
1604 }
1605 +
1606 + hr = S_OK;
1607 + }
1608 + else
1609 + {
1610 + hr = S_FALSE;
1611 }
1612 }
1613
@@ -1664,41 +1617,40 @@ LExit:
1617
1618
1619 DAPI_(HRESULT) ThemeSetTextControl(
1667 - __in const THEME* pTheme,
1668 - __in DWORD dwControl,
1620 + __in const THEME_CONTROL* pThemeControl,
1621 __in_z_opt LPCWSTR wzText
1622 )
1623 {
1672 - return ThemeSetTextControlEx(pTheme, dwControl, FALSE, wzText);
1624 + return ThemeSetTextControlEx(pThemeControl, FALSE, wzText);
1625 }
1626
1627
1628 DAPI_(HRESULT) ThemeSetTextControlEx(
1677 - __in const THEME* pTheme,
1678 - __in DWORD dwControl,
1629 + __in const THEME_CONTROL* pThemeControl,
1630 __in BOOL fUpdate,
1631 __in_z_opt LPCWSTR wzText
1632 )
1633 {
1683 - HRESULT hr = S_OK;
1684 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1634 + HRESULT hr = E_INVALIDARG;
1635
1686 - if (hWnd)
1636 + if (pThemeControl)
1637 {
1638 if (fUpdate)
1639 {
1690 - ::ShowWindow(hWnd, SW_HIDE);
1640 + ::ShowWindow(pThemeControl->hWnd, SW_HIDE);
1641 }
1642
1693 - if (!::SetWindowTextW(hWnd, wzText))
1643 + if (!::SetWindowTextW(pThemeControl->hWnd, wzText))
1644 {
1645 ThmExitWithLastError(hr, "Failed to set control text.");
1646 }
1647
1648 if (fUpdate)
1649 {
1700 - ::ShowWindow(hWnd, SW_SHOW);
1650 + ::ShowWindow(pThemeControl->hWnd, SW_SHOW);
1651 }
1652 +
1653 + hr = S_OK;
1654 }
1655
1656 LExit:
@@ -1707,50 +1659,17 @@ LExit:
1659
1660
1661 DAPI_(HRESULT) ThemeGetTextControl(
1710 - __in const THEME* pTheme,
1711 - __in DWORD dwControl,
1662 + __in const THEME_CONTROL* pThemeControl,
1663 __inout_z LPWSTR* psczText
1664 )
1665 {
1715 - HRESULT hr = S_OK;
1716 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
1717 - SIZE_T cbSize = 0;
1718 - DWORD cchText = 0;
1719 - DWORD cchTextRead = 0;
1720 -
1721 - // Ensure the string has room for at least one character.
1722 - hr = StrMaxLength(*psczText, &cbSize);
1723 - ThmExitOnFailure(hr, "Failed to get text buffer length.");
1666 + HRESULT hr = E_INVALIDARG;
1667
1725 - cchText = (DWORD)min(DWORD_MAX, cbSize);
1726 -
1727 - if (!cchText)
1668 + if (pThemeControl)
1669 {
1729 - cchText = GROW_WINDOW_TEXT;
1730 -
1731 - hr = StrAlloc(psczText, cchText);
1732 - ThmExitOnFailure(hr, "Failed to grow text buffer.");
1670 + hr = WnduGetControlText(pThemeControl->hWnd, psczText);
1671 }
1672
1735 - // Read (and keep growing buffer) until we finally read less than there
1736 - // is room in the buffer.
1737 - for (;;)
1738 - {
1739 - cchTextRead = ::GetWindowTextW(hWnd, *psczText, cchText);
1740 - if (cchTextRead + 1 < cchText)
1741 - {
1742 - break;
1743 - }
1744 - else
1745 - {
1746 - cchText = cchTextRead + GROW_WINDOW_TEXT;
1747 -
1748 - hr = StrAlloc(psczText, cchText);
1749 - ThmExitOnFailure(hr, "Failed to grow text buffer again.");
1750 - }
1751 - }
1752 -
1753 -LExit:
1673 return hr;
1674 }
1675
@@ -1771,25 +1690,26 @@ LExit:
1690
1691
1692 DAPI_(void) ThemeSetFocus(
1774 - __in THEME* pTheme,
1775 - __in DWORD dwControl
1693 + __in const THEME_CONTROL* pThemeControl
1694 )
1695 {
1778 - HWND hwndFocus = ::GetDlgItem(pTheme->hwndParent, dwControl);
1779 - if (hwndFocus && !ThemeControlEnabled(pTheme, dwControl))
1780 - {
1781 - hwndFocus = ::GetNextDlgTabItem(pTheme->hwndParent, hwndFocus, FALSE);
1782 - }
1696 + if (pThemeControl)
1697 + {
1698 + HWND hwndFocus = pThemeControl->hWnd;
1699 + if (hwndFocus && !ThemeControlEnabled(pThemeControl))
1700 + {
1701 + hwndFocus = ::GetNextDlgTabItem(pThemeControl->pTheme->hwndParent, hwndFocus, FALSE);
1702 + }
1703
1784 - if (hwndFocus)
1785 - {
1786 - ::SetFocus(hwndFocus);
1704 + if (hwndFocus)
1705 + {
1706 + ::SetFocus(hwndFocus);
1707 + }
1708 }
1709 }
1710
1711
1712 DAPI_(void) ThemeShowChild(
1792 - __in THEME* pTheme,
1713 __in THEME_CONTROL* pParentControl,
1714 __in DWORD dwIndex
1715 )
@@ -1798,7 +1718,7 @@ DAPI_(void) ThemeShowChild(
1718 for (DWORD i = 0; i < pParentControl->cControls; ++i)
1719 {
1720 THEME_CONTROL* pControl = pParentControl->rgControls + i;
1801 - ShowControl(pTheme, pControl, dwIndex == i ? SW_SHOW : SW_HIDE, FALSE, THEME_SHOW_PAGE_REASON_DEFAULT, 0, NULL);
1721 + ShowControl(pControl, dwIndex == i ? SW_SHOW : SW_HIDE, FALSE, THEME_SHOW_PAGE_REASON_DEFAULT, 0, NULL);
1722 }
1723 }
1724
@@ -4322,28 +4242,24 @@ LExit:
4242
4243 static HRESULT StartBillboard(
4244 __in THEME* pTheme,
4325 - __in DWORD dwControl
4245 + __in THEME_CONTROL* pControl
4246 )
4247 {
4248 HRESULT hr = E_NOTFOUND;
4329 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
4249 + UINT_PTR idEvent = reinterpret_cast<UINT_PTR>(pControl);
4250
4331 - if (hWnd)
4251 + if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type)
4252 {
4333 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd));
4334 - if (pControl && THEME_CONTROL_TYPE_BILLBOARD == pControl->type)
4335 - {
4336 - // kick off
4337 - pControl->dwData = 0;
4338 - OnBillboardTimer(pTheme, pTheme->hwndParent, dwControl);
4253 + // kick off
4254 + pControl->dwData = 0;
4255 + OnBillboardTimer(pTheme, pTheme->hwndParent, idEvent);
4256
4340 - if (!::SetTimer(pTheme->hwndParent, pControl->wId, pControl->wBillboardInterval, NULL))
4341 - {
4342 - ThmExitWithLastError(hr, "Failed to start billboard.");
4343 - }
4344 -
4345 - hr = S_OK;
4257 + if (!::SetTimer(pTheme->hwndParent, idEvent, pControl->wBillboardInterval, NULL))
4258 + {
4259 + ThmExitWithLastError(hr, "Failed to start billboard.");
4260 }
4261 +
4262 + hr = S_OK;
4263 }
4264
4265 LExit:
@@ -4353,23 +4269,19 @@ LExit:
4269
4270 static HRESULT StopBillboard(
4271 __in THEME* pTheme,
4356 - __in DWORD dwControl
4272 + __in THEME_CONTROL* pControl
4273 )
4274 {
4275 HRESULT hr = E_NOTFOUND;
4360 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
4276 + UINT_PTR idEvent = reinterpret_cast<UINT_PTR>(pControl);
4277
4362 - if (hWnd)
4278 + if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type)
4279 {
4364 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd);
4365 - if (pControl && THEME_CONTROL_TYPE_BILLBOARD == pControl->type)
4366 - {
4367 - ThemeControlEnable(pTheme, dwControl, FALSE);
4280 + ThemeControlEnable(pControl, FALSE);
4281
4369 - if (::KillTimer(pTheme->hwndParent, pControl->wId))
4370 - {
4371 - hr = S_OK;
4372 - }
4282 + if (::KillTimer(pTheme->hwndParent, idEvent))
4283 + {
4284 + hr = S_OK;
4285 }
4286 }
4287
@@ -5039,81 +4951,33 @@ static void FreeImageInstance(
4951 }
4952
4953
5042 -static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
5043 - __in DWORD_PTR dwCookie,
5044 - __in_bcount(cb) LPBYTE pbBuff,
5045 - __in LONG cb,
5046 - __in LONG* pcb
5047 - )
5048 -{
5049 - HRESULT hr = S_OK;
5050 - HANDLE hFile = reinterpret_cast<HANDLE>(dwCookie);
5051 -
5052 - if (!::ReadFile(hFile, pbBuff, cb, reinterpret_cast<DWORD*>(pcb), NULL))
5053 - {
5054 - ThmExitWithLastError(hr, "Failed to read file");
5055 - }
5056 -
5057 -LExit:
5058 - return hr;
5059 -}
5060 -
5061 -
5062 -static DWORD CALLBACK RichEditStreamFromMemoryCallback(
5063 - __in DWORD_PTR dwCookie,
5064 - __in_bcount(cb) LPBYTE pbBuff,
5065 - __in LONG cb,
5066 - __in LONG* pcb
5067 - )
5068 -{
5069 - HRESULT hr = S_OK;
5070 - MEMBUFFER_FOR_RICHEDIT* pBuffer = reinterpret_cast<MEMBUFFER_FOR_RICHEDIT*>(dwCookie);
5071 - DWORD cbCopy = 0;
5072 -
5073 - if (pBuffer->iData < pBuffer->cbData)
5074 - {
5075 - cbCopy = min(static_cast<DWORD>(cb), pBuffer->cbData - pBuffer->iData);
5076 - memcpy(pbBuff, pBuffer->rgbData + pBuffer->iData, cbCopy);
5077 -
5078 - pBuffer->iData += cbCopy;
5079 - Assert(pBuffer->iData <= pBuffer->cbData);
5080 - }
5081 -
5082 - *pcb = cbCopy;
5083 - return hr;
5084 -}
5085 -
5086 -
4954 static void CALLBACK OnBillboardTimer(
5088 - __in THEME* pTheme,
4955 + __in THEME* /*pTheme*/,
4956 __in HWND hwnd,
4957 __in UINT_PTR idEvent
4958 )
4959 {
5093 - HWND hwndControl = ::GetDlgItem(hwnd, static_cast<int>(idEvent));
5094 - if (hwndControl)
4960 + THEME_CONTROL* pControl = reinterpret_cast<THEME_CONTROL*>(idEvent);
4961 +
4962 + if (pControl)
4963 {
5096 - THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hwndControl));
5097 - AssertSz(pControl && THEME_CONTROL_TYPE_BILLBOARD == pControl->type, "Only billboard controls should get billboard timer messages.");
4964 + AssertSz(THEME_CONTROL_TYPE_BILLBOARD == pControl->type, "Only billboard controls should get billboard timer messages.");
4965
5099 - if (pControl)
4966 + if (pControl->dwData < pControl->cControls)
4967 {
5101 - if (pControl->dwData < pControl->cControls)
5102 - {
5103 - ThemeShowChild(pTheme, pControl, pControl->dwData);
5104 - }
5105 - else if (pControl->fBillboardLoops)
5106 - {
5107 - pControl->dwData = 0;
5108 - ThemeShowChild(pTheme, pControl, pControl->dwData);
5109 - }
5110 - else // no more looping
5111 - {
5112 - ::KillTimer(hwnd, idEvent);
5113 - }
5114 -
5115 - ++pControl->dwData;
4968 + ThemeShowChild(pControl, pControl->dwData);
4969 }
4970 + else if (pControl->fBillboardLoops)
4971 + {
4972 + pControl->dwData = 0;
4973 + ThemeShowChild(pControl, pControl->dwData);
4974 + }
4975 + else // no more looping
4976 + {
4977 + ::KillTimer(hwnd, idEvent);
4978 + }
4979 +
4980 + ++pControl->dwData;
4981 }
4982 }
4983
@@ -5151,7 +5015,7 @@ static void OnBrowseDirectory(
5015
5016 if (pTargetControl && THEME_CONTROL_TYPE_EDITBOX == pTargetControl->type && !pTargetControl->fDisableVariableFunctionality)
5017 {
5154 - hr = ThemeSetTextControl(pTheme, pTargetControl->wId, wzPath);
5018 + hr = ThemeSetTextControl(pTargetControl, wzPath);
5019 ThmExitOnFailure(hr, "Failed to set text on editbox: %ls", pTargetControl->sczName);
5020 }
5021 else if (pTheme->pfnSetStringVariable)
@@ -5161,7 +5025,7 @@ static void OnBrowseDirectory(
5025 }
5026 else if (pTargetControl)
5027 {
5164 - hr = ThemeSetTextControl(pTheme, pTargetControl->wId, wzPath);
5028 + hr = ThemeSetTextControl(pTargetControl, wzPath);
5029 ThmExitOnFailure(hr, "Failed to set text on control: %ls", pTargetControl->sczName);
5030 }
5031
@@ -5252,13 +5116,13 @@ static BOOL OnButtonClicked(
5116 case THEME_CONTROL_TYPE_CHECKBOX:
5117 if (pTheme->pfnSetNumericVariable && pControl->sczName && *pControl->sczName)
5118 {
5255 - BOOL fChecked = ThemeIsControlChecked(pTheme, pControl->wId);
5119 + BOOL fChecked = ThemeIsControlChecked(pControl);
5120 pTheme->pfnSetNumericVariable(pControl->sczName, fChecked ? 1 : 0, pTheme->pvVariableContext);
5121 fRefresh = TRUE;
5122 }
5123 break;
5124 case THEME_CONTROL_TYPE_RADIOBUTTON:
5261 - if (pTheme->pfnSetStringVariable && pControl->sczVariable && *pControl->sczVariable && ThemeIsControlChecked(pTheme, pControl->wId))
5125 + if (pTheme->pfnSetStringVariable && pControl->sczVariable && *pControl->sczVariable && ThemeIsControlChecked(pControl))
5126 {
5127 pTheme->pfnSetStringVariable(pControl->sczVariable, pControl->sczValue, FALSE, pTheme->pvVariableContext);
5128 fRefresh = TRUE;
@@ -5386,6 +5250,42 @@ LExit:
5250 return fProcessed;
5251 }
5252
5253 +static const THEME_CONTROL* FindControlFromId(
5254 + __in const THEME* pTheme,
5255 + __in WORD wId,
5256 + __in_opt const THEME_CONTROL* pParentControl
5257 + )
5258 +{
5259 + DWORD cControls = 0;
5260 + THEME_CONTROL* rgControls = NULL;
5261 + const THEME_CONTROL* pChildControl = NULL;
5262 +
5263 + GetControls(pTheme, pParentControl, cControls, rgControls);
5264 +
5265 + // Breadth first search since control ids are technically only valid for direct child windows of a specific parent window.
5266 + for (DWORD i = 0; i < cControls; ++i)
5267 + {
5268 + if (wId == rgControls[i].wId)
5269 + {
5270 + return rgControls + i;
5271 + }
5272 + }
5273 +
5274 + for (DWORD i = 0; i < cControls; ++i)
5275 + {
5276 + if (0 < rgControls[i].cControls)
5277 + {
5278 + pChildControl = FindControlFromId(pTheme, wId, rgControls + i);
5279 + if (pChildControl)
5280 + {
5281 + return pChildControl;
5282 + }
5283 + }
5284 + }
5285 +
5286 + return NULL;
5287 +}
5288 +
5289 static BOOL OnNotifyEnMsgFilter(
5290 __in THEME* pTheme,
5291 __in const THEME_CONTROL* pThemeControl,
@@ -5638,7 +5538,6 @@ LExit:
5538
5539
5540 static HRESULT ShowControl(
5641 - __in THEME* pTheme,
5541 __in THEME_CONTROL* pControl,
5542 __in int nCmdShow,
5543 __in BOOL fSaveEditboxes,
@@ -5654,13 +5553,14 @@ static HRESULT ShowControl(
5553 LPWSTR sczText = NULL;
5554 THEME_SAVEDVARIABLE* pSavedVariable = NULL;
5555 BOOL fHide = SW_HIDE == nCmdShow;
5556 + THEME* pTheme = pControl->pTheme;
5557 THEME_PAGE* pPage = ThemeGetPage(pTheme, dwPageId);
5558
5559 // Save the editbox value if necessary (other control types save their values immediately).
5560 if (pTheme->pfnSetStringVariable && !pControl->fDisableVariableFunctionality &&
5561 fSaveEditboxes && THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName)
5562 {
5663 - hr = ThemeGetTextControl(pTheme, pControl->wId, &sczText);
5563 + hr = ThemeGetTextControl(pControl, &sczText);
5564 ThmExitOnFailure(hr, "Failed to get the text for control: %ls", pControl->sczName);
5565
5566 hr = pTheme->pfnSetStringVariable(pControl->sczName, sczText, FALSE, pTheme->pvVariableContext);
@@ -5675,7 +5575,7 @@ static HRESULT ShowControl(
5575
5576 if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type)
5577 {
5678 - StopBillboard(pTheme, pControl->wId);
5578 + StopBillboard(pTheme, pControl);
5579 }
5580
5581 ExitFunction();
@@ -5767,7 +5667,7 @@ static HRESULT ShowControl(
5667 ReleaseNullStr(sczText);
5668 }
5669
5770 - ThemeSetTextControl(pTheme, pControl->wId, sczText);
5670 + ThemeSetTextControl(pControl, sczText);
5671
5672 if (wzNote && *wzNote)
5673 {
@@ -5811,7 +5711,7 @@ static HRESULT ShowControl(
5711 ++iPageControl;
5712 }
5713
5814 - ThemeSendControlMessage(pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0);
5714 + ::SendMessageW(pControl->hWnd, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0);
5715 }
5716
5717 // If this is an editbox control,
@@ -5838,7 +5738,7 @@ static HRESULT ShowControl(
5738 ++iPageControl;
5739 }
5740
5841 - ThemeSetTextControl(pTheme, pControl->wId, sczText);
5741 + ThemeSetTextControl(pControl, sczText);
5742 }
5743 }
5744
@@ -5901,11 +5801,11 @@ static HRESULT ShowControl(
5801 {
5802 if (fEnabled)
5803 {
5904 - StartBillboard(pTheme, pControl->wId);
5804 + StartBillboard(pTheme, pControl);
5805 }
5806 else
5807 {
5908 - StopBillboard(pTheme, pControl->wId);
5808 + StopBillboard(pTheme, pControl);
5809 }
5810 }
5811
@@ -5944,7 +5844,7 @@ static HRESULT ShowControls(
5844 // Only look at non-page controls and the specified page's controls.
5845 if (!pControl->wPageId || pControl->wPageId == dwPageId)
5846 {
5947 - hr = ShowControl(pTheme, pControl, nCmdShow, fSaveEditboxes, reason, dwPageId, &hwndFocus);
5847 + hr = ShowControl(pControl, nCmdShow, fSaveEditboxes, reason, dwPageId, &hwndFocus);
5848 ThmExitOnFailure(hr, "Failed to show control '%ls' at index %d.", pControl->sczName, i);
5849 }
5850 }
@@ -6509,7 +6409,7 @@ static HRESULT LoadControls(
6409 HRESULT hrFormat = pTheme->pfnFormatString(pControl->sczText, &sczText, pTheme->pvVariableContext);
6410 if (SUCCEEDED(hrFormat))
6411 {
6512 - ThemeSetTextControl(pTheme, pControl->wId, sczText);
6412 + ThemeSetTextControl(pControl, sczText);
6413 }
6414 }
6415
src/libs/dutil/WixToolset.DUtil/wndutil.cpp new
+206
@@ -0,0 +1,206 @@
1 +// 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.
2 +
3 +#include "precomp.h"
4 +
5 +
6 +// Exit macros
7 +#define WnduExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
8 +#define WnduExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
9 +#define WnduExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
10 +#define WnduExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
11 +#define WnduExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
12 +#define WnduExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_WNDUTIL, x, e, s, __VA_ARGS__)
13 +#define WnduExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
14 +#define WnduExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_WNDUTIL, p, x, e, s, __VA_ARGS__)
15 +#define WnduExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_WNDUTIL, p, x, s, __VA_ARGS__)
16 +#define WnduExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_WNDUTIL, p, x, e, s, __VA_ARGS__)
17 +#define WnduExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_WNDUTIL, p, x, s, __VA_ARGS__)
18 +#define WnduExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_WNDUTIL, e, x, s, __VA_ARGS__)
19 +#define WnduExitOnOptionalXmlQueryFailure(x, b, s, ...) ExitOnOptionalXmlQueryFailureSource(DUTIL_SOURCE_WNDUTIL, x, b, s, __VA_ARGS__)
20 +#define WnduExitOnRequiredXmlQueryFailure(x, s, ...) ExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__)
21 +#define WnduExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_WNDUTIL, g, x, s, __VA_ARGS__)
22 +
23 +struct MEMBUFFER_FOR_RICHEDIT
24 +{
25 + BYTE* rgbData;
26 + DWORD cbData;
27 +
28 + DWORD iData;
29 +};
30 +
31 +const DWORD GROW_WINDOW_TEXT = 250;
32 +
33 +
34 +// prototypes
35 +static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
36 + __in DWORD_PTR dwCookie,
37 + __in_bcount(cb) LPBYTE pbBuff,
38 + __in LONG cb,
39 + __in LONG *pcb
40 + );
41 +static DWORD CALLBACK RichEditStreamFromMemoryCallback(
42 + __in DWORD_PTR dwCookie,
43 + __in_bcount(cb) LPBYTE pbBuff,
44 + __in LONG cb,
45 + __in LONG *pcb
46 + );
47 +
48 +
49 +DAPI_(HRESULT) WnduLoadRichEditFromFile(
50 + __in HWND hWnd,
51 + __in_z LPCWSTR wzFileName,
52 + __in HMODULE hModule
53 + )
54 +{
55 + HRESULT hr = S_OK;
56 + LPWSTR sczFile = NULL;
57 + HANDLE hFile = INVALID_HANDLE_VALUE;
58 +
59 + hr = PathRelativeToModule(&sczFile, wzFileName, hModule);
60 + WnduExitOnFailure(hr, "Failed to read resource data.");
61 +
62 + hFile = ::CreateFileW(sczFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
63 + if (INVALID_HANDLE_VALUE == hFile)
64 + {
65 + WnduExitWithLastError(hr, "Failed to open RTF file.");
66 + }
67 + else
68 + {
69 + LONGLONG llRtfSize;
70 + hr = FileSizeByHandle(hFile, &llRtfSize);
71 + if (SUCCEEDED(hr))
72 + {
73 + ::SendMessageW(hWnd, EM_EXLIMITTEXT, 0, static_cast<LPARAM>(llRtfSize));
74 + }
75 +
76 + EDITSTREAM es = { };
77 + es.pfnCallback = RichEditStreamFromFileHandleCallback;
78 + es.dwCookie = reinterpret_cast<DWORD_PTR>(hFile);
79 +
80 + ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es));
81 + hr = es.dwError;
82 + WnduExitOnFailure(hr, "Failed to update RTF stream.");
83 + }
84 +
85 +LExit:
86 + ReleaseStr(sczFile);
87 + ReleaseFile(hFile);
88 +
89 + return hr;
90 +}
91 +
92 +DAPI_(HRESULT) WnduLoadRichEditFromResource(
93 + __in HWND hWnd,
94 + __in_z LPCSTR szResourceName,
95 + __in HMODULE hModule
96 + )
97 +{
98 + HRESULT hr = S_OK;
99 + MEMBUFFER_FOR_RICHEDIT buffer = { };
100 + EDITSTREAM es = { };
101 +
102 + hr = ResReadData(hModule, szResourceName, reinterpret_cast<LPVOID*>(&buffer.rgbData), &buffer.cbData);
103 + WnduExitOnFailure(hr, "Failed to read resource data.");
104 +
105 + es.pfnCallback = RichEditStreamFromMemoryCallback;
106 + es.dwCookie = reinterpret_cast<DWORD_PTR>(&buffer);
107 +
108 + ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es));
109 + hr = es.dwError;
110 + WnduExitOnFailure(hr, "Failed to update RTF stream.");
111 +
112 +LExit:
113 + return hr;
114 +}
115 +
116 +
117 +DAPI_(HRESULT) WnduGetControlText(
118 + __in HWND hWnd,
119 + __inout_z LPWSTR* psczText
120 + )
121 +{
122 + HRESULT hr = S_OK;
123 + SIZE_T cbSize = 0;
124 + DWORD cchText = 0;
125 + DWORD cchTextRead = 0;
126 +
127 + // Ensure the string has room for at least one character.
128 + hr = StrMaxLength(*psczText, &cbSize);
129 + WnduExitOnFailure(hr, "Failed to get text buffer length.");
130 +
131 + cchText = (DWORD)min(DWORD_MAX, cbSize);
132 +
133 + if (!cchText)
134 + {
135 + cchText = GROW_WINDOW_TEXT;
136 +
137 + hr = StrAlloc(psczText, cchText);
138 + WnduExitOnFailure(hr, "Failed to grow text buffer.");
139 + }
140 +
141 + // Read (and keep growing buffer) until we finally read less than there
142 + // is room in the buffer.
143 + for (;;)
144 + {
145 + cchTextRead = ::GetWindowTextW(hWnd, *psczText, cchText);
146 + if (cchTextRead + 1 < cchText)
147 + {
148 + break;
149 + }
150 + else
151 + {
152 + cchText = cchTextRead + GROW_WINDOW_TEXT;
153 +
154 + hr = StrAlloc(psczText, cchText);
155 + WnduExitOnFailure(hr, "Failed to grow text buffer again.");
156 + }
157 + }
158 +
159 +LExit:
160 + return hr;
161 +}
162 +
163 +
164 +static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
165 + __in DWORD_PTR dwCookie,
166 + __in_bcount(cb) LPBYTE pbBuff,
167 + __in LONG cb,
168 + __in LONG* pcb
169 + )
170 +{
171 + HRESULT hr = S_OK;
172 + HANDLE hFile = reinterpret_cast<HANDLE>(dwCookie);
173 +
174 + if (!::ReadFile(hFile, pbBuff, cb, reinterpret_cast<DWORD*>(pcb), NULL))
175 + {
176 + WnduExitWithLastError(hr, "Failed to read file");
177 + }
178 +
179 +LExit:
180 + return hr;
181 +}
182 +
183 +
184 +static DWORD CALLBACK RichEditStreamFromMemoryCallback(
185 + __in DWORD_PTR dwCookie,
186 + __in_bcount(cb) LPBYTE pbBuff,
187 + __in LONG cb,
188 + __in LONG* pcb
189 + )
190 +{
191 + HRESULT hr = S_OK;
192 + MEMBUFFER_FOR_RICHEDIT* pBuffer = reinterpret_cast<MEMBUFFER_FOR_RICHEDIT*>(dwCookie);
193 + DWORD cbCopy = 0;
194 +
195 + if (pBuffer->iData < pBuffer->cbData)
196 + {
197 + cbCopy = min(static_cast<DWORD>(cb), pBuffer->cbData - pBuffer->iData);
198 + memcpy(pbBuff, pBuffer->rgbData + pBuffer->iData, cbCopy);
199 +
200 + pBuffer->iData += cbCopy;
201 + Assert(pBuffer->iData <= pBuffer->cbData);
202 + }
203 +
204 + *pcb = cbCopy;
205 + return hr;
206 +}
src/samples/thmviewer/display.cpp
+4 -4
@@ -188,7 +188,7 @@ static DWORD WINAPI DisplayThreadProc(
188 THEME_CONTROL* pControl = pCurrentHandle->pTheme->rgControls + i;
189 if (!pControl->wPageId)
190 {
191 - ThemeShowControl(pCurrentHandle->pTheme, pControl->wId, nCmdShow);
191 + ThemeShowControl(pControl, nCmdShow);
192 }
193 }
194
@@ -264,7 +264,7 @@ static LRESULT CALLBACK DisplayWndProc(
264 break;
265
266 case WM_TIMER:
267 - if (!lParam && SUCCEEDED(ThemeSetProgressControl(pHandleTheme->pTheme, wParam, dwProgress)))
267 + if (!lParam && SUCCEEDED(ThemeSetProgressControl(reinterpret_cast<THEME_CONTROL*>(wParam), dwProgress)))
268 {
269 dwProgress += rand() % 10 + 1;
270 if (dwProgress > 100)
@@ -322,12 +322,12 @@ static BOOL DisplayOnThmLoadedControl(
322 // Pre-populate some control types with data.
323 if (THEME_CONTROL_TYPE_RICHEDIT == pControl->type)
324 {
325 - hr = ThemeLoadRichEditFromResource(pTheme, pControl->wId, MAKEINTRESOURCEA(THMVWR_RES_RICHEDIT_FILE), ::GetModuleHandleW(NULL));
325 + hr = WnduLoadRichEditFromResource(pControl->hWnd, MAKEINTRESOURCEA(THMVWR_RES_RICHEDIT_FILE), ::GetModuleHandleW(NULL));
326 ExitOnFailure(hr, "Failed to load richedit text.");
327 }
328 else if (THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
329 {
330 - DWORD dwId = ::SetTimer(pTheme->hwndParent, pControl->wId, 500, NULL);
330 + DWORD dwId = ::SetTimer(pTheme->hwndParent, reinterpret_cast<UINT_PTR>(pControl), 500, NULL);
331 dwId = dwId; // prevents warning in "ship" build.
332 Assert(dwId == pControl->wId);
333 }
src/samples/thmviewer/precomp.h
+1
@@ -28,6 +28,7 @@
28 #include "shelutil.h"
29 #include "strutil.h"
30 #include "thmutil.h"
31 +#include "wndutil.h"
32
33 #include "resource.h"
34
src/samples/thmviewer/thmviewer.cpp
+25 -12
@@ -390,6 +390,12 @@ static void OnThemeLoadError(
390 LPWSTR* psczErrors = NULL;
391 UINT cErrors = 0;
392 TVINSERTSTRUCTW tvi = { };
393 + const THEME_CONTROL* pTreeControl = NULL;
394 +
395 + if (!ThemeControlExistsById(pTheme, THMVWR_CONTROL_TREE, &pTreeControl))
396 + {
397 + ExitWithRootFailure(hr, E_INVALIDSTATE, "THMVWR_CONTROL_TREE control doesn't exist.");
398 + }
399
400 // Add the application node.
401 tvi.hParent = NULL;
@@ -397,7 +403,7 @@ static void OnThemeLoadError(
403 tvi.item.mask = TVIF_TEXT | TVIF_PARAM;
404 tvi.item.lParam = 0;
405 tvi.item.pszText = L"Failed to load theme.";
400 - tvi.hParent = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
406 + tvi.hParent = reinterpret_cast<HTREEITEM>(::SendMessage(pTreeControl->hWnd, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
407
408 if (!vsczThemeLoadErrors)
409 {
@@ -405,13 +411,13 @@ static void OnThemeLoadError(
411 ExitOnFailure(hr, "Failed to format error message.");
412
413 tvi.item.pszText = sczMessage;
408 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
414 + ::SendMessage(pTreeControl->hWnd, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
415
416 hr = StrAllocFromError(&sczMessage, hrFailure, NULL);
417 ExitOnFailure(hr, "Failed to format error message text.");
418
419 tvi.item.pszText = sczMessage;
414 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
420 + ::SendMessage(pTreeControl->hWnd, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
421 }
422 else
423 {
@@ -421,11 +427,11 @@ static void OnThemeLoadError(
427 for (DWORD i = 0; i < cErrors; ++i)
428 {
429 tvi.item.pszText = psczErrors[i];
424 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
430 + ::SendMessage(pTreeControl->hWnd, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
431 }
432 }
433
428 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(tvi.hParent));
434 + ::SendMessage(pTreeControl->hWnd, TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(tvi.hParent));
435
436 LExit:
437 ReleaseStr(sczMessage);
@@ -439,6 +445,7 @@ static void OnNewTheme(
445 __in HANDLE_THEME* pHandle
446 )
447 {
448 + const THEME_CONTROL* pTreeControl = NULL;
449 HANDLE_THEME* pOldHandle = reinterpret_cast<HANDLE_THEME*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
450 THEME* pNewTheme = pHandle->pTheme;
451
@@ -460,17 +467,23 @@ static void OnNewTheme(
467
468 ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pHandle));
469
470 + if (!ThemeControlExistsById(pTheme, THMVWR_CONTROL_TREE, &pTreeControl))
471 + {
472 + TraceError(E_INVALIDSTATE, "Tree control doesn't exist.");
473 + return;
474 + }
475 +
476 // Remember the currently selected item by name so we can try to automatically select it later.
477 // Otherwise, the user would see their window destroyed after every save of their theme file and
478 // have to click to get the window back.
479 item.mask = TVIF_TEXT;
480 item.pszText = wzSelectedPage;
481 item.cchTextMax = countof(wzSelectedPage);
469 - item.hItem = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_GETNEXTITEM, TVGN_CARET, NULL));
470 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_GETITEM, 0, reinterpret_cast<LPARAM>(&item));
482 + item.hItem = reinterpret_cast<HTREEITEM>(::SendMessage(pTreeControl->hWnd, TVM_GETNEXTITEM, TVGN_CARET, NULL));
483 + ::SendMessage(pTreeControl->hWnd, TVM_GETITEM, 0, reinterpret_cast<LPARAM>(&item));
484
485 // Remove the previous items in the tree.
473 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_DELETEITEM, 0, reinterpret_cast<LPARAM>(TVI_ROOT));
486 + ::SendMessage(pTreeControl->hWnd, TVM_DELETEITEM, 0, reinterpret_cast<LPARAM>(TVI_ROOT));
487
488 // Add the application node.
489 tvi.hParent = NULL;
@@ -480,7 +493,7 @@ static void OnNewTheme(
493 tvi.item.pszText = pHandle && pHandle->pTheme && pHandle->pTheme->sczCaption ? pHandle->pTheme->sczCaption : L"Window";
494
495 // Add the pages.
483 - tvi.hParent = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
496 + tvi.hParent = reinterpret_cast<HTREEITEM>(::SendMessage(pTreeControl->hWnd, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
497 tvi.hInsertAfter = TVI_SORT;
498 for (DWORD i = 0; i < pNewTheme->cPages; ++i)
499 {
@@ -490,7 +503,7 @@ static void OnNewTheme(
503 tvi.item.pszText = pPage->sczName;
504 tvi.item.lParam = i + 1; //prgdwPageIds[i]; - TODO: do the right thing here by calling ThemeGetPageIds(), should not assume we know how the page ids will be calculated.
505
493 - HTREEITEM hti = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
506 + HTREEITEM hti = reinterpret_cast<HTREEITEM>(::SendMessage(pTreeControl->hWnd, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
507 if (*wzSelectedPage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pPage->sczName, -1, wzSelectedPage, -1))
508 {
509 htiSelected = hti;
@@ -503,10 +516,10 @@ static void OnNewTheme(
516 htiSelected = tvi.hParent;
517 }
518
506 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(tvi.hParent));
519 + ::SendMessage(pTreeControl->hWnd, TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(tvi.hParent));
520 if (htiSelected)
521 {
509 - ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_SELECTITEM, TVGN_CARET, reinterpret_cast<LPARAM>(htiSelected));
522 + ::SendMessage(pTreeControl->hWnd, TVM_SELECTITEM, TVGN_CARET, reinterpret_cast<LPARAM>(htiSelected));
523 }
524 }
525
src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
+8 -3
@@ -365,18 +365,23 @@ private:
365
366 void UpdateProgressBarProgress()
367 {
368 + const THEME_CONTROL* pControlProgressbarImage = NULL;
369 + const THEME_CONTROL* pControlProgressbarStandard = NULL;
370 static DWORD dwProgress = 0;
371 DWORD dwCurrent = dwProgress < 100 ? dwProgress : 200 - dwProgress;
372
373 + ThemeControlExistsById(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, &pControlProgressbarImage);
374 + ThemeControlExistsById(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD, &pControlProgressbarStandard);
375 +
376 if (0 == dwProgress || 100 == dwProgress)
377 {
373 - ThemeSetProgressControlColor(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, 100 == dwProgress ? 1 : 0);
378 + ThemeSetProgressControlColor(pControlProgressbarImage, 100 == dwProgress ? 1 : 0);
379 }
380
381 dwProgress = (dwProgress + 10) % 200;
382
378 - ThemeSetProgressControl(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_IMAGE, dwCurrent);
379 - ThemeSetProgressControl(m_pBafTheme, BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD, dwCurrent);
383 + ThemeSetProgressControl(pControlProgressbarImage, dwCurrent);
384 + ThemeSetProgressControl(pControlProgressbarStandard, dwCurrent);
385 }
386
387 public: