Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2323 lines
74 KiB

  1. /*****************************************************************************\
  2. FILE: BaseAppearPg.cpp
  3. DESCRIPTION:
  4. This code will display a "Appearances" tab in the
  5. "Display Properties" dialog (the base dialog, not the advanced dlg).
  6. ??????? ?/??/1993 Created
  7. BryanSt 3/23/2000 Updated and Converted to C++
  8. Copyright (C) Microsoft Corp 1993-2000. All rights reserved.
  9. \*****************************************************************************/
  10. #include "priv.h"
  11. #include "BaseAppearPg.h"
  12. #include "AdvAppearPg.h"
  13. #include "CoverWnd.h"
  14. #include "AppScheme.h"
  15. #include "AdvDlg.h"
  16. #include "fontfix.h"
  17. //============================================================================================================
  18. // *** Globals ***
  19. //============================================================================================================
  20. const static DWORD FAR aBaseAppearanceHelpIds[] =
  21. {
  22. IDC_APPG_APPEARPREVIEW, IDH_DISPLAY_APPEARANCE_PREVIEW,
  23. IDC_APPG_LOOKFEEL, IDH_DISPLAY_APPEARANCE_LOOKFEEL,
  24. IDC_APPG_LOOKFEEL_LABLE, IDH_DISPLAY_APPEARANCE_LOOKFEEL,
  25. IDC_APPG_COLORSCHEME_LABLE, IDH_DISPLAY_APPEARANCE_COLORSCHEME,
  26. IDC_APPG_COLORSCHEME, IDH_DISPLAY_APPEARANCE_COLORSCHEME,
  27. IDC_APPG_WNDSIZE_LABLE, IDH_DISPLAY_APPEARANCE_WNDSIZE,
  28. IDC_APPG_WNDSIZE, IDH_DISPLAY_APPEARANCE_WNDSIZE,
  29. IDC_APPG_EFFECTS, IDH_DISPLAY_APPEARANCE_EFFECTS,
  30. IDC_APPG_ADVANCED, IDH_DISPLAY_APPEARANCE_ADVANCED,
  31. 0, 0
  32. };
  33. #define SZ_HELPFILE_BASEAPPEARANCE TEXT("display.hlp")
  34. // EnableApplyButton() fails in WM_INITDIALOG so we need to do it later.
  35. #define WMUSER_DELAYENABLEAPPLY (WM_USER + 1)
  36. #define DelayEnableApplyButton(hDlg) PostMessage(hDlg, WMUSER_DELAYENABLEAPPLY, 0, 0)
  37. //===========================
  38. // *** Class Internals & Helpers ***
  39. //===========================
  40. #ifdef DEBUG
  41. void _TestFault(void)
  42. {
  43. DWORD dwTemp = 3;
  44. DWORD * pdwDummy = NULL; // This is NULL in order that it causes a fault.
  45. for (int nIndex = 0; nIndex < 1000000; nIndex++)
  46. {
  47. // This will definitely fault sooner or later.
  48. dwTemp += pdwDummy[nIndex];
  49. }
  50. }
  51. #endif // DEBUG
  52. BOOL CBaseAppearancePage::_IsDirty(void)
  53. {
  54. BOOL fIsDirty = m_advDlgState.dwChanged;
  55. if (m_fIsDirty || // We need to check this because we may have gotten dirty from another page before our UI was displayed.
  56. (ComboBox_GetCurSel(m_hwndSchemeDropDown) != m_nSelectedScheme) ||
  57. (ComboBox_GetCurSel(m_hwndStyleDropDown) != m_nSelectedStyle) ||
  58. (ComboBox_GetCurSel(m_hwndSizeDropDown) != m_nSelectedSize) ||
  59. (m_nNewDPI != m_nAppliedDPI))
  60. {
  61. fIsDirty = TRUE;
  62. }
  63. return fIsDirty;
  64. }
  65. INT_PTR CALLBACK CBaseAppearancePage::BaseAppearanceDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  66. {
  67. CBaseAppearancePage * pThis = (CBaseAppearancePage *)GetWindowLongPtr(hDlg, DWLP_USER);
  68. if (WM_INITDIALOG == wMsg)
  69. {
  70. PROPSHEETPAGE * pPropSheetPage = (PROPSHEETPAGE *) lParam;
  71. if (pPropSheetPage)
  72. {
  73. SetWindowLongPtr(hDlg, DWLP_USER, pPropSheetPage->lParam);
  74. pThis = (CBaseAppearancePage *)pPropSheetPage->lParam;
  75. }
  76. }
  77. if (pThis)
  78. return pThis->_BaseAppearanceDlgProc(hDlg, wMsg, wParam, lParam);
  79. return DefWindowProc(hDlg, wMsg, wParam, lParam);
  80. }
  81. //============================================================================================================
  82. // *** Dialog Functions ***
  83. //============================================================================================================
  84. HRESULT CBaseAppearancePage::_OnAdvancedOptions(HWND hDlg)
  85. {
  86. HRESULT hr = E_FAIL;
  87. IAdvancedDialog * pAdvAppearDialog;
  88. hr = GetAdvancedDialog(&pAdvAppearDialog);
  89. if (SUCCEEDED(hr))
  90. {
  91. BOOL fEnableApply = FALSE;
  92. IUnknown_SetSite(pAdvAppearDialog, SAFECAST(this, IObjectWithSite *));
  93. hr = pAdvAppearDialog->DisplayAdvancedDialog(hDlg, SAFECAST(this, IPropertyBag *), &fEnableApply);
  94. IUnknown_SetSite(pAdvAppearDialog, NULL);
  95. if (SUCCEEDED(hr) && fEnableApply)
  96. {
  97. EnableApplyButton(hDlg);
  98. // We pass TRUE because we want to switch to Custom if:
  99. // 1) visual styles are off, and 2) some of the system metrics changed. Then we need to update the previews.
  100. _UpdatePreview(TRUE);
  101. }
  102. pAdvAppearDialog->Release();
  103. }
  104. return hr;
  105. }
  106. HRESULT CBaseAppearancePage::_OnEffectsOptions(HWND hDlg)
  107. {
  108. HRESULT hr = E_FAIL;
  109. if (_punkSite)
  110. {
  111. IThemeUIPages * pThemesUIPages;
  112. // Let's get the Effects base page.
  113. hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemesUIPages));
  114. if (SUCCEEDED(hr))
  115. {
  116. IEnumUnknown * pEnumUnknown;
  117. hr = pThemesUIPages->GetBasePagesEnum(&pEnumUnknown);
  118. if (SUCCEEDED(hr))
  119. {
  120. IUnknown * punk;
  121. hr = IEnumUnknown_FindCLSID(pEnumUnknown, PPID_Effects, &punk);
  122. if (SUCCEEDED(hr))
  123. {
  124. IBasePropPage * pEffects;
  125. hr = punk->QueryInterface(IID_PPV_ARG(IBasePropPage, &pEffects));
  126. if (SUCCEEDED(hr))
  127. {
  128. IAdvancedDialog * pEffectsDialog;
  129. hr = pEffects->GetAdvancedDialog(&pEffectsDialog);
  130. if (SUCCEEDED(hr))
  131. {
  132. IPropertyBag * pEffectsBag;
  133. hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, &pEffectsBag));
  134. if (SUCCEEDED(hr))
  135. {
  136. BOOL fEnableApply = FALSE;
  137. IUnknown_SetSite(pEffectsDialog, SAFECAST(this, IObjectWithSite *));
  138. hr = pEffectsDialog->DisplayAdvancedDialog(hDlg, pEffectsBag, &fEnableApply);
  139. IUnknown_SetSite(pEffectsDialog, NULL);
  140. if (SUCCEEDED(hr) && fEnableApply)
  141. {
  142. EnableApplyButton(hDlg);
  143. // We pass TRUE because we want to switch to Custom if:
  144. // 1) visual styles are off, and 2) some of the system metrics changed. Then we need to update the previews.
  145. _UpdatePreview(TRUE);
  146. }
  147. pEffectsBag->Release();
  148. }
  149. pEffectsDialog->Release();
  150. }
  151. pEffects->Release();
  152. }
  153. punk->Release();
  154. }
  155. pEnumUnknown->Release();
  156. }
  157. pThemesUIPages->Release();
  158. }
  159. }
  160. return hr;
  161. }
  162. HRESULT CBaseAppearancePage::_PopulateSchemeDropdown(void)
  163. {
  164. HRESULT hr = E_FAIL;
  165. _FreeSchemeDropdown(); // Purge any existing items.
  166. if (m_pThemeManager && m_pSelectedThemeScheme)
  167. {
  168. CComBSTR bstrSelectedName;
  169. m_nSelectedStyle = -1;
  170. // This will fail if someone deleted the .msstyles file.
  171. if (FAILED(m_pSelectedThemeScheme->get_DisplayName(&bstrSelectedName)))
  172. {
  173. bstrSelectedName = (BSTR)NULL;
  174. }
  175. VARIANT varIndex;
  176. #ifndef ENABLE_IA64_VISUALSTYLES
  177. // We use a different regkey for 64bit because we need to leave it off until the pre-Whistler
  178. // 64-bit release forks from the Whistler code base.
  179. BOOL fSkinsFeatureEnabled = SHRegGetBoolUSValue(SZ_REGKEY_APPEARANCE, SZ_REGVALUE_DISPLAYSCHEMES64, FALSE, FALSE);
  180. #else // ENABLE_IA64_VISUALSTYLES
  181. BOOL fSkinsFeatureEnabled = SHRegGetBoolUSValue(SZ_REGKEY_APPEARANCE, SZ_REGVALUE_DISPLAYSCHEMES, FALSE, TRUE);
  182. #endif // ENABLE_IA64_VISUALSTYLES
  183. varIndex.vt = VT_I4;
  184. varIndex.lVal = 0;
  185. do
  186. {
  187. hr = E_FAIL;
  188. // Only add the Skins if the policy doesn't lock it.
  189. if ((0 == varIndex.lVal) || fSkinsFeatureEnabled)
  190. {
  191. // Only add the Skins if the policy doesn't lock it.
  192. IThemeScheme * pThemeScheme;
  193. VARIANT varIndex2;
  194. varIndex2.vt = VT_I4;
  195. varIndex2.lVal = 0;
  196. // If a Theme can have more than one Scheme (Skin), then we should enum.
  197. hr = m_pThemeManager->get_schemeItem(varIndex, &pThemeScheme);
  198. if (SUCCEEDED(hr))
  199. {
  200. CComBSTR bstrDisplayName;
  201. hr = pThemeScheme->get_DisplayName(&bstrDisplayName);
  202. if (SUCCEEDED(hr) && m_hwndSchemeDropDown)
  203. {
  204. int nAddIndex = ComboBox_AddString(m_hwndSchemeDropDown, bstrDisplayName);
  205. if (-1 != nAddIndex)
  206. {
  207. ComboBox_SetItemData(m_hwndSchemeDropDown, nAddIndex, pThemeScheme);
  208. pThemeScheme = NULL;
  209. }
  210. else
  211. {
  212. hr = E_OUTOFMEMORY;
  213. }
  214. }
  215. ATOMICRELEASE(pThemeScheme);
  216. }
  217. }
  218. varIndex.lVal++;
  219. }
  220. while (SUCCEEDED(hr));
  221. //---- now that sorted list is built, find index of "bstrSelectedName" ----
  222. if (bstrSelectedName)
  223. {
  224. int nIndex = (int)ComboBox_FindStringExact(m_hwndSchemeDropDown, 0, bstrSelectedName);
  225. if (nIndex != -1) // got a match
  226. {
  227. ComboBox_SetCurSel(m_hwndSchemeDropDown, nIndex);
  228. m_nSelectedScheme = nIndex;
  229. }
  230. }
  231. hr = S_OK;
  232. }
  233. if (-1 == m_nSelectedScheme)
  234. {
  235. m_nSelectedScheme = 0;
  236. ComboBox_SetCurSel(m_hwndSchemeDropDown, m_nSelectedScheme);
  237. }
  238. return hr;
  239. }
  240. HRESULT CBaseAppearancePage::_FreeSchemeDropdown(void)
  241. {
  242. HRESULT hr = S_OK;
  243. LPARAM lParam;
  244. if (m_hwndSchemeDropDown)
  245. {
  246. do
  247. {
  248. lParam = ComboBox_GetItemData(m_hwndSchemeDropDown, 0);
  249. if (CB_ERR != lParam)
  250. {
  251. IThemeScheme * pThemeScheme = (IThemeScheme *) lParam;
  252. ATOMICRELEASE(pThemeScheme);
  253. ComboBox_DeleteString(m_hwndSchemeDropDown, 0);
  254. }
  255. }
  256. while (CB_ERR != lParam);
  257. }
  258. return hr;
  259. }
  260. HRESULT CBaseAppearancePage::_PopulateStyleDropdown(void)
  261. {
  262. HRESULT hr = E_FAIL;
  263. _FreeStyleDropdown(); // Purge any existing items.
  264. if (m_pSelectedStyle)
  265. {
  266. CComBSTR bstrSelectedName;
  267. m_nSelectedStyle = -1;
  268. hr = m_pSelectedStyle->get_DisplayName(&bstrSelectedName);
  269. if (SUCCEEDED(hr))
  270. {
  271. VARIANT varIndex;
  272. varIndex.vt = VT_I4;
  273. varIndex.lVal = 0;
  274. do
  275. {
  276. // Only add the Skins if the policy doesn't lock it.
  277. IThemeStyle * pThemeStyle;
  278. hr = m_pSelectedThemeScheme->get_item(varIndex, &pThemeStyle);
  279. if (SUCCEEDED(hr))
  280. {
  281. CComBSTR bstrDisplayName;
  282. hr = pThemeStyle->get_DisplayName(&bstrDisplayName);
  283. if (SUCCEEDED(hr) && m_hwndSchemeDropDown)
  284. {
  285. int nAddIndex = ComboBox_AddString(m_hwndStyleDropDown, bstrDisplayName);
  286. if (-1 != nAddIndex)
  287. {
  288. ComboBox_SetItemData(m_hwndStyleDropDown, nAddIndex, pThemeStyle);
  289. pThemeStyle = NULL;
  290. }
  291. else
  292. {
  293. hr = E_OUTOFMEMORY;
  294. }
  295. }
  296. ATOMICRELEASE(pThemeStyle);
  297. }
  298. varIndex.lVal++;
  299. }
  300. while (SUCCEEDED(hr));
  301. //---- now that sorted list is built, find index of "bstrSelectedName" ----
  302. if (bstrSelectedName)
  303. {
  304. int nIndex = (int)ComboBox_FindStringExact(m_hwndStyleDropDown, 0, bstrSelectedName);
  305. if (nIndex != -1) // got a match
  306. {
  307. ComboBox_SetCurSel(m_hwndStyleDropDown, nIndex);
  308. m_nSelectedStyle = nIndex;
  309. }
  310. }
  311. hr = S_OK;
  312. }
  313. }
  314. if (-1 == m_nSelectedStyle)
  315. {
  316. m_nSelectedStyle = 0;
  317. ComboBox_SetCurSel(m_hwndStyleDropDown, m_nSelectedStyle);
  318. }
  319. return hr;
  320. }
  321. HRESULT CBaseAppearancePage::_FreeStyleDropdown(void)
  322. {
  323. HRESULT hr = S_OK;
  324. LPARAM lParam;
  325. if (m_hwndStyleDropDown)
  326. {
  327. do
  328. {
  329. lParam = ComboBox_GetItemData(m_hwndStyleDropDown, 0);
  330. if (CB_ERR != lParam)
  331. {
  332. IThemeStyle * pThemeStyle = (IThemeStyle *) lParam;
  333. ATOMICRELEASE(pThemeStyle);
  334. ComboBox_DeleteString(m_hwndStyleDropDown, 0);
  335. }
  336. }
  337. while (CB_ERR != lParam);
  338. }
  339. return hr;
  340. }
  341. HRESULT CBaseAppearancePage::_PopulateSizeDropdown(void)
  342. {
  343. HRESULT hr = E_FAIL;
  344. _FreeSizeDropdown(); // Purge any existing items.
  345. if (m_pSelectedSize)
  346. {
  347. CComBSTR bstrSelectedName;
  348. m_nSelectedSize = -1;
  349. hr = m_pSelectedSize->get_DisplayName(&bstrSelectedName);
  350. if (SUCCEEDED(hr))
  351. {
  352. VARIANT varIndex;
  353. varIndex.vt = VT_I4;
  354. varIndex.lVal = 0;
  355. do
  356. {
  357. // Only add the Skins if the policy doesn't lock it.
  358. IThemeSize * pThemeSize;
  359. hr = m_pSelectedStyle->get_item(varIndex, &pThemeSize);
  360. if (SUCCEEDED(hr))
  361. {
  362. CComBSTR bstrDisplayName;
  363. hr = pThemeSize->get_DisplayName(&bstrDisplayName);
  364. if (SUCCEEDED(hr) && m_hwndSchemeDropDown)
  365. {
  366. int nAddIndex = ComboBox_AddString(m_hwndSizeDropDown, bstrDisplayName);
  367. if (-1 != nAddIndex)
  368. {
  369. ComboBox_SetItemData(m_hwndSizeDropDown, nAddIndex, pThemeSize);
  370. pThemeSize = NULL;
  371. }
  372. else
  373. {
  374. hr = E_OUTOFMEMORY;
  375. }
  376. }
  377. ATOMICRELEASE(pThemeSize);
  378. }
  379. varIndex.lVal++;
  380. }
  381. while (SUCCEEDED(hr));
  382. //---- now that sorted list is built, find index of "bstrSelectedName" ----
  383. if (bstrSelectedName)
  384. {
  385. int nIndex = (int)ComboBox_FindStringExact(m_hwndSizeDropDown, 0, bstrSelectedName);
  386. if (nIndex != -1) // got a match
  387. {
  388. ComboBox_SetCurSel(m_hwndSizeDropDown, nIndex);
  389. m_nSelectedSize = nIndex;
  390. }
  391. }
  392. hr = S_OK;
  393. }
  394. }
  395. if (-1 == m_nSelectedSize)
  396. {
  397. m_nSelectedSize = 0;
  398. ComboBox_SetCurSel(m_hwndSizeDropDown, m_nSelectedSize);
  399. }
  400. return hr;
  401. }
  402. HRESULT CBaseAppearancePage::_FreeSizeDropdown(void)
  403. {
  404. HRESULT hr = S_OK;
  405. LPARAM lParam;
  406. if (m_hwndSizeDropDown)
  407. {
  408. do
  409. {
  410. lParam = ComboBox_GetItemData(m_hwndSizeDropDown, 0);
  411. if (CB_ERR != lParam)
  412. {
  413. IThemeSize * pThemeSize = (IThemeSize *) lParam;
  414. ATOMICRELEASE(pThemeSize);
  415. ComboBox_DeleteString(m_hwndSizeDropDown, 0);
  416. }
  417. }
  418. while (CB_ERR != lParam);
  419. }
  420. return hr;
  421. }
  422. HRESULT CBaseAppearancePage::_OnInitAppearanceDlg(HWND hDlg)
  423. {
  424. HRESULT hr = S_OK;
  425. _OnInitData();
  426. _hwnd = hDlg;
  427. #ifdef DEBUG
  428. if (!SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\TaskManager"), TEXT("Enable Test Faults"), FALSE, FALSE))
  429. {
  430. // Disable the feature.
  431. DestroyWindow(GetDlgItem(hDlg, IDC_APPG_TESTFAULT));
  432. }
  433. #endif // DEBUG
  434. m_hwndSchemeDropDown = GetDlgItem(hDlg, IDC_APPG_LOOKFEEL);
  435. m_hwndStyleDropDown = GetDlgItem(hDlg, IDC_APPG_COLORSCHEME);
  436. m_hwndSizeDropDown = GetDlgItem(hDlg, IDC_APPG_WNDSIZE);
  437. hr = _OnInitData();
  438. if (SUCCEEDED(hr))
  439. {
  440. hr = _PopulateSchemeDropdown();
  441. if (SUCCEEDED(hr))
  442. {
  443. hr = _PopulateStyleDropdown();
  444. if (SUCCEEDED(hr))
  445. {
  446. hr = _PopulateSizeDropdown();
  447. if (SUCCEEDED(hr))
  448. {
  449. hr = _UpdatePreview(FALSE);
  450. }
  451. }
  452. }
  453. }
  454. TCHAR szTemp[MAX_PATH];
  455. DWORD dwType;
  456. DWORD cbSize = sizeof(szTemp);
  457. if (SHRestricted(REST_NOVISUALSTYLECHOICE) ||
  458. (ERROR_SUCCESS == SHRegGetUSValue(SZ_REGKEY_POLICIES_SYSTEM, SZ_REGVALUE_POLICY_SETVISUALSTYLE, &dwType, (void *) szTemp, &cbSize, FALSE, NULL, 0)))
  459. {
  460. EnableWindow(GetDlgItem(hDlg, IDC_APPG_LOOKFEEL_LABLE), FALSE);
  461. EnableWindow(GetDlgItem(hDlg, IDC_APPG_LOOKFEEL), FALSE);
  462. m_fLockVisualStylePolicyEnabled = TRUE;
  463. LogStatus("POLICY ENABLED: Either NoVisualChoice or SetVisualStyle policy is set, locking the visual style selection.");
  464. }
  465. if (SHRestricted(REST_NOCOLORCHOICE))
  466. {
  467. EnableWindow(GetDlgItem(hDlg, IDC_APPG_COLORSCHEME_LABLE), FALSE);
  468. EnableWindow(GetDlgItem(hDlg, IDC_APPG_COLORSCHEME), FALSE);
  469. }
  470. if (SHRestricted(REST_NOSIZECHOICE))
  471. {
  472. EnableWindow(GetDlgItem(hDlg, IDC_APPG_WNDSIZE_LABLE), FALSE);
  473. EnableWindow(GetDlgItem(hDlg, IDC_APPG_WNDSIZE), FALSE);
  474. }
  475. if (m_pszLoadMSTheme)
  476. {
  477. hr = _LoadVisaulStyleFile(m_pszLoadMSTheme);
  478. }
  479. _EnableAdvancedButton();
  480. return S_OK;
  481. }
  482. HRESULT CBaseAppearancePage::_OnInitData(void)
  483. {
  484. HRESULT hr = S_OK;
  485. if (!m_fInitialized)
  486. {
  487. // Load DPI Value
  488. HDC hdc = GetDC(NULL);
  489. int nDefault = GetDeviceCaps(hdc, LOGPIXELSY); // Get the default value;
  490. ReleaseDC(NULL, hdc);
  491. m_nAppliedDPI = HrRegGetDWORD(HKEY_CURRENT_USER, SZ_WINDOWMETRICS, SZ_APPLIEDDPI, DPI_PERSISTED);
  492. if (!m_nAppliedDPI)
  493. {
  494. m_nAppliedDPI = nDefault;
  495. }
  496. m_nNewDPI = m_nAppliedDPI;
  497. LogStatus("DPI: SYSTEMMETRICS currently at %d DPI CBaseAppearancePage::_OnInitData\r\n", m_nAppliedDPI);
  498. // Load everything else.
  499. AssertMsg((NULL != _punkSite), TEXT("I need my punkSite!!!"));
  500. if (!m_pThemeManager && _punkSite)
  501. {
  502. hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeManager, &m_pThemeManager));
  503. }
  504. if (SUCCEEDED(hr) && !m_pSelectedThemeScheme)
  505. {
  506. hr = m_pThemeManager->get_SelectedScheme(&m_pSelectedThemeScheme);
  507. if (SUCCEEDED(hr) && !m_pSelectedStyle)
  508. {
  509. hr = m_pSelectedThemeScheme->get_SelectedStyle(&m_pSelectedStyle);
  510. if (SUCCEEDED(hr) && !m_pSelectedSize)
  511. {
  512. hr = m_pSelectedStyle->get_SelectedSize(&m_pSelectedSize);
  513. if (SUCCEEDED(hr))
  514. {
  515. // We want to load whatever system metrics the users have now.
  516. hr = _LoadLiveSettings(SZ_SAVEGROUP_ALL);
  517. }
  518. }
  519. }
  520. }
  521. m_fInitialized = TRUE;
  522. }
  523. return hr;
  524. }
  525. HRESULT CBaseAppearancePage::_OnDestroy(HWND hDlg)
  526. {
  527. _FreeSchemeDropdown();
  528. _FreeStyleDropdown();
  529. _FreeSizeDropdown();
  530. return S_OK;
  531. }
  532. HRESULT CBaseAppearancePage::_EnableAdvancedButton(void)
  533. {
  534. HRESULT hr = S_OK;
  535. #ifdef FEATURE_ENABLE_ADVANCED_WITH_SKINSON
  536. BOOL fTurnOn = TRUE;
  537. #else // FEATURE_ENABLE_ADVANCED_WITH_SKINSON
  538. BOOL fTurnOn = (m_pSelectedThemeScheme ? IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme) : FALSE);
  539. if (SHRegGetBoolUSValue(SZ_REGKEY_APPEARANCE, L"AlwaysAllowAdvanced", FALSE, FALSE))
  540. {
  541. fTurnOn = TRUE;
  542. }
  543. #endif // FEATURE_ENABLE_ADVANCED_WITH_SKINSON
  544. EnableWindow(GetDlgItem(_hwnd, IDC_APPG_ADVANCED), fTurnOn);
  545. return hr;
  546. }
  547. HRESULT CBaseAppearancePage::_UpdatePreview(IN BOOL fUpdateThemePage)
  548. {
  549. HRESULT hr = S_OK;
  550. if (!m_pThemePreview)
  551. {
  552. // We won't execute the following code if our dialog hasn't
  553. // been created yet. That's fine because the preview will
  554. // obtain the correct state when we first initialize.
  555. if (_punkSite && m_hwndSchemeDropDown)
  556. {
  557. hr = CThemePreview_CreateInstance(NULL, IID_PPV_ARG(IThemePreview, &m_pThemePreview));
  558. if (SUCCEEDED(hr))
  559. {
  560. IPropertyBag * pPropertyBag;
  561. hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  562. if (SUCCEEDED(hr))
  563. {
  564. HWND hwndParent = GetParent(m_hwndSchemeDropDown);
  565. HWND hwndPlaceHolder = GetDlgItem(hwndParent, IDC_APPG_APPEARPREVIEW);
  566. RECT rcPreview;
  567. AssertMsg((NULL != m_hwndSchemeDropDown), TEXT("We should have this window at this point. -BryanSt"));
  568. GetClientRect(hwndPlaceHolder, &rcPreview);
  569. MapWindowPoints(hwndPlaceHolder, hwndParent, (LPPOINT)&rcPreview, 2);
  570. if (SUCCEEDED(m_pThemePreview->CreatePreview(hwndParent, TMPREV_SHOWVS, WS_VISIBLE | WS_CHILDWINDOW | WS_BORDER | WS_OVERLAPPED, WS_EX_CLIENTEDGE, rcPreview.left, rcPreview.top, RECTWIDTH(rcPreview), RECTHEIGHT(rcPreview), pPropertyBag, IDC_APPG_APPEARPREVIEW)))
  571. {
  572. // If we succeeded, remove the dummy window.
  573. DestroyWindow(hwndPlaceHolder);
  574. hr = SHPropertyBag_WritePunk(pPropertyBag, SZ_PBPROP_PREVIEW3, m_pThemePreview);
  575. if (SUCCEEDED(hr) && fUpdateThemePage)
  576. {
  577. // Tell the theme that we have customized the values.
  578. hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0);
  579. }
  580. }
  581. pPropertyBag->Release();
  582. }
  583. }
  584. }
  585. }
  586. else if (_punkSite)
  587. {
  588. IThemeUIPages * pThemeUIPages;
  589. hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUIPages));
  590. if (SUCCEEDED(hr))
  591. {
  592. hr = pThemeUIPages->UpdatePreview(0);
  593. }
  594. pThemeUIPages->Release();
  595. }
  596. if (_punkSite && fUpdateThemePage)
  597. {
  598. IPropertyBag * pPropertyBag;
  599. hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  600. if (SUCCEEDED(hr))
  601. {
  602. // Tell the theme that we have customized the values.
  603. hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0);
  604. pPropertyBag->Release();
  605. }
  606. }
  607. return hr;
  608. }
  609. INT_PTR CBaseAppearancePage::_OnCommand(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  610. {
  611. BOOL fHandled = 1; // Not handled (WM_COMMAND seems to be different)
  612. WORD idCtrl = GET_WM_COMMAND_ID(wParam, lParam);
  613. switch (idCtrl)
  614. {
  615. case IDC_APPG_COLORSCHEME:
  616. if(HIWORD(wParam) == CBN_SELCHANGE)
  617. {
  618. _OnStyleChange(hDlg);
  619. }
  620. break;
  621. case IDC_APPG_WNDSIZE:
  622. if(HIWORD(wParam) == CBN_SELCHANGE)
  623. {
  624. _OnSizeChange(hDlg);
  625. }
  626. break;
  627. case IDC_APPG_LOOKFEEL:
  628. if(HIWORD(wParam) == CBN_SELCHANGE)
  629. {
  630. _OnSchemeChange(hDlg, TRUE); // Display Error dialogs since the user is picking the visual style.
  631. }
  632. break;
  633. case IDC_APPG_EFFECTS: // This is the Effects button.
  634. _OnEffectsOptions(hDlg);
  635. break;
  636. case IDC_APPG_ADVANCED: // This is the Advanced button.
  637. _OnAdvancedOptions(hDlg);
  638. break;
  639. #ifdef DEBUG
  640. case IDC_APPG_TESTFAULT:
  641. _TestFault();
  642. break;
  643. #endif // DEBUG
  644. default:
  645. break;
  646. }
  647. return fHandled;
  648. }
  649. HRESULT CBaseAppearancePage::_OnSchemeChange(HWND hDlg, BOOL fDisplayErrors)
  650. {
  651. HRESULT hr = E_FAIL;
  652. int nIndex = ComboBox_GetCurSel(m_hwndSchemeDropDown);
  653. BOOL fPreviousSelectionIsVS = (!IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme));
  654. if (-1 == nIndex)
  655. {
  656. nIndex = 0; // The caller may NOT select nothing.
  657. }
  658. IThemeScheme * pThemeScheme = (IThemeScheme *) ComboBox_GetItemData(m_hwndSchemeDropDown, nIndex);
  659. m_fLoadedAdvState = FALSE; // Forget the state we previously loaded.
  660. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  661. PropSheet_Changed(GetParent(hDlg), hDlg);
  662. if (pThemeScheme)
  663. {
  664. IUnknown_Set((IUnknown **)&m_pSelectedThemeScheme, pThemeScheme);
  665. }
  666. hr = _SetScheme(TRUE, TRUE, fPreviousSelectionIsVS);
  667. if (FAILED(hr))
  668. {
  669. if (fDisplayErrors)
  670. {
  671. // Displaying an error dialog when the visual style is selected is very important because
  672. // this is where we catch parse errors in the visual style.
  673. hr = DisplayThemeErrorDialog(hDlg, hr, IDS_ERROR_TITLE_LOAD_MSSTYLES_FAIL, IDS_ERROR_LOAD_MSSTYLES_FAIL);
  674. }
  675. }
  676. _EnableAdvancedButton();
  677. return hr;
  678. }
  679. HRESULT CBaseAppearancePage::_OutsideSetScheme(BSTR bstrScheme)
  680. {
  681. HRESULT hr = E_ACCESSDENIED;
  682. if (!m_fLockVisualStylePolicyEnabled)
  683. {
  684. hr = E_FAIL;
  685. BOOL fPreviousSelectionIsVS = !IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme);
  686. ATOMICRELEASE(m_pSelectedThemeScheme);
  687. if (bstrScheme && bstrScheme[0])
  688. {
  689. BOOL fVisualStylesSupported = (QueryThemeServicesWrap() & QTS_AVAILABLE);
  690. LogStatus("QueryThemeServices() returned %hs. In CBaseAppearancePage::_OutsideSetScheme\r\n", (fVisualStylesSupported ? "TRUE" : "FALSE"));
  691. // Do not load a visual style of themes do not work.
  692. if (fVisualStylesSupported)
  693. {
  694. if (PathFileExists(bstrScheme))
  695. {
  696. hr = CSkinScheme_CreateInstance(bstrScheme, &m_pSelectedThemeScheme);
  697. }
  698. else
  699. {
  700. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); // Them the caller that the theme service was not running.
  701. }
  702. }
  703. else
  704. {
  705. hr = HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE); // Them the caller that the theme service was not running.
  706. }
  707. }
  708. else
  709. {
  710. hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &m_pSelectedThemeScheme));
  711. }
  712. if (SUCCEEDED(hr))
  713. {
  714. // If we are displaying UI, update it.
  715. if (m_hwndSchemeDropDown)
  716. {
  717. CComBSTR bstrSelectedName;
  718. m_fIsDirty = TRUE;
  719. hr = m_pSelectedThemeScheme->get_DisplayName(&bstrSelectedName);
  720. if (SUCCEEDED(hr))
  721. {
  722. int nIndex = ComboBox_FindString(m_hwndSchemeDropDown, 0, bstrSelectedName);
  723. ComboBox_SetCurSel(m_hwndSchemeDropDown, nIndex);
  724. }
  725. }
  726. if (SUCCEEDED(hr))
  727. {
  728. hr = _SetScheme(FALSE, FALSE, fPreviousSelectionIsVS);
  729. }
  730. }
  731. }
  732. return hr;
  733. }
  734. /*****************************************************************************\
  735. DESCRIPTION:
  736. The caller just loaded a new value into m_pSelectedThemeScheme. Now
  737. load good default values into m_pSelectedStyle and m_pSelectedSize.
  738. Then this is called, the UI may or may not be displayed. Either the user made a change in
  739. the dropdown in this tab or the Theme page is setting our values.
  740. PARAMETERS:
  741. fLoadSystemMetrics: If true, we load the system metrics from the scheme. If false,
  742. we simply select that as the name for the drop down when we let the caller
  743. push the system metrics into us.
  744. fLoadLiveSettings: When the user switches from Skin->NoSkin, do we want to
  745. load custom settings they had before they switched?
  746. \*****************************************************************************/
  747. HRESULT CBaseAppearancePage::_SetScheme(IN BOOL fLoadSystemMetrics, IN BOOL fLoadLiveSettings, IN BOOL fPreviousSelectionIsVS)
  748. {
  749. HRESULT hr = E_FAIL;
  750. if (m_pSelectedThemeScheme)
  751. {
  752. // Now that they choose a different VisualStyle (Scheme), we want to select the new Color Style
  753. // and Size in that Scheme.
  754. // will fall back to the first ColorStyle.
  755. CComBSTR bstrSelectedStyle;
  756. CComBSTR bstrSelectedSize;
  757. if (m_pSelectedStyle) // This will be empty if someone deletes the current .msstyles file.
  758. {
  759. hr = m_pSelectedStyle->get_DisplayName(&bstrSelectedStyle);
  760. }
  761. if (m_pSelectedSize)
  762. {
  763. hr = m_pSelectedSize->get_DisplayName(&bstrSelectedSize);
  764. }
  765. ATOMICRELEASE(m_pSelectedStyle);
  766. ATOMICRELEASE(m_pSelectedSize);
  767. CComVariant varNameBSTR(bstrSelectedStyle);
  768. // We prefer to get the ColorStyle with the same name as the previously selected one.
  769. hr = m_pSelectedThemeScheme->get_item(varNameBSTR, &m_pSelectedStyle);
  770. if (FAILED(hr))
  771. {
  772. // If that failed to return a value, then we will try to get the default ColorStyle.
  773. hr = m_pSelectedThemeScheme->get_SelectedStyle(&m_pSelectedStyle);
  774. if (FAILED(hr))
  775. {
  776. // If that failed then we will just pick the first ColorStyles. (Beggers can't be choosers)
  777. VARIANT varIndex;
  778. varIndex.vt = VT_I4;
  779. varIndex.lVal = 0;
  780. hr = m_pSelectedThemeScheme->get_item(varIndex, &m_pSelectedStyle);
  781. }
  782. }
  783. if (m_pSelectedStyle)
  784. {
  785. varNameBSTR = bstrSelectedSize;
  786. // Now we want to repeat this process with the size.
  787. // We prefer to get the ColorStyle with the same name as the previously selected one.
  788. hr = m_pSelectedStyle->get_item(varNameBSTR, &m_pSelectedSize);
  789. if (FAILED(hr))
  790. {
  791. // If that failed to return a value, then we will try to get the default ColorStyle.
  792. hr = m_pSelectedStyle->get_SelectedSize(&m_pSelectedSize);
  793. if (FAILED(hr))
  794. {
  795. // If that failed then we will just pick the first ColorStyles. (Beggers can't be choosers)
  796. VARIANT varIndex;
  797. varIndex.vt = VT_I4;
  798. varIndex.lVal = 0;
  799. hr = m_pSelectedStyle->get_item(varIndex, &m_pSelectedSize);
  800. }
  801. }
  802. }
  803. hr = _PopulateStyleDropdown();
  804. hr = _PopulateSizeDropdown();
  805. BOOL fStateLoaded = FALSE;
  806. BOOL fIsThemeActive = IsThemeActive();
  807. LogStatus("IsThemeActive() returned %hs. In CBaseAppearancePage::_SetScheme\r\n", (fIsThemeActive ? "TRUE" : "FALSE"));
  808. // If the user switched from a skin to "NoSkin", then we want to load the settings from the settings
  809. // chosen before the user chose the skin.
  810. if (fIsThemeActive && // Was a skin last applied?
  811. fLoadLiveSettings && // Do we want to load live settings?
  812. IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme) && // Is the new selection a "No Skin"?
  813. !m_fLoadedAdvState) // Have we not yet loaded these setting?
  814. {
  815. // We want to load the last set of customized settings....
  816. if (SUCCEEDED(_LoadLiveSettings(SZ_SAVEGROUP_NOSKIN)))
  817. {
  818. fStateLoaded = TRUE;
  819. }
  820. }
  821. // We don't want to load the state if the change came from the outside
  822. // because they will load the state themselves.
  823. if (fLoadSystemMetrics && !fStateLoaded)
  824. {
  825. hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
  826. if (SUCCEEDED(hr))
  827. {
  828. m_fLoadedAdvState = TRUE;
  829. }
  830. }
  831. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  832. if (SUCCEEDED(hr))
  833. {
  834. hr = _UpdatePreview(fLoadSystemMetrics);
  835. if (!fPreviousSelectionIsVS &&
  836. !IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme))
  837. {
  838. IPropertyBag * pEffectsBag;
  839. // Whenever we turn on a visual style and a visual style was previously off,
  840. // turn on "Menu Drop Shadows".
  841. if (SUCCEEDED(_GetPageByCLSID(&PPID_Effects, &pEffectsBag)))
  842. {
  843. SHPropertyBag_WriteBOOL(pEffectsBag, SZ_PBPROP_EFFECTS_MENUDROPSHADOWS, VARIANT_TRUE);
  844. pEffectsBag->Release();
  845. }
  846. }
  847. }
  848. }
  849. return hr;
  850. }
  851. HRESULT CBaseAppearancePage::_OnStyleChange(HWND hDlg)
  852. {
  853. int nIndex = ComboBox_GetCurSel(m_hwndStyleDropDown);
  854. m_fLoadedAdvState = FALSE; // Forget the state we previously loaded.
  855. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  856. PropSheet_Changed(GetParent(hDlg), hDlg);
  857. if (-1 == nIndex)
  858. {
  859. nIndex = 0; // The caller may NOT select nothing.
  860. }
  861. IThemeStyle * pThemeStyle = (IThemeStyle *) ComboBox_GetItemData(m_hwndStyleDropDown, nIndex);
  862. AssertMsg((NULL != pThemeStyle), TEXT("We need pThemeStyle"));
  863. if (pThemeStyle)
  864. {
  865. IUnknown_Set((IUnknown **)&m_pSelectedStyle, pThemeStyle);
  866. }
  867. return _SetStyle(TRUE);
  868. }
  869. HRESULT CBaseAppearancePage::_OutsideSetStyle(BSTR bstrStyle)
  870. {
  871. HRESULT hr = E_FAIL;
  872. AssertMsg((NULL != m_pSelectedThemeScheme), TEXT("We need m_pSelectedThemeScheme"));
  873. if (m_pSelectedThemeScheme)
  874. {
  875. IThemeStyle * pSelectedStyle;
  876. CComVariant varNameBSTR(bstrStyle);
  877. m_fIsDirty = TRUE;
  878. hr = m_pSelectedThemeScheme->get_item(varNameBSTR, &pSelectedStyle);
  879. if (SUCCEEDED(hr))
  880. {
  881. ATOMICRELEASE(m_pSelectedStyle);
  882. m_pSelectedStyle = pSelectedStyle;
  883. // If we are displaying UI, update it.
  884. if (m_hwndStyleDropDown)
  885. {
  886. CComBSTR bstrSelectedName;
  887. hr = m_pSelectedStyle->get_DisplayName(&bstrSelectedName);
  888. if (SUCCEEDED(hr))
  889. {
  890. int nIndex = ComboBox_FindString(m_hwndStyleDropDown, 0, bstrSelectedName);
  891. ComboBox_SetCurSel(m_hwndStyleDropDown, nIndex);
  892. }
  893. }
  894. hr = _SetStyle(FALSE);
  895. }
  896. }
  897. return hr;
  898. }
  899. HRESULT CBaseAppearancePage::_SetStyle(IN BOOL fUpdateThemePage)
  900. {
  901. HRESULT hr = E_FAIL;
  902. AssertMsg((m_pSelectedSize && m_pSelectedSize), TEXT("We need m_pSelectedSize && m_pSelectedSize"));
  903. if (m_pSelectedSize && m_pSelectedSize)
  904. {
  905. // Now that they choose a different style, we want to select the new size
  906. // in that style. We prefer to get the size with the same name but will
  907. // will fall back to the first style.
  908. CComBSTR bstrSelectedSize;
  909. hr = m_pSelectedSize->get_DisplayName(&bstrSelectedSize);
  910. ATOMICRELEASE(m_pSelectedSize);
  911. CComVariant varNameBSTR(bstrSelectedSize);
  912. hr = m_pSelectedStyle->get_item(varNameBSTR, &m_pSelectedSize);
  913. if (FAILED(hr))
  914. {
  915. VARIANT varIndex;
  916. varIndex.vt = VT_I4;
  917. varIndex.lVal = 0;
  918. hr = m_pSelectedStyle->get_item(varIndex, &m_pSelectedSize);
  919. }
  920. hr = _PopulateSizeDropdown();
  921. if (fUpdateThemePage && SUCCEEDED(SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI)))
  922. {
  923. m_fLoadedAdvState = TRUE;
  924. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  925. }
  926. if (SUCCEEDED(hr))
  927. {
  928. hr = _UpdatePreview(fUpdateThemePage);
  929. }
  930. }
  931. return hr;
  932. }
  933. HRESULT CBaseAppearancePage::_OnSizeChange(HWND hDlg)
  934. {
  935. int nIndex = ComboBox_GetCurSel(m_hwndSizeDropDown);
  936. PropSheet_Changed(GetParent(hDlg), hDlg);
  937. if (-1 == nIndex)
  938. {
  939. nIndex = 0; // The caller may NOT select nothing.
  940. }
  941. IThemeSize * pThemeSize = (IThemeSize *) ComboBox_GetItemData(m_hwndSizeDropDown, nIndex);
  942. AssertMsg((NULL != pThemeSize), TEXT("We need pThemeSize"));
  943. if (pThemeSize)
  944. {
  945. IUnknown_Set((IUnknown **)&m_pSelectedSize, pThemeSize);
  946. }
  947. return _SetSize(TRUE, TRUE);
  948. }
  949. HRESULT CBaseAppearancePage::_OutsideSetSize(BSTR bstrSize)
  950. {
  951. HRESULT hr = E_FAIL;
  952. AssertMsg((m_pSelectedThemeScheme && m_pSelectedStyle), TEXT("We need m_pSelectedThemeScheme && m_pSelectedStyle"));
  953. if (m_pSelectedThemeScheme && m_pSelectedStyle)
  954. {
  955. IThemeSize * pSelectedSize;
  956. CComVariant varNameBSTR(bstrSize);
  957. m_fIsDirty = TRUE;
  958. hr = m_pSelectedStyle->get_item(varNameBSTR, &pSelectedSize);
  959. if (SUCCEEDED(hr))
  960. {
  961. ATOMICRELEASE(m_pSelectedSize);
  962. m_pSelectedSize = pSelectedSize;
  963. // If we are displaying UI, update it.
  964. if (m_hwndSizeDropDown)
  965. {
  966. CComBSTR bstrSelectedName;
  967. hr = m_pSelectedSize->get_DisplayName(&bstrSelectedName);
  968. if (SUCCEEDED(hr))
  969. {
  970. int nIndex = ComboBox_FindString(m_hwndSizeDropDown, 0, bstrSelectedName);
  971. ComboBox_SetCurSel(m_hwndSizeDropDown, nIndex);
  972. }
  973. }
  974. hr = _SetSize(TRUE, FALSE);
  975. }
  976. }
  977. return hr;
  978. }
  979. HRESULT CBaseAppearancePage::_SetSize(IN BOOL fLoadSystemMetrics, IN BOOL fUpdateThemePage)
  980. {
  981. HRESULT hr = E_FAIL;
  982. AssertMsg((NULL != m_pSelectedSize), TEXT("We need m_pSelectedSize"));
  983. if (m_pSelectedSize)
  984. {
  985. hr = S_OK;
  986. // SystemMetricsAll_Load() will fail if m_pSelectedSize is a .msstyles file.
  987. if (fLoadSystemMetrics)
  988. {
  989. if (SUCCEEDED(SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI)))
  990. {
  991. m_fLoadedAdvState = TRUE;
  992. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  993. }
  994. else
  995. {
  996. m_fLoadedAdvState = FALSE;
  997. }
  998. }
  999. if (SUCCEEDED(hr))
  1000. {
  1001. hr = _UpdatePreview(fUpdateThemePage);
  1002. }
  1003. }
  1004. return hr;
  1005. }
  1006. HRESULT CBaseAppearancePage::_GetPageByCLSID(const GUID * pClsid, IPropertyBag ** ppPropertyBag)
  1007. {
  1008. HRESULT hr = E_FAIL;
  1009. *ppPropertyBag = NULL;
  1010. if (_punkSite)
  1011. {
  1012. IThemeUIPages * pThemeUI;
  1013. hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUI));
  1014. if (SUCCEEDED(hr))
  1015. {
  1016. IEnumUnknown * pEnumUnknown;
  1017. hr = pThemeUI->GetBasePagesEnum(&pEnumUnknown);
  1018. if (SUCCEEDED(hr))
  1019. {
  1020. IUnknown * punk;
  1021. // This may not exit due to policy
  1022. hr = IEnumUnknown_FindCLSID(pEnumUnknown, *pClsid, &punk);
  1023. if (SUCCEEDED(hr))
  1024. {
  1025. hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, ppPropertyBag));
  1026. punk->Release();
  1027. }
  1028. pEnumUnknown->Release();
  1029. }
  1030. pThemeUI->Release();
  1031. }
  1032. }
  1033. return hr;
  1034. }
  1035. HRESULT CBaseAppearancePage::_OnSetActive(HWND hDlg)
  1036. {
  1037. #ifdef READ_3D_RULES_FROM_REGISTRY
  1038. Look_Reset3DRatios();
  1039. #endif
  1040. _LoadState();
  1041. _EnableAdvancedButton();
  1042. _ScaleSizesSinceDPIChanged(); // We want to update our settings if someone changed the DPI
  1043. return S_OK;
  1044. }
  1045. HRESULT CBaseAppearancePage::_OnApply(HWND hDlg, LPARAM lParam)
  1046. {
  1047. // Our parent dialog will be notified of the Apply event and will call our
  1048. // IBasePropPage::OnApply() to do the real work.
  1049. return S_OK;
  1050. }
  1051. // This Property Sheet appear in the top level of the "Display Control Panel".
  1052. INT_PTR CBaseAppearancePage::_BaseAppearanceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1053. {
  1054. NMHDR FAR *lpnm;
  1055. switch(message)
  1056. {
  1057. case WM_NOTIFY:
  1058. lpnm = (NMHDR FAR *)lParam;
  1059. switch(lpnm->code)
  1060. {
  1061. case PSN_SETACTIVE:
  1062. _OnSetActive(hDlg);
  1063. break;
  1064. case PSN_APPLY:
  1065. _OnApply(hDlg, lParam);
  1066. break;
  1067. case PSN_RESET:
  1068. break;
  1069. }
  1070. break;
  1071. case WM_INITDIALOG:
  1072. _OnInitAppearanceDlg(hDlg);
  1073. break;
  1074. case WM_DESTROY:
  1075. _OnDestroy(hDlg);
  1076. break;
  1077. case WM_HELP:
  1078. WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, SZ_HELPFILE_BASEAPPEARANCE, HELP_WM_HELP, (DWORD_PTR) aBaseAppearanceHelpIds);
  1079. break;
  1080. case WM_CONTEXTMENU: // right mouse click
  1081. WinHelp((HWND) wParam, SZ_HELPFILE_BASEAPPEARANCE, HELP_CONTEXTMENU, (DWORD_PTR) aBaseAppearanceHelpIds);
  1082. break;
  1083. case WM_COMMAND:
  1084. _OnCommand(hDlg, message, wParam, lParam);
  1085. break;
  1086. case WMUSER_DELAYENABLEAPPLY:
  1087. EnableApplyButton(hDlg);
  1088. break;
  1089. }
  1090. return FALSE;
  1091. }
  1092. HRESULT CBaseAppearancePage::_LoadState(void)
  1093. {
  1094. HRESULT hr = S_OK;
  1095. if (!m_fLoadedAdvState)
  1096. {
  1097. m_advDlgState.dwChanged = NO_CHANGE;
  1098. if (m_pSelectedThemeScheme && m_pSelectedStyle && m_pSelectedSize)
  1099. {
  1100. hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
  1101. if (SUCCEEDED(hr))
  1102. {
  1103. m_fLoadedAdvState = TRUE;
  1104. }
  1105. }
  1106. else
  1107. {
  1108. hr = E_FAIL;
  1109. }
  1110. }
  1111. return hr;
  1112. }
  1113. BOOL IsSkinScheme(IN IThemeScheme * pThemeScheme)
  1114. {
  1115. BOOL fIsSkin = !IUnknown_CompareCLSID(pThemeScheme, CLSID_LegacyAppearanceScheme);
  1116. return fIsSkin;
  1117. }
  1118. /*****************************************************************************\
  1119. DESCRIPTION:
  1120. This method will turn on or off the visual style.
  1121. \*****************************************************************************/
  1122. HRESULT CBaseAppearancePage::_ApplyScheme(IThemeScheme * pThemeScheme, IThemeStyle * pColorStyle, IThemeSize * pThemeSize)
  1123. {
  1124. HRESULT hr = E_INVALIDARG;
  1125. if (pThemeScheme && pColorStyle && pThemeSize)
  1126. {
  1127. hr = pColorStyle->put_SelectedSize(pThemeSize);
  1128. if (SUCCEEDED(hr))
  1129. {
  1130. hr = pThemeScheme->put_SelectedStyle(pColorStyle);
  1131. if (SUCCEEDED(hr))
  1132. {
  1133. CComBSTR bstrPath;
  1134. if (IsSkinScheme(pThemeScheme) &&
  1135. SUCCEEDED(hr = pThemeScheme->get_Path(&bstrPath)) &&
  1136. SUCCEEDED(CheckThemeSignature(bstrPath)))
  1137. {
  1138. CComBSTR bstrStyle;
  1139. hr = pColorStyle->get_Name(&bstrStyle);
  1140. if (SUCCEEDED(hr))
  1141. {
  1142. CComBSTR bstrSize;
  1143. hr = pThemeSize->get_Name(&bstrSize);
  1144. if (SUCCEEDED(hr))
  1145. {
  1146. hr = ApplyVisualStyle(bstrPath, bstrStyle, bstrSize);
  1147. if (FAILED(hr))
  1148. {
  1149. HWND hwndParent = NULL;
  1150. // We want to display UI if an error occured here. We want to do
  1151. // it instead of our parent because THEMELOADPARAMS contains
  1152. // extra error information that we can't pass back to the caller.
  1153. // However, we will only display error UI if our caller wants us
  1154. // to. We determine that by the fact that they make an hwnd available
  1155. // to us. We get the hwnd by getting our site pointer and getting
  1156. // the hwnd via ::GetWindow().
  1157. if (_punkSite && SUCCEEDED(IUnknown_GetWindow(_punkSite, &hwndParent)))
  1158. {
  1159. hr = DisplayThemeErrorDialog(hwndParent, hr, IDS_ERROR_TITLE_APPLYBASEAPPEARANCE, IDS_ERROR_APPLYBASEAPPEARANCE_LOADTHEME);
  1160. }
  1161. }
  1162. }
  1163. }
  1164. }
  1165. else
  1166. {
  1167. // Unload any existing skin.
  1168. ApplyVisualStyle(NULL, NULL, NULL);
  1169. // Ignore the error value, the service could be down
  1170. hr = S_OK;
  1171. }
  1172. IPropertyBag * pPropertyBag;
  1173. if (SUCCEEDED(pThemeSize->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag))))
  1174. {
  1175. TCHAR szLegacyName[MAX_PATH];
  1176. // Here, we need to update a regkey with the selected legacy name. That way we can tell if
  1177. // 3rd party UI or downlevel OSs change the Win2k "Appearance Scheme". If they do, uxtheme (LMouton)
  1178. // will disable visual styles on the next login. This will make sure we don't get someone else's
  1179. // NONCLIENTMETRICS and our visual style.
  1180. if (FAILED(SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_COLORSCHEME_LEGACYNAME, szLegacyName, ARRAYSIZE(szLegacyName))))
  1181. {
  1182. szLegacyName[0] = 0;
  1183. }
  1184. HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_APPEARANCE, THEMEPROP_NEWCURRSCHEME, szLegacyName);
  1185. HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_APPEARANCE, SZ_REGVALUE_CURRENT, szLegacyName);
  1186. pPropertyBag->Release();
  1187. }
  1188. }
  1189. }
  1190. }
  1191. return hr;
  1192. }
  1193. HRESULT CBaseAppearancePage::_SaveState(CDimmedWindow* pDimmedWindow)
  1194. {
  1195. HRESULT hr = S_OK;
  1196. BOOL fIsSkinApplied = IsThemeActive(); // This will keep track if a skin was applied before this apply action.
  1197. LogStatus("IsThemeActive() returned %hs in CBaseAppearancePage::_SaveState.\r\n", (fIsSkinApplied ? "TRUE" : "FALSE"));
  1198. // If we are switching from NoSkin->Skin, we want to save the live settings before
  1199. // we turn on the skin (now & here). We do this so we can reload these settings
  1200. // if the user turns Skins off later. This acts like a "Custom" settings option.
  1201. if (!fIsSkinApplied && !IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme))
  1202. {
  1203. hr = _SaveLiveSettings(SZ_SAVEGROUP_NOSKIN); // If we are switching from "NoSkin" to "Skin", we want to save the custom settings now.
  1204. }
  1205. hr = _ApplyScheme(m_pSelectedThemeScheme, m_pSelectedStyle, m_pSelectedSize);
  1206. if (SUCCEEDED(hr))
  1207. {
  1208. m_nSelectedScheme = ComboBox_GetCurSel(m_hwndSchemeDropDown);
  1209. m_nSelectedStyle = ComboBox_GetCurSel(m_hwndStyleDropDown);
  1210. m_nSelectedSize = ComboBox_GetCurSel(m_hwndSizeDropDown);
  1211. }
  1212. if (SUCCEEDED(hr))
  1213. {
  1214. // Here we save the settings no matter which direction we are going. These
  1215. // settings will be loaded when the Display Control Panel is opened next time.
  1216. hr = _SaveLiveSettings(SZ_SAVEGROUP_ALL);
  1217. }
  1218. // We normally want the call to IThemeManager->put_SelectedScheme() to not only
  1219. // store the selection but to also update the live system metrics. We special case
  1220. // the Legacy "Appearance Schemes" because the user could have customized the
  1221. // settings in the Advanced Appearance dialog. If they did, then m_advDlgState.dwChanged
  1222. // will have dirty bits set and we need to apply that state ourselves.
  1223. if (m_advDlgState.dwChanged)
  1224. {
  1225. hr = SystemMetricsAll_Set(&m_advDlgState, pDimmedWindow);
  1226. LogSystemMetrics("CBaseAppearancePage::_SaveState() pushing to live", &m_advDlgState);
  1227. }
  1228. if (SUCCEEDED(hr))
  1229. {
  1230. m_advDlgState.dwChanged = NO_CHANGE;
  1231. m_fIsDirty = FALSE;
  1232. }
  1233. return hr;
  1234. }
  1235. // If we are switching from "NoSkin" to "Skin", we want to save the custom settings now.
  1236. HRESULT CBaseAppearancePage::_LoadLiveSettings(IN LPCWSTR pszSaveGroup)
  1237. {
  1238. HRESULT hr = S_OK;
  1239. if (!m_fLoadedAdvState)
  1240. {
  1241. #ifndef FEATURE_SAVECUSTOM_APPEARANCE
  1242. if (!StrCmpI(pszSaveGroup, SZ_SAVEGROUP_ALL))
  1243. {
  1244. SystemMetricsAll_Get(&m_advDlgState);
  1245. LogSystemMetrics("LOADING SYSMETRICS: ", &m_advDlgState);
  1246. m_fLoadedAdvState = TRUE;
  1247. }
  1248. else
  1249. {
  1250. hr = E_FAIL; // The caller needs to get their own system metrics.
  1251. }
  1252. #else // FEATURE_SAVECUSTOM_APPEARANCE
  1253. AssertMsg((NULL != m_pSelectedThemeScheme), TEXT("_LoadLiveSettings() can't get it's job done without m_pSelectedThemeScheme"));
  1254. if (m_pSelectedThemeScheme)
  1255. {
  1256. IThemeScheme * pThemeScheme;
  1257. hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &pThemeScheme));
  1258. if (SUCCEEDED(hr))
  1259. {
  1260. CComVariant varCurrentNameBSTR(pszSaveGroup);
  1261. IThemeStyle * pSelectedStyle;
  1262. // The next call may fail because we may have never saved the settings yet.
  1263. hr = pThemeScheme->get_item(varCurrentNameBSTR, &pSelectedStyle);
  1264. if (FAILED(hr))
  1265. {
  1266. // So, let's save the settings now.
  1267. hr = _SaveLiveSettings(pszSaveGroup);
  1268. if (SUCCEEDED(hr))
  1269. {
  1270. hr = m_pSelectedThemeScheme->get_item(varCurrentNameBSTR, &pSelectedStyle);
  1271. }
  1272. }
  1273. if (SUCCEEDED(hr))
  1274. {
  1275. IThemeSize * pSelectedSize;
  1276. VARIANT varIndex;
  1277. varIndex.vt = VT_I4;
  1278. varIndex.lVal = 0;
  1279. hr = pSelectedStyle->get_item(varIndex, &pSelectedSize);
  1280. if (FAILED(hr))
  1281. {
  1282. HKEY hKeyTemp;
  1283. if (SUCCEEDED(HrRegOpenKeyEx(HKEY_CURRENT_USER, SZ_REGKEY_UPGRADE_KEY, 0, KEY_READ, &hKeyTemp)))
  1284. {
  1285. RegCloseKey(hKeyTemp);
  1286. }
  1287. else
  1288. {
  1289. // If this happens, we may not have saved the previous settings. So do that now
  1290. // and retry.
  1291. _SaveLiveSettings(pszSaveGroup);
  1292. hr = pSelectedStyle->get_item(varIndex, &pSelectedSize);
  1293. }
  1294. }
  1295. if (SUCCEEDED(hr))
  1296. {
  1297. if (SUCCEEDED(SystemMetricsAll_Load(pSelectedSize, &m_advDlgState, &m_nNewDPI)))
  1298. {
  1299. LogSystemMetrics("LOADING SYSMETRICS: ", &m_advDlgState);
  1300. m_fLoadedAdvState = TRUE;
  1301. }
  1302. pSelectedSize->Release();
  1303. }
  1304. pSelectedStyle->Release();
  1305. }
  1306. pThemeScheme->Release();
  1307. }
  1308. }
  1309. else
  1310. {
  1311. hr = E_FAIL;
  1312. }
  1313. #endif // FEATURE_SAVECUSTOM_APPEARANCE
  1314. }
  1315. return hr;
  1316. }
  1317. HRESULT CBaseAppearancePage::_SaveLiveSettings(IN LPCWSTR pszSaveGroup)
  1318. {
  1319. HRESULT hr = S_OK;
  1320. // Now, get the current (possibly custom) settings and save them.
  1321. SYSTEMMETRICSALL state = {0};
  1322. hr = SystemMetricsAll_Get(&state);
  1323. if (SUCCEEDED(hr))
  1324. {
  1325. IThemeScheme * pThemeScheme;
  1326. LogSystemMetrics("CBaseAppearancePage::_SaveLiveSettings() getting live", &state);
  1327. hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &pThemeScheme));
  1328. if (SUCCEEDED(hr))
  1329. {
  1330. CComVariant varCurrentNameBSTR(pszSaveGroup); // The "Customized Live" item
  1331. IThemeStyle * pSelectedStyle;
  1332. hr = pThemeScheme->get_item(varCurrentNameBSTR, &pSelectedStyle);
  1333. if (SUCCEEDED(hr))
  1334. {
  1335. IThemeSize * pSelectedSize;
  1336. VARIANT varIndex;
  1337. varIndex.vt = VT_I4;
  1338. varIndex.lVal = 0;
  1339. hr = pSelectedStyle->get_item(varIndex, &pSelectedSize);
  1340. if (FAILED(hr))
  1341. {
  1342. hr = pSelectedStyle->AddSize(&pSelectedSize);
  1343. }
  1344. if (SUCCEEDED(hr))
  1345. {
  1346. hr = SystemMetricsAll_Save(&state, pSelectedSize, &m_nNewDPI);
  1347. CHAR szTemp[MAX_PATH];
  1348. StringCchPrintfA(szTemp, ARRAYSIZE(szTemp), "CBaseAppearancePage::_SaveLiveSettings() Grp=\"%ls\", new DPI=%d", pszSaveGroup, m_nNewDPI);
  1349. LogSystemMetrics(szTemp, &state);
  1350. pSelectedSize->Release();
  1351. }
  1352. pSelectedStyle->Release();
  1353. }
  1354. pThemeScheme->Release();
  1355. }
  1356. }
  1357. return hr;
  1358. }
  1359. HRESULT CBaseAppearancePage::_LoadVisaulStyleFile(IN LPCWSTR pszPath)
  1360. {
  1361. HRESULT hr = E_FAIL;
  1362. if (SUCCEEDED(CheckThemeSignature(pszPath)))
  1363. {
  1364. // Now we want to:
  1365. int nSlot = -1;
  1366. int nCount = ComboBox_GetCount(m_hwndSchemeDropDown);
  1367. hr = S_OK;
  1368. // 1. Is it in the list already?
  1369. for (int nIndex = 0; nIndex < nCount; nIndex++)
  1370. {
  1371. IThemeScheme * pThemeScheme = (IThemeScheme *) ComboBox_GetItemData(m_hwndSchemeDropDown, nIndex);
  1372. if (pThemeScheme)
  1373. {
  1374. CComBSTR bstrPath;
  1375. hr = pThemeScheme->get_Path(&bstrPath);
  1376. if (SUCCEEDED(hr))
  1377. {
  1378. if (!StrCmpIW(bstrPath, pszPath))
  1379. {
  1380. bstrPath.Empty();
  1381. // We found it, so stop looking.
  1382. nSlot = nIndex;
  1383. break;
  1384. }
  1385. }
  1386. }
  1387. }
  1388. // 2. If it is not in the list, add it. We put it on the bottom, right above "Other...".
  1389. if (-1 == nSlot)
  1390. {
  1391. IThemeScheme * pThemeSchemeNew;
  1392. hr = CSkinScheme_CreateInstance(pszPath, &pThemeSchemeNew);
  1393. if (SUCCEEDED(hr))
  1394. {
  1395. CComBSTR bstrDisplayName;
  1396. hr = pThemeSchemeNew->get_DisplayName(&bstrDisplayName);
  1397. if (SUCCEEDED(hr))
  1398. {
  1399. nIndex = ComboBox_GetCount(m_hwndSchemeDropDown);
  1400. if (nIndex > 1)
  1401. {
  1402. nIndex -= 1;
  1403. }
  1404. nSlot = nIndex = ComboBox_InsertString(m_hwndSchemeDropDown, nIndex, bstrDisplayName);
  1405. if ((CB_ERR != nIndex) && (CB_ERRSPACE != nIndex))
  1406. {
  1407. if (CB_ERR == ComboBox_SetItemData(m_hwndSchemeDropDown, nIndex, pThemeSchemeNew))
  1408. {
  1409. hr = E_FAIL;
  1410. }
  1411. }
  1412. else
  1413. {
  1414. hr = E_OUTOFMEMORY;
  1415. }
  1416. }
  1417. if (FAILED(hr))
  1418. {
  1419. pThemeSchemeNew->Release();
  1420. }
  1421. }
  1422. }
  1423. if (-1 != nSlot)
  1424. {
  1425. ComboBox_SetCurSel(m_hwndSchemeDropDown, nIndex);
  1426. // 3. Select the theme from the list.
  1427. if (CB_ERR != ComboBox_GetItemData(m_hwndSchemeDropDown, ComboBox_GetCurSel(m_hwndSchemeDropDown)))
  1428. {
  1429. // Okay, we now know we won't recurse infinitely, so let's recurse.
  1430. hr = _OnSchemeChange(_hwnd, FALSE); // FALSE means don't display error dialogs
  1431. if (SUCCEEDED(hr))
  1432. {
  1433. // Since this happens during WM_INITDIALOG, we need to delay enabling the Apply button.
  1434. DelayEnableApplyButton(_hwnd);
  1435. }
  1436. }
  1437. else
  1438. {
  1439. hr = E_FAIL;
  1440. AssertMsg(0, TEXT("We should have correctly selected the item. Please investiate. -BryanSt"));
  1441. }
  1442. }
  1443. else
  1444. {
  1445. hr = E_FAIL;
  1446. }
  1447. }
  1448. return hr;
  1449. }
  1450. //===========================
  1451. // *** IObjectWithSite Interface ***
  1452. //===========================
  1453. HRESULT CBaseAppearancePage::SetSite(IN IUnknown *punkSite)
  1454. {
  1455. if (!punkSite)
  1456. {
  1457. ATOMICRELEASE(m_pThemeManager); // This is a copy of our _punkSite and we need to break the cycle.
  1458. }
  1459. HRESULT hr = CObjectWithSite::SetSite(punkSite);
  1460. if (punkSite)
  1461. {
  1462. // Load the defaults so we will have them if another base tab opens the advanced dlg.
  1463. _OnInitData();
  1464. }
  1465. return hr;
  1466. }
  1467. //===========================
  1468. // *** IPreviewSystemMetrics Interface ***
  1469. //===========================
  1470. HRESULT CBaseAppearancePage::RefreshColors(void)
  1471. {
  1472. UINT i;
  1473. HKEY hk;
  1474. TCHAR szColor[15];
  1475. DWORD dwSize, dwType;
  1476. int iColors[COLOR_MAX];
  1477. COLORREF rgbColors[COLOR_MAX];
  1478. // Open the Colors key in the registry
  1479. if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_COLORS, 0, KEY_READ, &hk) != ERROR_SUCCESS)
  1480. {
  1481. return S_OK;
  1482. }
  1483. // Query for the color information
  1484. for (i = 0; i < ARRAYSIZE(s_pszColorNames); i++)
  1485. {
  1486. dwSize = 15 * sizeof(TCHAR);
  1487. if ((RegQueryValueEx(hk, s_pszColorNames[i], NULL, &dwType, (LPBYTE) szColor, &dwSize) == ERROR_SUCCESS) &&
  1488. (REG_SZ == dwType))
  1489. {
  1490. m_advDlgState.schemeData.rgb[i] = ConvertColor(szColor);
  1491. }
  1492. else
  1493. {
  1494. m_advDlgState.schemeData.rgb[i] = GetSysColor(i);
  1495. }
  1496. }
  1497. RegCloseKey(hk);
  1498. // This call causes user to send a WM_SYSCOLORCHANGE
  1499. for (i=0; i < ARRAYSIZE(rgbColors); i++)
  1500. {
  1501. iColors[i] = i;
  1502. rgbColors[i] = m_advDlgState.schemeData.rgb[i] & 0x00FFFFFF;
  1503. }
  1504. SetSysColors(ARRAYSIZE(rgbColors), iColors, rgbColors);
  1505. return S_OK;
  1506. }
  1507. // When another tab in the Display Control Panel changes the DPI, this tab needs
  1508. // to update any state that was based on the old DPI. For us, this could be
  1509. // the cached data in m_advDlgState.
  1510. HRESULT CBaseAppearancePage::_ScaleSizesSinceDPIChanged(void)
  1511. {
  1512. HRESULT hr = _LoadState();
  1513. //Check if the DPI value has really changed since the last time we applied a DPI change.
  1514. if (SUCCEEDED(hr) && (m_nNewDPI != m_nAppliedDPI))
  1515. {
  1516. CHAR szTemp[MAX_PATH];
  1517. StringCchPrintfA(szTemp, ARRAYSIZE(szTemp), "CBaseAppear::_ScaleSizesSinceDPIChanged() BEFORE Apply(%d)->New(%d) on DPI chang", m_nAppliedDPI, m_nNewDPI);
  1518. LogSystemMetrics(szTemp, &m_advDlgState);
  1519. // Cycle through all the UI fonts and change their sizes.
  1520. DPIConvert_SystemMetricsAll(FALSE, &m_advDlgState, m_nAppliedDPI, m_nNewDPI);
  1521. StringCchPrintfA(szTemp, ARRAYSIZE(szTemp), "CBaseAppear::_ScaleSizesSinceDPIChanged() AFTER Apply(%d)->New(%d) on DPI chang", m_nAppliedDPI, m_nNewDPI);
  1522. LogSystemMetrics(szTemp, &m_advDlgState);
  1523. m_nAppliedDPI = m_nNewDPI;
  1524. m_fIsDirty = TRUE;
  1525. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  1526. _UpdatePreview(FALSE);
  1527. }
  1528. return hr;
  1529. }
  1530. HRESULT CBaseAppearancePage::UpdateCharsetChanges(void)
  1531. {
  1532. return FixFontsOnLanguageChange();
  1533. }
  1534. /**************************************************************\
  1535. DESCRIPTION:
  1536. We shipped this API long ago. The goal is to:
  1537. 1. Set the current "Appearance Scheme".
  1538. 2. If the UI is displayed, update the UI.
  1539. 3. Apply the changes.
  1540. \**************************************************************/
  1541. HRESULT CBaseAppearancePage::DeskSetCurrentScheme(IN LPCWSTR pwzSchemeName)
  1542. {
  1543. int nIndex;
  1544. HRESULT hr = E_INVALIDARG;
  1545. if (pwzSchemeName)
  1546. {
  1547. TCHAR szTemp[MAX_PATH];
  1548. if (!pwzSchemeName[0])
  1549. {
  1550. if (LoadString(HINST_THISDLL, IDS_DEFAULT_APPEARANCES_SCHEME, szTemp, ARRAYSIZE(szTemp)))
  1551. {
  1552. pwzSchemeName = szTemp;
  1553. }
  1554. }
  1555. LoadConversionMappings(); // Load theme if needed.
  1556. hr = MapLegacyAppearanceSchemeToIndex(pwzSchemeName, &nIndex); // Failure means, FALSE, we didn't convert.
  1557. if (SUCCEEDED(hr) && _punkSite)
  1558. {
  1559. IThemeManager * pThemeManager;
  1560. hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeManager, &pThemeManager));
  1561. if (SUCCEEDED(hr))
  1562. {
  1563. hr = InstallVisualStyle(pThemeManager, L"", g_UpgradeMapping[nIndex].szNewColorSchemeName, g_UpgradeMapping[nIndex].szNewSizeName);
  1564. if (SUCCEEDED(hr))
  1565. {
  1566. // This ApplyNow() call will take a little while in normal situation (~10-20 seconds) in order
  1567. // to broadcast the message to all open apps. If a top level window is hung, it may take the
  1568. // full 30 seconds to timeout.
  1569. hr = pThemeManager->ApplyNow();
  1570. // We need to delete the "Live settings" because they are no longer valid.
  1571. SHDeleteKey(HKEY_CURRENT_USER, SZ_SAVEGROUP_NOSKIN_KEY);
  1572. SHDeleteKey(HKEY_CURRENT_USER, SZ_SAVEGROUP_ALL_KEY);
  1573. }
  1574. IUnknown_SetSite(pThemeManager, NULL); // Break the ref-count cycle.
  1575. pThemeManager->Release();
  1576. }
  1577. }
  1578. }
  1579. LogStatus("DeskSetCurrentScheme(\"%ls\") returned hr=%#08lx.\r\n", pwzSchemeName, hr);
  1580. return hr;
  1581. }
  1582. //===========================
  1583. // *** IPropertyBag Interface ***
  1584. //===========================
  1585. HRESULT CBaseAppearancePage::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
  1586. {
  1587. HRESULT hr = E_INVALIDARG;
  1588. _OnInitData();
  1589. if (pszPropName && pVar)
  1590. {
  1591. if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH) && m_pSelectedThemeScheme)
  1592. {
  1593. CComBSTR bstrPath;
  1594. hr = m_pSelectedThemeScheme->get_Path(&bstrPath);
  1595. if (FAILED(hr))
  1596. {
  1597. bstrPath = L"";
  1598. hr = S_OK; // We return an empty string for "Windows Classic" since they ask for the path.
  1599. }
  1600. pVar->vt = VT_BSTR;
  1601. hr = HrSysAllocString(bstrPath, &pVar->bstrVal);
  1602. }
  1603. else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR) && m_pSelectedStyle)
  1604. {
  1605. CComBSTR bstrName;
  1606. hr = m_pSelectedStyle->get_Name(&bstrName);
  1607. if (SUCCEEDED(hr))
  1608. {
  1609. pVar->vt = VT_BSTR;
  1610. hr = HrSysAllocString(bstrName, &pVar->bstrVal);
  1611. }
  1612. }
  1613. else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE) && m_pSelectedSize)
  1614. {
  1615. CComBSTR bstrName;
  1616. hr = m_pSelectedSize->get_Name(&bstrName);
  1617. if (SUCCEEDED(hr))
  1618. {
  1619. pVar->vt = VT_BSTR;
  1620. hr = HrSysAllocString(bstrName, &pVar->bstrVal);
  1621. }
  1622. }
  1623. else if (!StrCmpW(pszPropName, SZ_PBPROP_SYSTEM_METRICS))
  1624. {
  1625. hr = _LoadState();
  1626. // This is pretty ugly.
  1627. pVar->vt = VT_BYREF;
  1628. pVar->byref = &m_advDlgState;
  1629. }
  1630. else if (!StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR))
  1631. {
  1632. hr = _LoadState();
  1633. // This is pretty ugly.
  1634. pVar->vt = VT_UI4;
  1635. pVar->ulVal = m_advDlgState.schemeData.rgb[COLOR_BACKGROUND];
  1636. }
  1637. else if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE))
  1638. {
  1639. pVar->vt = VT_I4;
  1640. pVar->lVal = m_nNewDPI;
  1641. hr = S_OK;
  1642. }
  1643. else if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
  1644. {
  1645. pVar->vt = VT_I4;
  1646. pVar->lVal = m_nAppliedDPI;
  1647. hr = S_OK;
  1648. }
  1649. }
  1650. return hr;
  1651. }
  1652. HRESULT CBaseAppearancePage::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
  1653. {
  1654. HRESULT hr = E_INVALIDARG;
  1655. _OnInitData();
  1656. if (pszPropName && pVar)
  1657. {
  1658. if (VT_BSTR == pVar->vt)
  1659. {
  1660. if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH))
  1661. {
  1662. hr = _OutsideSetScheme(pVar->bstrVal);
  1663. }
  1664. else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR))
  1665. {
  1666. hr = _OutsideSetStyle(pVar->bstrVal);
  1667. }
  1668. else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE))
  1669. {
  1670. hr = _OutsideSetSize(pVar->bstrVal);
  1671. }
  1672. }
  1673. else if ((VT_BYREF == pVar->vt) && pVar->byref)
  1674. {
  1675. if (!StrCmpW(pszPropName, SZ_PBPROP_SYSTEM_METRICS))
  1676. {
  1677. hr = S_OK;
  1678. if (!m_fLoadedAdvState)
  1679. {
  1680. AssertMsg((NULL != m_pSelectedSize), TEXT("m_pSelectedSize should have already been loaded by now or we shouldn't be showing the Adv Appearance page. -BryanSt"));
  1681. hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
  1682. if (SUCCEEDED(hr))
  1683. {
  1684. m_fLoadedAdvState = TRUE;
  1685. }
  1686. }
  1687. SystemMetricsAll_Copy((SYSTEMMETRICSALL *) pVar->byref, &m_advDlgState);
  1688. m_fIsDirty = TRUE;
  1689. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  1690. }
  1691. }
  1692. else if ((VT_UI4 == pVar->vt) &&
  1693. !StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR))
  1694. {
  1695. hr = S_OK;
  1696. if (!m_fLoadedAdvState)
  1697. {
  1698. AssertMsg((NULL != m_pSelectedSize), TEXT("m_pSelectedSize should have already been loaded by now or we shouldn't be showing the Adv Appearance page. -BryanSt"));
  1699. hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
  1700. if (SUCCEEDED(hr))
  1701. {
  1702. m_fLoadedAdvState = TRUE;
  1703. }
  1704. }
  1705. // This is pretty ugly.
  1706. m_advDlgState.schemeData.rgb[COLOR_BACKGROUND] = pVar->ulVal;
  1707. m_fIsDirty = TRUE;
  1708. m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
  1709. }
  1710. else if ((VT_LPWSTR == pVar->vt) &&
  1711. !StrCmpW(pszPropName, SZ_PBPROP_APPEARANCE_LAUNCHMSTHEME))
  1712. {
  1713. Str_SetPtrW(&m_pszLoadMSTheme, pVar->bstrVal);
  1714. hr = S_OK;
  1715. }
  1716. else if (VT_I4 == pVar->vt)
  1717. {
  1718. if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE))
  1719. {
  1720. m_nNewDPI = pVar->lVal;
  1721. hr = _ScaleSizesSinceDPIChanged(); // Scale all the values.
  1722. }
  1723. else if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
  1724. {
  1725. m_nAppliedDPI = pVar->lVal;
  1726. hr = S_OK;
  1727. }
  1728. }
  1729. }
  1730. return hr;
  1731. }
  1732. //===========================
  1733. // *** IBasePropPage Interface ***
  1734. //===========================
  1735. HRESULT CBaseAppearancePage::GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog)
  1736. {
  1737. HRESULT hr = E_INVALIDARG;
  1738. if (ppAdvDialog)
  1739. {
  1740. *ppAdvDialog = NULL;
  1741. hr = _LoadState();
  1742. if (SUCCEEDED(hr))
  1743. {
  1744. _ScaleSizesSinceDPIChanged(); // We want to update our settings if someone changed the DPI
  1745. hr = CAdvAppearancePage_CreateInstance(ppAdvDialog, &m_advDlgState);
  1746. }
  1747. }
  1748. return hr;
  1749. }
  1750. HRESULT CBaseAppearancePage::OnApply(IN PROPPAGEONAPPLY oaAction)
  1751. {
  1752. HRESULT hr = S_OK;
  1753. if (PPOAACTION_CANCEL != oaAction)
  1754. {
  1755. HCURSOR old = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1756. if (_IsDirty())
  1757. {
  1758. //Check to see if there is a change in the DPI value due to "Advanced->General" tab.
  1759. _ScaleSizesSinceDPIChanged();
  1760. // Update the "AppliedDPI" value in the registry.
  1761. HrRegSetDWORD(HKEY_CURRENT_USER, SZ_WINDOWMETRICS, SZ_APPLIEDDPI, m_nNewDPI);
  1762. LogStatus("DPI: SYSTEMMETRICS saved at %d DPI CBaseAppearancePage::OnApply\r\n", m_nNewDPI);
  1763. CDimmedWindow* pDimmedWindow = NULL;
  1764. if (!g_fInSetup)
  1765. {
  1766. pDimmedWindow = new CDimmedWindow(HINST_THISDLL);
  1767. if (pDimmedWindow)
  1768. {
  1769. pDimmedWindow->Create(30000);
  1770. }
  1771. }
  1772. hr = _SaveState(pDimmedWindow);
  1773. if (pDimmedWindow)
  1774. {
  1775. pDimmedWindow->Release();
  1776. }
  1777. if (FAILED(hr) && !g_fInSetup && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr))
  1778. {
  1779. // We want to display UI here. Especially if we fail.
  1780. HWND hwndParent = GetParent(m_hwndSchemeDropDown);
  1781. WCHAR szTitle[MAX_PATH];
  1782. LoadString(HINST_THISDLL, IDS_ERROR_TITLE_APPLYBASEAPPEARANCE2, szTitle, ARRAYSIZE(szTitle));
  1783. ErrorMessageBox(hwndParent, szTitle, IDS_ERROR_APPLYBASEAPPEARANCE, hr, NULL, (MB_OK | MB_ICONEXCLAMATION));
  1784. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1785. }
  1786. }
  1787. SetCursor(old);
  1788. }
  1789. if (PPOAACTION_OK == oaAction)
  1790. {
  1791. }
  1792. return hr;
  1793. }
  1794. //===========================
  1795. // *** IShellPropSheetExt Interface ***
  1796. //===========================
  1797. HRESULT CBaseAppearancePage::AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam)
  1798. {
  1799. HRESULT hr = E_INVALIDARG;
  1800. PROPSHEETPAGE psp = {0};
  1801. psp.dwSize = sizeof(psp);
  1802. psp.hInstance = HINST_THISDLL;
  1803. psp.dwFlags = PSP_DEFAULT;
  1804. psp.lParam = (LPARAM) this;
  1805. psp.pszTemplate = MAKEINTRESOURCE(DLG_APPEARANCEPG);
  1806. psp.pfnDlgProc = CBaseAppearancePage::BaseAppearanceDlgProc;
  1807. HPROPSHEETPAGE hpsp = CreatePropertySheetPage(&psp);
  1808. if (hpsp)
  1809. {
  1810. if (pfnAddPage(hpsp, lParam))
  1811. {
  1812. hr = S_OK;
  1813. }
  1814. else
  1815. {
  1816. DestroyPropertySheetPage(hpsp);
  1817. hr = E_FAIL;
  1818. }
  1819. }
  1820. return hr;
  1821. }
  1822. //===========================
  1823. // *** IUnknown Interface ***
  1824. //===========================
  1825. ULONG CBaseAppearancePage::AddRef()
  1826. {
  1827. return InterlockedIncrement(&m_cRef);
  1828. }
  1829. ULONG CBaseAppearancePage::Release()
  1830. {
  1831. ASSERT( 0 != m_cRef );
  1832. ULONG cRef = InterlockedDecrement(&m_cRef);
  1833. if ( 0 == cRef )
  1834. {
  1835. delete this;
  1836. }
  1837. return cRef;
  1838. }
  1839. HRESULT CBaseAppearancePage::QueryInterface(REFIID riid, void **ppvObj)
  1840. {
  1841. static const QITAB qit[] =
  1842. {
  1843. QITABENT(CBaseAppearancePage, IObjectWithSite),
  1844. QITABENT(CBaseAppearancePage, IOleWindow),
  1845. QITABENT(CBaseAppearancePage, IPersist),
  1846. QITABENT(CBaseAppearancePage, IPropertyBag),
  1847. QITABENT(CBaseAppearancePage, IPreviewSystemMetrics),
  1848. QITABENT(CBaseAppearancePage, IBasePropPage),
  1849. QITABENTMULTI(CBaseAppearancePage, IShellPropSheetExt, IBasePropPage),
  1850. { 0 },
  1851. };
  1852. return QISearch(this, qit, riid, ppvObj);
  1853. }
  1854. //===========================
  1855. // *** Class Methods ***
  1856. //===========================
  1857. CBaseAppearancePage::CBaseAppearancePage() : m_cRef(1), CObjectCLSID(&PPID_BaseAppearance)
  1858. {
  1859. DllAddRef();
  1860. // This needs to be allocated in Zero Inited Memory.
  1861. // Assert that all Member Variables are inited to Zero.
  1862. ASSERT(!m_pThemeManager);
  1863. ASSERT(!m_pSelectedThemeScheme);
  1864. ASSERT(!m_pSelectedStyle);
  1865. ASSERT(!m_pSelectedSize);
  1866. ASSERT(!m_hwndSchemeDropDown);
  1867. ASSERT(!m_hwndStyleDropDown);
  1868. ASSERT(!m_hwndSizeDropDown);
  1869. ASSERT(!m_pThemePreview);
  1870. ASSERT(!m_fIsDirty);
  1871. m_fInitialized = FALSE;
  1872. }
  1873. CBaseAppearancePage::~CBaseAppearancePage()
  1874. {
  1875. Str_SetPtrW(&m_pszLoadMSTheme, NULL);
  1876. ATOMICRELEASE(m_pThemeManager);
  1877. ATOMICRELEASE(m_pSelectedThemeScheme);
  1878. ATOMICRELEASE(m_pSelectedStyle);
  1879. ATOMICRELEASE(m_pSelectedSize);
  1880. ATOMICRELEASE(m_pThemePreview);
  1881. DllRelease();
  1882. }