2338 lines
75 KiB
C++
2338 lines
75 KiB
C++
/*****************************************************************************\
|
|
FILE: BaseAppearPg.cpp
|
|
|
|
DESCRIPTION:
|
|
This code will display a "Appearances" tab in the
|
|
"Display Properties" dialog (the base dialog, not the advanced dlg).
|
|
|
|
??????? ?/??/1993 Created
|
|
BryanSt 3/23/2000 Updated and Converted to C++
|
|
|
|
Copyright (C) Microsoft Corp 1993-2000. All rights reserved.
|
|
\*****************************************************************************/
|
|
|
|
#include "priv.h"
|
|
#include "BaseAppearPg.h"
|
|
#include "AdvAppearPg.h"
|
|
#include "CoverWnd.h"
|
|
#include "AppScheme.h"
|
|
#include "AdvDlg.h"
|
|
#include "fontfix.h"
|
|
|
|
//============================================================================================================
|
|
// *** Globals ***
|
|
//============================================================================================================
|
|
const static DWORD FAR aBaseAppearanceHelpIds[] =
|
|
{
|
|
IDC_APPG_APPEARPREVIEW, IDH_DISPLAY_APPEARANCE_PREVIEW,
|
|
IDC_APPG_LOOKFEEL, IDH_DISPLAY_APPEARANCE_LOOKFEEL,
|
|
IDC_APPG_LOOKFEEL_LABLE, IDH_DISPLAY_APPEARANCE_LOOKFEEL,
|
|
IDC_APPG_COLORSCHEME_LABLE, IDH_DISPLAY_APPEARANCE_COLORSCHEME,
|
|
IDC_APPG_COLORSCHEME, IDH_DISPLAY_APPEARANCE_COLORSCHEME,
|
|
IDC_APPG_WNDSIZE_LABLE, IDH_DISPLAY_APPEARANCE_WNDSIZE,
|
|
IDC_APPG_WNDSIZE, IDH_DISPLAY_APPEARANCE_WNDSIZE,
|
|
IDC_APPG_EFFECTS, IDH_DISPLAY_APPEARANCE_EFFECTS,
|
|
IDC_APPG_ADVANCED, IDH_DISPLAY_APPEARANCE_ADVANCED,
|
|
0, 0
|
|
};
|
|
|
|
#define SZ_HELPFILE_BASEAPPEARANCE TEXT("display.hlp")
|
|
|
|
// EnableApplyButton() fails in WM_INITDIALOG so we need to do it later.
|
|
#define WMUSER_DELAYENABLEAPPLY (WM_USER + 1)
|
|
#define DelayEnableApplyButton(hDlg) PostMessage(hDlg, WMUSER_DELAYENABLEAPPLY, 0, 0)
|
|
|
|
|
|
|
|
|
|
//===========================
|
|
// *** Class Internals & Helpers ***
|
|
//===========================
|
|
#ifdef DEBUG
|
|
void _TestFault(void)
|
|
{
|
|
DWORD dwTemp = 3;
|
|
DWORD * pdwDummy = NULL; // This is NULL in order that it causes a fault.
|
|
|
|
for (int nIndex = 0; nIndex < 1000000; nIndex++)
|
|
{
|
|
// This will definitely fault sooner or later.
|
|
dwTemp += pdwDummy[nIndex];
|
|
}
|
|
}
|
|
#endif // DEBUG
|
|
|
|
|
|
BOOL CBaseAppearancePage::_IsDirty(void)
|
|
{
|
|
BOOL fIsDirty = m_advDlgState.dwChanged;
|
|
|
|
if (m_fIsDirty || // We need to check this because we may have gotten dirty from another page before our UI was displayed.
|
|
(ComboBox_GetCurSel(m_hwndSchemeDropDown) != m_nSelectedScheme) ||
|
|
(ComboBox_GetCurSel(m_hwndStyleDropDown) != m_nSelectedStyle) ||
|
|
(ComboBox_GetCurSel(m_hwndSizeDropDown) != m_nSelectedSize) ||
|
|
(m_nNewDPI != m_nAppliedDPI))
|
|
{
|
|
fIsDirty = TRUE;
|
|
}
|
|
|
|
return fIsDirty;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK CBaseAppearancePage::BaseAppearanceDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CBaseAppearancePage * pThis = (CBaseAppearancePage *)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
if (WM_INITDIALOG == wMsg)
|
|
{
|
|
PROPSHEETPAGE * pPropSheetPage = (PROPSHEETPAGE *) lParam;
|
|
|
|
if (pPropSheetPage)
|
|
{
|
|
SetWindowLongPtr(hDlg, DWLP_USER, pPropSheetPage->lParam);
|
|
pThis = (CBaseAppearancePage *)pPropSheetPage->lParam;
|
|
}
|
|
}
|
|
|
|
if (pThis)
|
|
return pThis->_BaseAppearanceDlgProc(hDlg, wMsg, wParam, lParam);
|
|
|
|
return DefWindowProc(hDlg, wMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
BOOL DisplayAdvAppearancePage(IN IThemeScheme * pSelectedThemeScheme)
|
|
{
|
|
BOOL fDisplayAdvanced = TRUE;
|
|
|
|
if (pSelectedThemeScheme)
|
|
{
|
|
fDisplayAdvanced = IUnknown_CompareCLSID(pSelectedThemeScheme, CLSID_LegacyAppearanceScheme);
|
|
}
|
|
|
|
return fDisplayAdvanced;
|
|
}
|
|
|
|
|
|
|
|
//============================================================================================================
|
|
// *** Dialog Functions ***
|
|
//============================================================================================================
|
|
HRESULT CBaseAppearancePage::_OnAdvancedOptions(HWND hDlg)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IAdvancedDialog * pAdvAppearDialog;
|
|
|
|
hr = GetAdvancedDialog(&pAdvAppearDialog);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BOOL fEnableApply = FALSE;
|
|
|
|
IUnknown_SetSite(pAdvAppearDialog, SAFECAST(this, IObjectWithSite *));
|
|
hr = pAdvAppearDialog->DisplayAdvancedDialog(hDlg, SAFECAST(this, IPropertyBag *), &fEnableApply);
|
|
IUnknown_SetSite(pAdvAppearDialog, NULL);
|
|
if (SUCCEEDED(hr) && fEnableApply)
|
|
{
|
|
EnableApplyButton(hDlg);
|
|
|
|
// We pass TRUE because we want to switch to Custom if:
|
|
// 1) visual styles are off, and 2) some of the system metrics changed. Then we need to update the previews.
|
|
_UpdatePreview(TRUE);
|
|
}
|
|
|
|
pAdvAppearDialog->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnEffectsOptions(HWND hDlg)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (_punkSite)
|
|
{
|
|
IThemeUIPages * pThemesUIPages;
|
|
|
|
// Let's get the Effects base page.
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemesUIPages));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IEnumUnknown * pEnumUnknown;
|
|
|
|
hr = pThemesUIPages->GetBasePagesEnum(&pEnumUnknown);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUnknown * punk;
|
|
|
|
hr = IEnumUnknown_FindCLSID(pEnumUnknown, PPID_Effects, &punk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IBasePropPage * pEffects;
|
|
|
|
hr = punk->QueryInterface(IID_PPV_ARG(IBasePropPage, &pEffects));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IAdvancedDialog * pEffectsDialog;
|
|
|
|
hr = pEffects->GetAdvancedDialog(&pEffectsDialog);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPropertyBag * pEffectsBag;
|
|
|
|
hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, &pEffectsBag));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BOOL fEnableApply = FALSE;
|
|
|
|
IUnknown_SetSite(pEffectsDialog, SAFECAST(this, IObjectWithSite *));
|
|
hr = pEffectsDialog->DisplayAdvancedDialog(hDlg, pEffectsBag, &fEnableApply);
|
|
IUnknown_SetSite(pEffectsDialog, NULL);
|
|
if (SUCCEEDED(hr) && fEnableApply)
|
|
{
|
|
EnableApplyButton(hDlg);
|
|
|
|
// We pass TRUE because we want to switch to Custom if:
|
|
// 1) visual styles are off, and 2) some of the system metrics changed. Then we need to update the previews.
|
|
_UpdatePreview(TRUE);
|
|
}
|
|
|
|
pEffectsBag->Release();
|
|
}
|
|
|
|
pEffectsDialog->Release();
|
|
}
|
|
|
|
pEffects->Release();
|
|
}
|
|
|
|
punk->Release();
|
|
}
|
|
|
|
pEnumUnknown->Release();
|
|
}
|
|
|
|
pThemesUIPages->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_PopulateSchemeDropdown(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
_FreeSchemeDropdown(); // Purge any existing items.
|
|
if (m_pThemeManager && m_pSelectedThemeScheme)
|
|
{
|
|
CComBSTR bstrSelectedName;
|
|
|
|
m_nSelectedStyle = -1;
|
|
// This will fail if someone deleted the .msstyles file.
|
|
if (FAILED(m_pSelectedThemeScheme->get_DisplayName(&bstrSelectedName)))
|
|
{
|
|
bstrSelectedName = (BSTR)NULL;
|
|
}
|
|
|
|
VARIANT varIndex;
|
|
#ifndef ENABLE_IA64_VISUALSTYLES
|
|
// We use a different regkey for 64bit because we need to leave it off until the pre-Whistler
|
|
// 64-bit release forks from the Whistler code base.
|
|
BOOL fSkinsFeatureEnabled = SHRegGetBoolUSValue(SZ_REGKEY_APPEARANCE, SZ_REGVALUE_DISPLAYSCHEMES64, FALSE, FALSE);
|
|
#else // ENABLE_IA64_VISUALSTYLES
|
|
BOOL fSkinsFeatureEnabled = SHRegGetBoolUSValue(SZ_REGKEY_APPEARANCE, SZ_REGVALUE_DISPLAYSCHEMES, FALSE, TRUE);
|
|
#endif // ENABLE_IA64_VISUALSTYLES
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
do
|
|
{
|
|
hr = E_FAIL;
|
|
|
|
// Only add the Skins if the policy doesn't lock it.
|
|
if ((0 == varIndex.lVal) || fSkinsFeatureEnabled)
|
|
{
|
|
// Only add the Skins if the policy doesn't lock it.
|
|
IThemeScheme * pThemeScheme;
|
|
VARIANT varIndex2;
|
|
|
|
varIndex2.vt = VT_I4;
|
|
varIndex2.lVal = 0;
|
|
|
|
// If a Theme can have more than one Scheme (Skin), then we should enum.
|
|
hr = m_pThemeManager->get_schemeItem(varIndex, &pThemeScheme);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDisplayName;
|
|
|
|
hr = pThemeScheme->get_DisplayName(&bstrDisplayName);
|
|
if (SUCCEEDED(hr) && m_hwndSchemeDropDown)
|
|
{
|
|
int nAddIndex = ComboBox_AddString(m_hwndSchemeDropDown, bstrDisplayName);
|
|
|
|
if (-1 != nAddIndex)
|
|
{
|
|
ComboBox_SetItemData(m_hwndSchemeDropDown, nAddIndex, pThemeScheme);
|
|
pThemeScheme = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
ATOMICRELEASE(pThemeScheme);
|
|
}
|
|
}
|
|
|
|
varIndex.lVal++;
|
|
}
|
|
while (SUCCEEDED(hr));
|
|
|
|
//---- now that sorted list is built, find index of "bstrSelectedName" ----
|
|
if (bstrSelectedName)
|
|
{
|
|
int nIndex = (int)ComboBox_FindStringExact(m_hwndSchemeDropDown, 0, bstrSelectedName);
|
|
if (nIndex != -1) // got a match
|
|
{
|
|
ComboBox_SetCurSel(m_hwndSchemeDropDown, nIndex);
|
|
m_nSelectedScheme = nIndex;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (-1 == m_nSelectedScheme)
|
|
{
|
|
m_nSelectedScheme = 0;
|
|
ComboBox_SetCurSel(m_hwndSchemeDropDown, m_nSelectedScheme);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_FreeSchemeDropdown(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPARAM lParam;
|
|
|
|
if (m_hwndSchemeDropDown)
|
|
{
|
|
do
|
|
{
|
|
lParam = ComboBox_GetItemData(m_hwndSchemeDropDown, 0);
|
|
|
|
if (CB_ERR != lParam)
|
|
{
|
|
IThemeScheme * pThemeScheme = (IThemeScheme *) lParam;
|
|
|
|
ATOMICRELEASE(pThemeScheme);
|
|
ComboBox_DeleteString(m_hwndSchemeDropDown, 0);
|
|
}
|
|
}
|
|
while (CB_ERR != lParam);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_PopulateStyleDropdown(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
_FreeStyleDropdown(); // Purge any existing items.
|
|
if (m_pSelectedStyle)
|
|
{
|
|
CComBSTR bstrSelectedName;
|
|
|
|
m_nSelectedStyle = -1;
|
|
hr = m_pSelectedStyle->get_DisplayName(&bstrSelectedName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
do
|
|
{
|
|
// Only add the Skins if the policy doesn't lock it.
|
|
IThemeStyle * pThemeStyle;
|
|
|
|
hr = m_pSelectedThemeScheme->get_item(varIndex, &pThemeStyle);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDisplayName;
|
|
|
|
hr = pThemeStyle->get_DisplayName(&bstrDisplayName);
|
|
if (SUCCEEDED(hr) && m_hwndSchemeDropDown)
|
|
{
|
|
int nAddIndex = ComboBox_AddString(m_hwndStyleDropDown, bstrDisplayName);
|
|
|
|
if (-1 != nAddIndex)
|
|
{
|
|
ComboBox_SetItemData(m_hwndStyleDropDown, nAddIndex, pThemeStyle);
|
|
pThemeStyle = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
ATOMICRELEASE(pThemeStyle);
|
|
}
|
|
|
|
varIndex.lVal++;
|
|
}
|
|
while (SUCCEEDED(hr));
|
|
|
|
//---- now that sorted list is built, find index of "bstrSelectedName" ----
|
|
if (bstrSelectedName)
|
|
{
|
|
int nIndex = (int)ComboBox_FindStringExact(m_hwndStyleDropDown, 0, bstrSelectedName);
|
|
if (nIndex != -1) // got a match
|
|
{
|
|
ComboBox_SetCurSel(m_hwndStyleDropDown, nIndex);
|
|
m_nSelectedStyle = nIndex;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
if (-1 == m_nSelectedStyle)
|
|
{
|
|
m_nSelectedStyle = 0;
|
|
ComboBox_SetCurSel(m_hwndStyleDropDown, m_nSelectedStyle);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_FreeStyleDropdown(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPARAM lParam;
|
|
|
|
if (m_hwndStyleDropDown)
|
|
{
|
|
do
|
|
{
|
|
lParam = ComboBox_GetItemData(m_hwndStyleDropDown, 0);
|
|
|
|
if (CB_ERR != lParam)
|
|
{
|
|
IThemeStyle * pThemeStyle = (IThemeStyle *) lParam;
|
|
|
|
ATOMICRELEASE(pThemeStyle);
|
|
ComboBox_DeleteString(m_hwndStyleDropDown, 0);
|
|
}
|
|
}
|
|
while (CB_ERR != lParam);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_PopulateSizeDropdown(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
_FreeSizeDropdown(); // Purge any existing items.
|
|
if (m_pSelectedSize)
|
|
{
|
|
CComBSTR bstrSelectedName;
|
|
|
|
m_nSelectedSize = -1;
|
|
hr = m_pSelectedSize->get_DisplayName(&bstrSelectedName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
do
|
|
{
|
|
// Only add the Skins if the policy doesn't lock it.
|
|
IThemeSize * pThemeSize;
|
|
|
|
hr = m_pSelectedStyle->get_item(varIndex, &pThemeSize);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDisplayName;
|
|
|
|
hr = pThemeSize->get_DisplayName(&bstrDisplayName);
|
|
if (SUCCEEDED(hr) && m_hwndSchemeDropDown)
|
|
{
|
|
int nAddIndex = ComboBox_AddString(m_hwndSizeDropDown, bstrDisplayName);
|
|
|
|
if (-1 != nAddIndex)
|
|
{
|
|
ComboBox_SetItemData(m_hwndSizeDropDown, nAddIndex, pThemeSize);
|
|
pThemeSize = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
ATOMICRELEASE(pThemeSize);
|
|
}
|
|
|
|
varIndex.lVal++;
|
|
}
|
|
while (SUCCEEDED(hr));
|
|
|
|
//---- now that sorted list is built, find index of "bstrSelectedName" ----
|
|
if (bstrSelectedName)
|
|
{
|
|
int nIndex = (int)ComboBox_FindStringExact(m_hwndSizeDropDown, 0, bstrSelectedName);
|
|
if (nIndex != -1) // got a match
|
|
{
|
|
ComboBox_SetCurSel(m_hwndSizeDropDown, nIndex);
|
|
m_nSelectedSize = nIndex;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
if (-1 == m_nSelectedSize)
|
|
{
|
|
m_nSelectedSize = 0;
|
|
ComboBox_SetCurSel(m_hwndSizeDropDown, m_nSelectedSize);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_FreeSizeDropdown(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPARAM lParam;
|
|
|
|
if (m_hwndSizeDropDown)
|
|
{
|
|
do
|
|
{
|
|
lParam = ComboBox_GetItemData(m_hwndSizeDropDown, 0);
|
|
|
|
if (CB_ERR != lParam)
|
|
{
|
|
IThemeSize * pThemeSize = (IThemeSize *) lParam;
|
|
|
|
ATOMICRELEASE(pThemeSize);
|
|
ComboBox_DeleteString(m_hwndSizeDropDown, 0);
|
|
}
|
|
}
|
|
while (CB_ERR != lParam);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnInitAppearanceDlg(HWND hDlg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_OnInitData();
|
|
_hwnd = hDlg;
|
|
|
|
#ifdef DEBUG
|
|
if (!SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\TaskManager"), TEXT("Enable Test Faults"), FALSE, FALSE))
|
|
{
|
|
// Disable the feature.
|
|
DestroyWindow(GetDlgItem(hDlg, IDC_APPG_TESTFAULT));
|
|
}
|
|
#endif // DEBUG
|
|
|
|
m_hwndSchemeDropDown = GetDlgItem(hDlg, IDC_APPG_LOOKFEEL);
|
|
m_hwndStyleDropDown = GetDlgItem(hDlg, IDC_APPG_COLORSCHEME);
|
|
m_hwndSizeDropDown = GetDlgItem(hDlg, IDC_APPG_WNDSIZE);
|
|
|
|
hr = _OnInitData();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _PopulateSchemeDropdown();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _PopulateStyleDropdown();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _PopulateSizeDropdown();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _UpdatePreview(FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TCHAR szTemp[MAX_PATH];
|
|
DWORD dwType;
|
|
DWORD cbSize = sizeof(szTemp);
|
|
|
|
if (SHRestricted(REST_NOVISUALSTYLECHOICE) ||
|
|
(ERROR_SUCCESS == SHRegGetUSValue(SZ_REGKEY_POLICIES_SYSTEM, SZ_REGVALUE_POLICY_SETVISUALSTYLE, &dwType, (void *) szTemp, &cbSize, FALSE, NULL, 0)))
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_APPG_LOOKFEEL_LABLE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_APPG_LOOKFEEL), FALSE);
|
|
m_fLockVisualStylePolicyEnabled = TRUE;
|
|
LogStatus("POLICY ENABLED: Either NoVisualChoice or SetVisualStyle policy is set, locking the visual style selection.");
|
|
}
|
|
|
|
if (SHRestricted(REST_NOCOLORCHOICE))
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_APPG_COLORSCHEME_LABLE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_APPG_COLORSCHEME), FALSE);
|
|
}
|
|
|
|
if (SHRestricted(REST_NOSIZECHOICE))
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_APPG_WNDSIZE_LABLE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_APPG_WNDSIZE), FALSE);
|
|
}
|
|
|
|
if (m_pszLoadMSTheme)
|
|
{
|
|
hr = _LoadVisaulStyleFile(m_pszLoadMSTheme);
|
|
}
|
|
|
|
_EnableAdvancedButton();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnInitData(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fInitialized)
|
|
{
|
|
// Load DPI Value
|
|
HDC hdc = GetDC(NULL);
|
|
int nDefault = GetDeviceCaps(hdc, LOGPIXELSY); // Get the default value;
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
m_nAppliedDPI = HrRegGetDWORD(HKEY_CURRENT_USER, SZ_WINDOWMETRICS, SZ_APPLIEDDPI, DPI_PERSISTED);
|
|
if (!m_nAppliedDPI)
|
|
{
|
|
m_nAppliedDPI = nDefault;
|
|
}
|
|
m_nNewDPI = m_nAppliedDPI;
|
|
LogStatus("DPI: SYSTEMMETRICS currently at %d DPI CBaseAppearancePage::_OnInitData\r\n", m_nAppliedDPI);
|
|
|
|
// Load everything else.
|
|
AssertMsg((NULL != _punkSite), TEXT("I need my punkSite!!!"));
|
|
if (!m_pThemeManager && _punkSite)
|
|
{
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeManager, &m_pThemeManager));
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && !m_pSelectedThemeScheme)
|
|
{
|
|
hr = m_pThemeManager->get_SelectedScheme(&m_pSelectedThemeScheme);
|
|
if (SUCCEEDED(hr) && !m_pSelectedStyle)
|
|
{
|
|
hr = m_pSelectedThemeScheme->get_SelectedStyle(&m_pSelectedStyle);
|
|
if (SUCCEEDED(hr) && !m_pSelectedSize)
|
|
{
|
|
hr = m_pSelectedStyle->get_SelectedSize(&m_pSelectedSize);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// We want to load whatever system metrics the users have now.
|
|
hr = _LoadLiveSettings(SZ_SAVEGROUP_ALL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_fInitialized = TRUE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnDestroy(HWND hDlg)
|
|
{
|
|
_FreeSchemeDropdown();
|
|
_FreeStyleDropdown();
|
|
_FreeSizeDropdown();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_EnableAdvancedButton(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
#ifdef FEATURE_ENABLE_ADVANCED_WITH_SKINSON
|
|
BOOL fTurnOn = TRUE;
|
|
#else // FEATURE_ENABLE_ADVANCED_WITH_SKINSON
|
|
BOOL fTurnOn = (m_pSelectedThemeScheme ? IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme) : FALSE);
|
|
|
|
if (SHRegGetBoolUSValue(SZ_REGKEY_APPEARANCE, L"AlwaysAllowAdvanced", FALSE, FALSE))
|
|
{
|
|
fTurnOn = TRUE;
|
|
}
|
|
|
|
#endif // FEATURE_ENABLE_ADVANCED_WITH_SKINSON
|
|
EnableWindow(GetDlgItem(_hwnd, IDC_APPG_ADVANCED), fTurnOn);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_UpdatePreview(IN BOOL fUpdateThemePage)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_pThemePreview)
|
|
{
|
|
// We won't execute the following code if our dialog hasn't
|
|
// been created yet. That's fine because the preview will
|
|
// obtain the correct state when we first initialize.
|
|
if (_punkSite && m_hwndSchemeDropDown)
|
|
{
|
|
hr = CThemePreview_CreateInstance(NULL, IID_PPV_ARG(IThemePreview, &m_pThemePreview));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPropertyBag * pPropertyBag;
|
|
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
HWND hwndParent = GetParent(m_hwndSchemeDropDown);
|
|
HWND hwndPlaceHolder = GetDlgItem(hwndParent, IDC_APPG_APPEARPREVIEW);
|
|
RECT rcPreview;
|
|
|
|
AssertMsg((NULL != m_hwndSchemeDropDown), TEXT("We should have this window at this point. -BryanSt"));
|
|
GetClientRect(hwndPlaceHolder, &rcPreview);
|
|
MapWindowPoints(hwndPlaceHolder, hwndParent, (LPPOINT)&rcPreview, 2);
|
|
|
|
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)))
|
|
{
|
|
// If we succeeded, remove the dummy window.
|
|
DestroyWindow(hwndPlaceHolder);
|
|
hr = SHPropertyBag_WritePunk(pPropertyBag, SZ_PBPROP_PREVIEW3, m_pThemePreview);
|
|
if (SUCCEEDED(hr) && fUpdateThemePage)
|
|
{
|
|
// Tell the theme that we have customized the values.
|
|
hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0);
|
|
}
|
|
}
|
|
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (_punkSite)
|
|
{
|
|
IThemeUIPages * pThemeUIPages;
|
|
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUIPages));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pThemeUIPages->UpdatePreview(0);
|
|
}
|
|
pThemeUIPages->Release();
|
|
}
|
|
|
|
if (_punkSite && fUpdateThemePage)
|
|
{
|
|
IPropertyBag * pPropertyBag;
|
|
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Tell the theme that we have customized the values.
|
|
hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0);
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
INT_PTR CBaseAppearancePage::_OnCommand(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL fHandled = 1; // Not handled (WM_COMMAND seems to be different)
|
|
WORD idCtrl = GET_WM_COMMAND_ID(wParam, lParam);
|
|
|
|
switch (idCtrl)
|
|
{
|
|
case IDC_APPG_COLORSCHEME:
|
|
if(HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
_OnStyleChange(hDlg);
|
|
}
|
|
break;
|
|
|
|
case IDC_APPG_WNDSIZE:
|
|
if(HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
_OnSizeChange(hDlg);
|
|
}
|
|
break;
|
|
|
|
case IDC_APPG_LOOKFEEL:
|
|
if(HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
_OnSchemeChange(hDlg, TRUE); // Display Error dialogs since the user is picking the visual style.
|
|
}
|
|
break;
|
|
|
|
case IDC_APPG_EFFECTS: // This is the Effects button.
|
|
_OnEffectsOptions(hDlg);
|
|
break;
|
|
|
|
case IDC_APPG_ADVANCED: // This is the Advanced button.
|
|
_OnAdvancedOptions(hDlg);
|
|
break;
|
|
|
|
#ifdef DEBUG
|
|
case IDC_APPG_TESTFAULT:
|
|
_TestFault();
|
|
break;
|
|
#endif // DEBUG
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fHandled;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnSchemeChange(HWND hDlg, BOOL fDisplayErrors)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
int nIndex = ComboBox_GetCurSel(m_hwndSchemeDropDown);
|
|
BOOL fPreviousSelectionIsVS = (!IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme));
|
|
|
|
if (-1 == nIndex)
|
|
{
|
|
nIndex = 0; // The caller may NOT select nothing.
|
|
}
|
|
|
|
IThemeScheme * pThemeScheme = (IThemeScheme *) ComboBox_GetItemData(m_hwndSchemeDropDown, nIndex);
|
|
m_fLoadedAdvState = FALSE; // Forget the state we previously loaded.
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
|
|
if (pThemeScheme)
|
|
{
|
|
IUnknown_Set((IUnknown **)&m_pSelectedThemeScheme, pThemeScheme);
|
|
}
|
|
|
|
hr = _SetScheme(TRUE, TRUE, fPreviousSelectionIsVS);
|
|
if (FAILED(hr))
|
|
{
|
|
if (fDisplayErrors)
|
|
{
|
|
// Displaying an error dialog when the visual style is selected is very important because
|
|
// this is where we catch parse errors in the visual style.
|
|
hr = DisplayThemeErrorDialog(hDlg, hr, IDS_ERROR_TITLE_LOAD_MSSTYLES_FAIL, IDS_ERROR_LOAD_MSSTYLES_FAIL);
|
|
}
|
|
}
|
|
|
|
_EnableAdvancedButton();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OutsideSetScheme(BSTR bstrScheme)
|
|
{
|
|
HRESULT hr = E_ACCESSDENIED;
|
|
|
|
if (!m_fLockVisualStylePolicyEnabled)
|
|
{
|
|
hr = E_FAIL;
|
|
BOOL fPreviousSelectionIsVS = !IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme);
|
|
|
|
ATOMICRELEASE(m_pSelectedThemeScheme);
|
|
if (bstrScheme && bstrScheme[0])
|
|
{
|
|
BOOL fVisualStylesSupported = (QueryThemeServicesWrap() & QTS_AVAILABLE);
|
|
|
|
LogStatus("QueryThemeServices() returned %hs. In CBaseAppearancePage::_OutsideSetScheme\r\n", (fVisualStylesSupported ? "TRUE" : "FALSE"));
|
|
|
|
// Do not load a visual style of themes do not work.
|
|
if (fVisualStylesSupported)
|
|
{
|
|
if (PathFileExists(bstrScheme))
|
|
{
|
|
hr = CSkinScheme_CreateInstance(bstrScheme, &m_pSelectedThemeScheme);
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); // Them the caller that the theme service was not running.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE); // Them the caller that the theme service was not running.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &m_pSelectedThemeScheme));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// If we are displaying UI, update it.
|
|
if (m_hwndSchemeDropDown)
|
|
{
|
|
CComBSTR bstrSelectedName;
|
|
|
|
m_fIsDirty = TRUE;
|
|
hr = m_pSelectedThemeScheme->get_DisplayName(&bstrSelectedName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
int nIndex = ComboBox_FindString(m_hwndSchemeDropDown, 0, bstrSelectedName);
|
|
|
|
ComboBox_SetCurSel(m_hwndSchemeDropDown, nIndex);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _SetScheme(FALSE, FALSE, fPreviousSelectionIsVS);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************\
|
|
DESCRIPTION:
|
|
The caller just loaded a new value into m_pSelectedThemeScheme. Now
|
|
load good default values into m_pSelectedStyle and m_pSelectedSize.
|
|
|
|
Then this is called, the UI may or may not be displayed. Either the user made a change in
|
|
the dropdown in this tab or the Theme page is setting our values.
|
|
|
|
PARAMETERS:
|
|
fLoadSystemMetrics: If true, we load the system metrics from the scheme. If false,
|
|
we simply select that as the name for the drop down when we let the caller
|
|
push the system metrics into us.
|
|
fLoadLiveSettings: When the user switches from Skin->NoSkin, do we want to
|
|
load custom settings they had before they switched?
|
|
\*****************************************************************************/
|
|
HRESULT CBaseAppearancePage::_SetScheme(IN BOOL fLoadSystemMetrics, IN BOOL fLoadLiveSettings, IN BOOL fPreviousSelectionIsVS)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (m_pSelectedThemeScheme)
|
|
{
|
|
// Now that they choose a different VisualStyle (Scheme), we want to select the new Color Style
|
|
// and Size in that Scheme.
|
|
|
|
// will fall back to the first ColorStyle.
|
|
CComBSTR bstrSelectedStyle;
|
|
CComBSTR bstrSelectedSize;
|
|
|
|
if (m_pSelectedStyle) // This will be empty if someone deletes the current .msstyles file.
|
|
{
|
|
hr = m_pSelectedStyle->get_DisplayName(&bstrSelectedStyle);
|
|
}
|
|
if (m_pSelectedSize)
|
|
{
|
|
hr = m_pSelectedSize->get_DisplayName(&bstrSelectedSize);
|
|
}
|
|
|
|
ATOMICRELEASE(m_pSelectedStyle);
|
|
ATOMICRELEASE(m_pSelectedSize);
|
|
|
|
CComVariant varNameBSTR(bstrSelectedStyle);
|
|
|
|
// We prefer to get the ColorStyle with the same name as the previously selected one.
|
|
hr = m_pSelectedThemeScheme->get_item(varNameBSTR, &m_pSelectedStyle);
|
|
if (FAILED(hr))
|
|
{
|
|
// If that failed to return a value, then we will try to get the default ColorStyle.
|
|
hr = m_pSelectedThemeScheme->get_SelectedStyle(&m_pSelectedStyle);
|
|
if (FAILED(hr))
|
|
{
|
|
// If that failed then we will just pick the first ColorStyles. (Beggers can't be choosers)
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
hr = m_pSelectedThemeScheme->get_item(varIndex, &m_pSelectedStyle);
|
|
}
|
|
}
|
|
|
|
if (m_pSelectedStyle)
|
|
{
|
|
varNameBSTR = bstrSelectedSize;
|
|
|
|
// Now we want to repeat this process with the size.
|
|
// We prefer to get the ColorStyle with the same name as the previously selected one.
|
|
hr = m_pSelectedStyle->get_item(varNameBSTR, &m_pSelectedSize);
|
|
if (FAILED(hr))
|
|
{
|
|
// If that failed to return a value, then we will try to get the default ColorStyle.
|
|
hr = m_pSelectedStyle->get_SelectedSize(&m_pSelectedSize);
|
|
if (FAILED(hr))
|
|
{
|
|
// If that failed then we will just pick the first ColorStyles. (Beggers can't be choosers)
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
hr = m_pSelectedStyle->get_item(varIndex, &m_pSelectedSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = _PopulateStyleDropdown();
|
|
hr = _PopulateSizeDropdown();
|
|
|
|
BOOL fStateLoaded = FALSE;
|
|
BOOL fIsThemeActive = IsThemeActive();
|
|
LogStatus("IsThemeActive() returned %hs. In CBaseAppearancePage::_SetScheme\r\n", (fIsThemeActive ? "TRUE" : "FALSE"));
|
|
|
|
// If the user switched from a skin to "NoSkin", then we want to load the settings from the settings
|
|
// chosen before the user chose the skin.
|
|
if (fIsThemeActive && // Was a skin last applied?
|
|
fLoadLiveSettings && // Do we want to load live settings?
|
|
IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme) && // Is the new selection a "No Skin"?
|
|
!m_fLoadedAdvState) // Have we not yet loaded these setting?
|
|
{
|
|
// We want to load the last set of customized settings....
|
|
if (SUCCEEDED(_LoadLiveSettings(SZ_SAVEGROUP_NOSKIN)))
|
|
{
|
|
fStateLoaded = TRUE;
|
|
}
|
|
}
|
|
|
|
// We don't want to load the state if the change came from the outside
|
|
// because they will load the state themselves.
|
|
if (fLoadSystemMetrics && !fStateLoaded)
|
|
{
|
|
hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_fLoadedAdvState = TRUE;
|
|
}
|
|
}
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _UpdatePreview(fLoadSystemMetrics);
|
|
|
|
if (!fPreviousSelectionIsVS &&
|
|
!IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme))
|
|
{
|
|
IPropertyBag * pEffectsBag;
|
|
|
|
// Whenever we turn on a visual style and a visual style was previously off,
|
|
// turn on "Menu Drop Shadows".
|
|
if (SUCCEEDED(_GetPageByCLSID(&PPID_Effects, &pEffectsBag)))
|
|
{
|
|
SHPropertyBag_WriteBOOL(pEffectsBag, SZ_PBPROP_EFFECTS_MENUDROPSHADOWS, VARIANT_TRUE);
|
|
pEffectsBag->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnStyleChange(HWND hDlg)
|
|
{
|
|
int nIndex = ComboBox_GetCurSel(m_hwndStyleDropDown);
|
|
|
|
m_fLoadedAdvState = FALSE; // Forget the state we previously loaded.
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
if (-1 == nIndex)
|
|
{
|
|
nIndex = 0; // The caller may NOT select nothing.
|
|
}
|
|
|
|
IThemeStyle * pThemeStyle = (IThemeStyle *) ComboBox_GetItemData(m_hwndStyleDropDown, nIndex);
|
|
AssertMsg((NULL != pThemeStyle), TEXT("We need pThemeStyle"));
|
|
if (pThemeStyle)
|
|
{
|
|
IUnknown_Set((IUnknown **)&m_pSelectedStyle, pThemeStyle);
|
|
}
|
|
|
|
return _SetStyle(TRUE);
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OutsideSetStyle(BSTR bstrStyle)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
AssertMsg((NULL != m_pSelectedThemeScheme), TEXT("We need m_pSelectedThemeScheme"));
|
|
if (m_pSelectedThemeScheme)
|
|
{
|
|
IThemeStyle * pSelectedStyle;
|
|
CComVariant varNameBSTR(bstrStyle);
|
|
|
|
m_fIsDirty = TRUE;
|
|
hr = m_pSelectedThemeScheme->get_item(varNameBSTR, &pSelectedStyle);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ATOMICRELEASE(m_pSelectedStyle);
|
|
m_pSelectedStyle = pSelectedStyle;
|
|
|
|
// If we are displaying UI, update it.
|
|
if (m_hwndStyleDropDown)
|
|
{
|
|
CComBSTR bstrSelectedName;
|
|
|
|
hr = m_pSelectedStyle->get_DisplayName(&bstrSelectedName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
int nIndex = ComboBox_FindString(m_hwndStyleDropDown, 0, bstrSelectedName);
|
|
|
|
ComboBox_SetCurSel(m_hwndStyleDropDown, nIndex);
|
|
}
|
|
}
|
|
|
|
hr = _SetStyle(FALSE);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_SetStyle(IN BOOL fUpdateThemePage)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
AssertMsg((m_pSelectedSize && m_pSelectedSize), TEXT("We need m_pSelectedSize && m_pSelectedSize"));
|
|
if (m_pSelectedSize && m_pSelectedSize)
|
|
{
|
|
// Now that they choose a different style, we want to select the new size
|
|
// in that style. We prefer to get the size with the same name but will
|
|
// will fall back to the first style.
|
|
CComBSTR bstrSelectedSize;
|
|
hr = m_pSelectedSize->get_DisplayName(&bstrSelectedSize);
|
|
ATOMICRELEASE(m_pSelectedSize);
|
|
|
|
CComVariant varNameBSTR(bstrSelectedSize);
|
|
hr = m_pSelectedStyle->get_item(varNameBSTR, &m_pSelectedSize);
|
|
if (FAILED(hr))
|
|
{
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
hr = m_pSelectedStyle->get_item(varIndex, &m_pSelectedSize);
|
|
}
|
|
|
|
hr = _PopulateSizeDropdown();
|
|
if (fUpdateThemePage && SUCCEEDED(SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI)))
|
|
{
|
|
m_fLoadedAdvState = TRUE;
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _UpdatePreview(fUpdateThemePage);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnSizeChange(HWND hDlg)
|
|
{
|
|
int nIndex = ComboBox_GetCurSel(m_hwndSizeDropDown);
|
|
|
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
|
if (-1 == nIndex)
|
|
{
|
|
nIndex = 0; // The caller may NOT select nothing.
|
|
}
|
|
|
|
IThemeSize * pThemeSize = (IThemeSize *) ComboBox_GetItemData(m_hwndSizeDropDown, nIndex);
|
|
AssertMsg((NULL != pThemeSize), TEXT("We need pThemeSize"));
|
|
if (pThemeSize)
|
|
{
|
|
IUnknown_Set((IUnknown **)&m_pSelectedSize, pThemeSize);
|
|
}
|
|
|
|
return _SetSize(TRUE, TRUE);
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OutsideSetSize(BSTR bstrSize)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
AssertMsg((m_pSelectedThemeScheme && m_pSelectedStyle), TEXT("We need m_pSelectedThemeScheme && m_pSelectedStyle"));
|
|
if (m_pSelectedThemeScheme && m_pSelectedStyle)
|
|
{
|
|
IThemeSize * pSelectedSize;
|
|
CComVariant varNameBSTR(bstrSize);
|
|
|
|
m_fIsDirty = TRUE;
|
|
hr = m_pSelectedStyle->get_item(varNameBSTR, &pSelectedSize);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ATOMICRELEASE(m_pSelectedSize);
|
|
m_pSelectedSize = pSelectedSize;
|
|
|
|
// If we are displaying UI, update it.
|
|
if (m_hwndSizeDropDown)
|
|
{
|
|
CComBSTR bstrSelectedName;
|
|
|
|
hr = m_pSelectedSize->get_DisplayName(&bstrSelectedName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
int nIndex = ComboBox_FindString(m_hwndSizeDropDown, 0, bstrSelectedName);
|
|
|
|
ComboBox_SetCurSel(m_hwndSizeDropDown, nIndex);
|
|
}
|
|
}
|
|
|
|
hr = _SetSize(TRUE, FALSE);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_SetSize(IN BOOL fLoadSystemMetrics, IN BOOL fUpdateThemePage)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
AssertMsg((NULL != m_pSelectedSize), TEXT("We need m_pSelectedSize"));
|
|
if (m_pSelectedSize)
|
|
{
|
|
hr = S_OK;
|
|
|
|
// SystemMetricsAll_Load() will fail if m_pSelectedSize is a .msstyles file.
|
|
if (fLoadSystemMetrics)
|
|
{
|
|
if (SUCCEEDED(SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI)))
|
|
{
|
|
m_fLoadedAdvState = TRUE;
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
}
|
|
else
|
|
{
|
|
m_fLoadedAdvState = FALSE;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = _UpdatePreview(fUpdateThemePage);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_GetPageByCLSID(const GUID * pClsid, IPropertyBag ** ppPropertyBag)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*ppPropertyBag = NULL;
|
|
if (_punkSite)
|
|
{
|
|
IThemeUIPages * pThemeUI;
|
|
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUI));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IEnumUnknown * pEnumUnknown;
|
|
|
|
hr = pThemeUI->GetBasePagesEnum(&pEnumUnknown);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IUnknown * punk;
|
|
|
|
// This may not exit due to policy
|
|
hr = IEnumUnknown_FindCLSID(pEnumUnknown, *pClsid, &punk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, ppPropertyBag));
|
|
punk->Release();
|
|
}
|
|
|
|
pEnumUnknown->Release();
|
|
}
|
|
|
|
pThemeUI->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnSetActive(HWND hDlg)
|
|
{
|
|
#ifdef READ_3D_RULES_FROM_REGISTRY
|
|
Look_Reset3DRatios();
|
|
#endif
|
|
_LoadState();
|
|
|
|
_EnableAdvancedButton();
|
|
|
|
_ScaleSizesSinceDPIChanged(); // We want to update our settings if someone changed the DPI
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_OnApply(HWND hDlg, LPARAM lParam)
|
|
{
|
|
// Our parent dialog will be notified of the Apply event and will call our
|
|
// IBasePropPage::OnApply() to do the real work.
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// This Property Sheet appear in the top level of the "Display Control Panel".
|
|
INT_PTR CBaseAppearancePage::_BaseAppearanceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
NMHDR FAR *lpnm;
|
|
|
|
switch(message)
|
|
{
|
|
case WM_NOTIFY:
|
|
lpnm = (NMHDR FAR *)lParam;
|
|
switch(lpnm->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
_OnSetActive(hDlg);
|
|
break;
|
|
case PSN_APPLY:
|
|
_OnApply(hDlg, lParam);
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
_OnInitAppearanceDlg(hDlg);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
_OnDestroy(hDlg);
|
|
break;
|
|
|
|
case WM_HELP:
|
|
WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, SZ_HELPFILE_BASEAPPEARANCE, HELP_WM_HELP, (DWORD_PTR) aBaseAppearanceHelpIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU: // right mouse click
|
|
WinHelp((HWND) wParam, SZ_HELPFILE_BASEAPPEARANCE, HELP_CONTEXTMENU, (DWORD_PTR) aBaseAppearanceHelpIds);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
_OnCommand(hDlg, message, wParam, lParam);
|
|
break;
|
|
|
|
case WMUSER_DELAYENABLEAPPLY:
|
|
EnableApplyButton(hDlg);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_LoadState(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fLoadedAdvState)
|
|
{
|
|
m_advDlgState.dwChanged = NO_CHANGE;
|
|
|
|
if (m_pSelectedThemeScheme && m_pSelectedStyle && m_pSelectedSize)
|
|
{
|
|
hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_fLoadedAdvState = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
BOOL IsSkinScheme(IN IThemeScheme * pThemeScheme)
|
|
{
|
|
BOOL fIsSkin = !IUnknown_CompareCLSID(pThemeScheme, CLSID_LegacyAppearanceScheme);
|
|
return fIsSkin;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
DESCRIPTION:
|
|
This method will turn on or off the visual style.
|
|
\*****************************************************************************/
|
|
HRESULT CBaseAppearancePage::_ApplyScheme(IThemeScheme * pThemeScheme, IThemeStyle * pColorStyle, IThemeSize * pThemeSize)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pThemeScheme && pColorStyle && pThemeSize)
|
|
{
|
|
hr = pColorStyle->put_SelectedSize(pThemeSize);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pThemeScheme->put_SelectedStyle(pColorStyle);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrPath;
|
|
|
|
if (IsSkinScheme(pThemeScheme) &&
|
|
SUCCEEDED(hr = pThemeScheme->get_Path(&bstrPath)) &&
|
|
SUCCEEDED(CheckThemeSignature(bstrPath)))
|
|
{
|
|
CComBSTR bstrStyle;
|
|
|
|
hr = pColorStyle->get_Name(&bstrStyle);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrSize;
|
|
|
|
hr = pThemeSize->get_Name(&bstrSize);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ApplyVisualStyle(bstrPath, bstrStyle, bstrSize);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
HWND hwndParent = NULL;
|
|
|
|
// We want to display UI if an error occured here. We want to do
|
|
// it instead of our parent because THEMELOADPARAMS contains
|
|
// extra error information that we can't pass back to the caller.
|
|
// However, we will only display error UI if our caller wants us
|
|
// to. We determine that by the fact that they make an hwnd available
|
|
// to us. We get the hwnd by getting our site pointer and getting
|
|
// the hwnd via ::GetWindow().
|
|
if (_punkSite && SUCCEEDED(IUnknown_GetWindow(_punkSite, &hwndParent)))
|
|
{
|
|
hr = DisplayThemeErrorDialog(hwndParent, hr, IDS_ERROR_TITLE_APPLYBASEAPPEARANCE, IDS_ERROR_APPLYBASEAPPEARANCE_LOADTHEME);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Unload any existing skin.
|
|
hr = ApplyVisualStyle(NULL, NULL, NULL);
|
|
|
|
#ifndef ENABLE_IA64_VISUALSTYLES
|
|
// We don't support themes on non-x86 don't ignore the error value.
|
|
hr = S_OK;
|
|
#endif // ENABLE_IA64_VISUALSTYLES
|
|
}
|
|
|
|
IPropertyBag * pPropertyBag;
|
|
|
|
if (SUCCEEDED(pThemeSize->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag))))
|
|
{
|
|
TCHAR szLegacyName[MAX_PATH];
|
|
|
|
// Here, we need to update a regkey with the selected legacy name. That way we can tell if
|
|
// 3rd party UI or downlevel OSs change the Win2k "Appearance Scheme". If they do, uxtheme (LMouton)
|
|
// will disable visual styles on the next login. This will make sure we don't get someone else's
|
|
// NONCLIENTMETRICS and our visual style.
|
|
if (FAILED(SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_COLORSCHEME_LEGACYNAME, szLegacyName, ARRAYSIZE(szLegacyName))))
|
|
{
|
|
szLegacyName[0] = 0;
|
|
}
|
|
|
|
HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_APPEARANCE, THEMEPROP_NEWCURRSCHEME, szLegacyName);
|
|
HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_APPEARANCE, SZ_REGVALUE_CURRENT, szLegacyName);
|
|
pPropertyBag->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_SaveState(CDimmedWindow* pDimmedWindow)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
BOOL fIsSkinApplied = IsThemeActive(); // This will keep track if a skin was applied before this apply action.
|
|
LogStatus("IsThemeActive() returned %hs in CBaseAppearancePage::_SaveState.\r\n", (fIsSkinApplied ? "TRUE" : "FALSE"));
|
|
|
|
// If we are switching from NoSkin->Skin, we want to save the live settings before
|
|
// we turn on the skin (now & here). We do this so we can reload these settings
|
|
// if the user turns Skins off later. This acts like a "Custom" settings option.
|
|
if (!fIsSkinApplied && !IUnknown_CompareCLSID(m_pSelectedThemeScheme, CLSID_LegacyAppearanceScheme))
|
|
{
|
|
hr = _SaveLiveSettings(SZ_SAVEGROUP_NOSKIN); // If we are switching from "NoSkin" to "Skin", we want to save the custom settings now.
|
|
}
|
|
|
|
hr = _ApplyScheme(m_pSelectedThemeScheme, m_pSelectedStyle, m_pSelectedSize);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_nSelectedScheme = ComboBox_GetCurSel(m_hwndSchemeDropDown);
|
|
m_nSelectedStyle = ComboBox_GetCurSel(m_hwndStyleDropDown);
|
|
m_nSelectedSize = ComboBox_GetCurSel(m_hwndSizeDropDown);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Here we save the settings no matter which direction we are going. These
|
|
// settings will be loaded when the Display Control Panel is opened next time.
|
|
hr = _SaveLiveSettings(SZ_SAVEGROUP_ALL);
|
|
}
|
|
|
|
// We normally want the call to IThemeManager->put_SelectedScheme() to not only
|
|
// store the selection but to also update the live system metrics. We special case
|
|
// the Legacy "Appearance Schemes" because the user could have customized the
|
|
// settings in the Advanced Appearance dialog. If they did, then m_advDlgState.dwChanged
|
|
// will have dirty bits set and we need to apply that state ourselves.
|
|
if (m_advDlgState.dwChanged)
|
|
{
|
|
hr = SystemMetricsAll_Set(&m_advDlgState, pDimmedWindow);
|
|
LogSystemMetrics("CBaseAppearancePage::_SaveState() pushing to live", &m_advDlgState);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_advDlgState.dwChanged = NO_CHANGE;
|
|
m_fIsDirty = FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// If we are switching from "NoSkin" to "Skin", we want to save the custom settings now.
|
|
HRESULT CBaseAppearancePage::_LoadLiveSettings(IN LPCWSTR pszSaveGroup)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fLoadedAdvState)
|
|
{
|
|
#ifndef FEATURE_SAVECUSTOM_APPEARANCE
|
|
if (!StrCmpI(pszSaveGroup, SZ_SAVEGROUP_ALL))
|
|
{
|
|
SystemMetricsAll_Get(&m_advDlgState);
|
|
LogSystemMetrics("LOADING SYSMETRICS: ", &m_advDlgState);
|
|
m_fLoadedAdvState = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL; // The caller needs to get their own system metrics.
|
|
}
|
|
|
|
#else // FEATURE_SAVECUSTOM_APPEARANCE
|
|
AssertMsg((NULL != m_pSelectedThemeScheme), TEXT("_LoadLiveSettings() can't get it's job done without m_pSelectedThemeScheme"));
|
|
if (m_pSelectedThemeScheme)
|
|
{
|
|
IThemeScheme * pThemeScheme;
|
|
|
|
hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &pThemeScheme));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComVariant varCurrentNameBSTR(pszSaveGroup);
|
|
IThemeStyle * pSelectedStyle;
|
|
|
|
// The next call may fail because we may have never saved the settings yet.
|
|
hr = pThemeScheme->get_item(varCurrentNameBSTR, &pSelectedStyle);
|
|
if (FAILED(hr))
|
|
{
|
|
// So, let's save the settings now.
|
|
hr = _SaveLiveSettings(pszSaveGroup);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pSelectedThemeScheme->get_item(varCurrentNameBSTR, &pSelectedStyle);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IThemeSize * pSelectedSize;
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
hr = pSelectedStyle->get_item(varIndex, &pSelectedSize);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
HKEY hKeyTemp;
|
|
|
|
if (SUCCEEDED(HrRegOpenKeyEx(HKEY_CURRENT_USER, SZ_REGKEY_UPGRADE_KEY, 0, KEY_READ, &hKeyTemp)))
|
|
{
|
|
RegCloseKey(hKeyTemp);
|
|
}
|
|
else
|
|
{
|
|
// If this happens, we may not have saved the previous settings. So do that now
|
|
// and retry.
|
|
_SaveLiveSettings(pszSaveGroup);
|
|
hr = pSelectedStyle->get_item(varIndex, &pSelectedSize);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (SUCCEEDED(SystemMetricsAll_Load(pSelectedSize, &m_advDlgState, &m_nNewDPI)))
|
|
{
|
|
LogSystemMetrics("LOADING SYSMETRICS: ", &m_advDlgState);
|
|
m_fLoadedAdvState = TRUE;
|
|
}
|
|
|
|
pSelectedSize->Release();
|
|
}
|
|
|
|
pSelectedStyle->Release();
|
|
}
|
|
|
|
pThemeScheme->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
#endif // FEATURE_SAVECUSTOM_APPEARANCE
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_SaveLiveSettings(IN LPCWSTR pszSaveGroup)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Now, get the current (possibly custom) settings and save them.
|
|
SYSTEMMETRICSALL state = {0};
|
|
|
|
hr = SystemMetricsAll_Get(&state);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IThemeScheme * pThemeScheme;
|
|
|
|
LogSystemMetrics("CBaseAppearancePage::_SaveLiveSettings() getting live", &state);
|
|
hr = CAppearanceScheme_CreateInstance(NULL, IID_PPV_ARG(IThemeScheme, &pThemeScheme));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComVariant varCurrentNameBSTR(pszSaveGroup); // The "Customized Live" item
|
|
IThemeStyle * pSelectedStyle;
|
|
|
|
hr = pThemeScheme->get_item(varCurrentNameBSTR, &pSelectedStyle);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IThemeSize * pSelectedSize;
|
|
VARIANT varIndex;
|
|
|
|
varIndex.vt = VT_I4;
|
|
varIndex.lVal = 0;
|
|
hr = pSelectedStyle->get_item(varIndex, &pSelectedSize);
|
|
if (FAILED(hr))
|
|
{
|
|
hr = pSelectedStyle->AddSize(&pSelectedSize);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SystemMetricsAll_Save(&state, pSelectedSize, &m_nNewDPI);
|
|
|
|
CHAR szTemp[MAX_PATH];
|
|
wnsprintfA(szTemp, ARRAYSIZE(szTemp), "CBaseAppearancePage::_SaveLiveSettings() Grp=\"%ls\", new DPI=%d", pszSaveGroup, m_nNewDPI);
|
|
LogSystemMetrics(szTemp, &state);
|
|
|
|
pSelectedSize->Release();
|
|
}
|
|
|
|
pSelectedStyle->Release();
|
|
}
|
|
|
|
pThemeScheme->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::_LoadVisaulStyleFile(IN LPCWSTR pszPath)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (SUCCEEDED(CheckThemeSignature(pszPath)))
|
|
{
|
|
// Now we want to:
|
|
int nSlot = -1;
|
|
int nCount = ComboBox_GetCount(m_hwndSchemeDropDown);
|
|
|
|
hr = S_OK;
|
|
|
|
// 1. Is it in the list already?
|
|
for (int nIndex = 0; nIndex < nCount; nIndex++)
|
|
{
|
|
IThemeScheme * pThemeScheme = (IThemeScheme *) ComboBox_GetItemData(m_hwndSchemeDropDown, nIndex);
|
|
|
|
if (pThemeScheme)
|
|
{
|
|
CComBSTR bstrPath;
|
|
|
|
hr = pThemeScheme->get_Path(&bstrPath);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!StrCmpIW(bstrPath, pszPath))
|
|
{
|
|
bstrPath.Empty();
|
|
// We found it, so stop looking.
|
|
nSlot = nIndex;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. If it is not in the list, add it. We put it on the bottom, right above "Other...".
|
|
if (-1 == nSlot)
|
|
{
|
|
IThemeScheme * pThemeSchemeNew;
|
|
|
|
hr = CSkinScheme_CreateInstance(pszPath, &pThemeSchemeNew);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrDisplayName;
|
|
|
|
hr = pThemeSchemeNew->get_DisplayName(&bstrDisplayName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
nIndex = ComboBox_GetCount(m_hwndSchemeDropDown);
|
|
|
|
if (nIndex > 1)
|
|
{
|
|
nIndex -= 1;
|
|
}
|
|
|
|
nSlot = nIndex = ComboBox_InsertString(m_hwndSchemeDropDown, nIndex, bstrDisplayName);
|
|
if ((CB_ERR != nIndex) && (CB_ERRSPACE != nIndex))
|
|
{
|
|
if (CB_ERR == ComboBox_SetItemData(m_hwndSchemeDropDown, nIndex, pThemeSchemeNew))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pThemeSchemeNew->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-1 != nSlot)
|
|
{
|
|
ComboBox_SetCurSel(m_hwndSchemeDropDown, nIndex);
|
|
|
|
// 3. Select the theme from the list.
|
|
if (CB_ERR != ComboBox_GetItemData(m_hwndSchemeDropDown, ComboBox_GetCurSel(m_hwndSchemeDropDown)))
|
|
{
|
|
// Okay, we now know we won't recurse infinitely, so let's recurse.
|
|
hr = _OnSchemeChange(_hwnd, FALSE); // FALSE means don't display error dialogs
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Since this happens during WM_INITDIALOG, we need to delay enabling the Apply button.
|
|
DelayEnableApplyButton(_hwnd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
AssertMsg(0, TEXT("We should have correctly selected the item. Please investiate. -BryanSt"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IObjectWithSite Interface ***
|
|
//===========================
|
|
HRESULT CBaseAppearancePage::SetSite(IN IUnknown *punkSite)
|
|
{
|
|
if (!punkSite)
|
|
{
|
|
ATOMICRELEASE(m_pThemeManager); // This is a copy of our _punkSite and we need to break the cycle.
|
|
}
|
|
|
|
HRESULT hr = CObjectWithSite::SetSite(punkSite);
|
|
if (punkSite)
|
|
{
|
|
// Load the defaults so we will have them if another base tab opens the advanced dlg.
|
|
_OnInitData();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IPreviewSystemMetrics Interface ***
|
|
//===========================
|
|
HRESULT CBaseAppearancePage::RefreshColors(void)
|
|
{
|
|
UINT i;
|
|
HKEY hk;
|
|
TCHAR szColor[15];
|
|
DWORD dwSize, dwType;
|
|
int iColors[COLOR_MAX];
|
|
COLORREF rgbColors[COLOR_MAX];
|
|
|
|
// Open the Colors key in the registry
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_COLORS, 0, KEY_READ, &hk) != ERROR_SUCCESS)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// Query for the color information
|
|
for (i = 0; i < ARRAYSIZE(s_pszColorNames); i++)
|
|
{
|
|
dwSize = 15 * sizeof(TCHAR);
|
|
|
|
if ((RegQueryValueEx(hk, s_pszColorNames[i], NULL, &dwType, (LPBYTE) szColor, &dwSize) == ERROR_SUCCESS) &&
|
|
(REG_SZ == dwType))
|
|
{
|
|
m_advDlgState.schemeData.rgb[i] = ConvertColor(szColor);
|
|
}
|
|
else
|
|
{
|
|
m_advDlgState.schemeData.rgb[i] = GetSysColor(i);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hk);
|
|
|
|
// This call causes user to send a WM_SYSCOLORCHANGE
|
|
for (i=0; i < ARRAYSIZE(rgbColors); i++)
|
|
{
|
|
iColors[i] = i;
|
|
rgbColors[i] = m_advDlgState.schemeData.rgb[i] & 0x00FFFFFF;
|
|
}
|
|
|
|
SetSysColors(ARRAYSIZE(rgbColors), iColors, rgbColors);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// When another tab in the Display Control Panel changes the DPI, this tab needs
|
|
// to update any state that was based on the old DPI. For us, this could be
|
|
// the cached data in m_advDlgState.
|
|
HRESULT CBaseAppearancePage::_ScaleSizesSinceDPIChanged(void)
|
|
{
|
|
HRESULT hr = _LoadState();
|
|
|
|
//Check if the DPI value has really changed since the last time we applied a DPI change.
|
|
if (SUCCEEDED(hr) && (m_nNewDPI != m_nAppliedDPI))
|
|
{
|
|
CHAR szTemp[MAX_PATH];
|
|
|
|
wnsprintfA(szTemp, ARRAYSIZE(szTemp), "CBaseAppear::_ScaleSizesSinceDPIChanged() BEFORE Apply(%d)->New(%d) on DPI chang", m_nAppliedDPI, m_nNewDPI);
|
|
LogSystemMetrics(szTemp, &m_advDlgState);
|
|
|
|
// Cycle through all the UI fonts and change their sizes.
|
|
DPIConvert_SystemMetricsAll(FALSE, &m_advDlgState, m_nAppliedDPI, m_nNewDPI);
|
|
|
|
wnsprintfA(szTemp, ARRAYSIZE(szTemp), "CBaseAppear::_ScaleSizesSinceDPIChanged() AFTER Apply(%d)->New(%d) on DPI chang", m_nAppliedDPI, m_nNewDPI);
|
|
LogSystemMetrics(szTemp, &m_advDlgState);
|
|
|
|
m_nAppliedDPI = m_nNewDPI;
|
|
m_fIsDirty = TRUE;
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
_UpdatePreview(FALSE);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::UpdateCharsetChanges(void)
|
|
{
|
|
return FixFontsOnLanguageChange();
|
|
}
|
|
|
|
|
|
/**************************************************************\
|
|
DESCRIPTION:
|
|
We shipped this API long ago. The goal is to:
|
|
1. Set the current "Appearance Scheme".
|
|
2. If the UI is displayed, update the UI.
|
|
3. Apply the changes.
|
|
\**************************************************************/
|
|
HRESULT CBaseAppearancePage::DeskSetCurrentScheme(IN LPCWSTR pwzSchemeName)
|
|
{
|
|
int nIndex;
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pwzSchemeName)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
|
|
if (!pwzSchemeName[0])
|
|
{
|
|
if (LoadString(HINST_THISDLL, IDS_DEFAULT_APPEARANCES_SCHEME, szTemp, ARRAYSIZE(szTemp)))
|
|
{
|
|
pwzSchemeName = szTemp;
|
|
}
|
|
}
|
|
|
|
LoadConversionMappings(); // Load theme if needed.
|
|
hr = MapLegacyAppearanceSchemeToIndex(pwzSchemeName, &nIndex); // Failure means, FALSE, we didn't convert.
|
|
if (SUCCEEDED(hr) && _punkSite)
|
|
{
|
|
IThemeManager * pThemeManager;
|
|
|
|
hr = _punkSite->QueryInterface(IID_PPV_ARG(IThemeManager, &pThemeManager));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = InstallVisualStyle(pThemeManager, L"", g_UpgradeMapping[nIndex].szNewColorSchemeName, g_UpgradeMapping[nIndex].szNewSizeName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// This ApplyNow() call will take a little while in normal situation (~10-20 seconds) in order
|
|
// to broadcast the message to all open apps. If a top level window is hung, it may take the
|
|
// full 30 seconds to timeout.
|
|
hr = pThemeManager->ApplyNow();
|
|
|
|
// We need to delete the "Live settings" because they are no longer valid.
|
|
SHDeleteKey(HKEY_CURRENT_USER, SZ_SAVEGROUP_NOSKIN_KEY);
|
|
SHDeleteKey(HKEY_CURRENT_USER, SZ_SAVEGROUP_ALL_KEY);
|
|
}
|
|
|
|
IUnknown_SetSite(pThemeManager, NULL); // Break the ref-count cycle.
|
|
pThemeManager->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
LogStatus("DeskSetCurrentScheme(\"%ls\") returned hr=%#08lx.\r\n", pwzSchemeName, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IPropertyBag Interface ***
|
|
//===========================
|
|
HRESULT CBaseAppearancePage::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
_OnInitData();
|
|
if (pszPropName && pVar)
|
|
{
|
|
if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH) && m_pSelectedThemeScheme)
|
|
{
|
|
CComBSTR bstrPath;
|
|
|
|
hr = m_pSelectedThemeScheme->get_Path(&bstrPath);
|
|
if (FAILED(hr))
|
|
{
|
|
bstrPath = L"";
|
|
hr = S_OK; // We return an empty string for "Windows Classic" since they ask for the path.
|
|
}
|
|
|
|
pVar->vt = VT_BSTR;
|
|
hr = HrSysAllocString(bstrPath, &pVar->bstrVal);
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR) && m_pSelectedStyle)
|
|
{
|
|
CComBSTR bstrName;
|
|
|
|
hr = m_pSelectedStyle->get_Name(&bstrName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pVar->vt = VT_BSTR;
|
|
hr = HrSysAllocString(bstrName, &pVar->bstrVal);
|
|
}
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE) && m_pSelectedSize)
|
|
{
|
|
CComBSTR bstrName;
|
|
|
|
hr = m_pSelectedSize->get_Name(&bstrName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pVar->vt = VT_BSTR;
|
|
hr = HrSysAllocString(bstrName, &pVar->bstrVal);
|
|
}
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_SYSTEM_METRICS))
|
|
{
|
|
hr = _LoadState();
|
|
|
|
// This is pretty ugly.
|
|
pVar->vt = VT_BYREF;
|
|
pVar->byref = &m_advDlgState;
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR))
|
|
{
|
|
hr = _LoadState();
|
|
|
|
// This is pretty ugly.
|
|
pVar->vt = VT_UI4;
|
|
pVar->ulVal = m_advDlgState.schemeData.rgb[COLOR_BACKGROUND];
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE))
|
|
{
|
|
pVar->vt = VT_I4;
|
|
pVar->lVal = m_nNewDPI;
|
|
hr = S_OK;
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
|
|
{
|
|
pVar->vt = VT_I4;
|
|
pVar->lVal = m_nAppliedDPI;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
_OnInitData();
|
|
if (pszPropName && pVar)
|
|
{
|
|
if (VT_BSTR == pVar->vt)
|
|
{
|
|
if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_PATH))
|
|
{
|
|
hr = _OutsideSetScheme(pVar->bstrVal);
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_COLOR))
|
|
{
|
|
hr = _OutsideSetStyle(pVar->bstrVal);
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_VISUALSTYLE_SIZE))
|
|
{
|
|
hr = _OutsideSetSize(pVar->bstrVal);
|
|
}
|
|
}
|
|
else if ((VT_BYREF == pVar->vt) && pVar->byref)
|
|
{
|
|
if (!StrCmpW(pszPropName, SZ_PBPROP_SYSTEM_METRICS))
|
|
{
|
|
hr = S_OK;
|
|
if (!m_fLoadedAdvState)
|
|
{
|
|
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"));
|
|
hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_fLoadedAdvState = TRUE;
|
|
}
|
|
}
|
|
|
|
SystemMetricsAll_Copy((SYSTEMMETRICSALL *) pVar->byref, &m_advDlgState);
|
|
m_fIsDirty = TRUE;
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
}
|
|
}
|
|
else if ((VT_UI4 == pVar->vt) &&
|
|
!StrCmpW(pszPropName, SZ_PBPROP_BACKGROUND_COLOR))
|
|
{
|
|
hr = S_OK;
|
|
if (!m_fLoadedAdvState)
|
|
{
|
|
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"));
|
|
hr = SystemMetricsAll_Load(m_pSelectedSize, &m_advDlgState, &m_nNewDPI);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_fLoadedAdvState = TRUE;
|
|
}
|
|
}
|
|
|
|
// This is pretty ugly.
|
|
m_advDlgState.schemeData.rgb[COLOR_BACKGROUND] = pVar->ulVal;
|
|
m_fIsDirty = TRUE;
|
|
m_advDlgState.dwChanged = (METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE);
|
|
}
|
|
else if ((VT_LPWSTR == pVar->vt) &&
|
|
!StrCmpW(pszPropName, SZ_PBPROP_APPEARANCE_LAUNCHMSTHEME))
|
|
{
|
|
Str_SetPtrW(&m_pszLoadMSTheme, pVar->bstrVal);
|
|
hr = S_OK;
|
|
}
|
|
else if (VT_I4 == pVar->vt)
|
|
{
|
|
if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_MODIFIED_VALUE))
|
|
{
|
|
m_nNewDPI = pVar->lVal;
|
|
hr = _ScaleSizesSinceDPIChanged(); // Scale all the values.
|
|
}
|
|
else if (!StrCmpW(pszPropName, SZ_PBPROP_DPI_APPLIED_VALUE))
|
|
{
|
|
m_nAppliedDPI = pVar->lVal;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================
|
|
// *** IBasePropPage Interface ***
|
|
//===========================
|
|
HRESULT CBaseAppearancePage::GetAdvancedDialog(OUT IAdvancedDialog ** ppAdvDialog)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppAdvDialog)
|
|
{
|
|
*ppAdvDialog = NULL;
|
|
hr = _LoadState();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_ScaleSizesSinceDPIChanged(); // We want to update our settings if someone changed the DPI
|
|
hr = CAdvAppearancePage_CreateInstance(ppAdvDialog, &m_advDlgState);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::OnApply(IN PROPPAGEONAPPLY oaAction)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (PPOAACTION_CANCEL != oaAction)
|
|
{
|
|
HCURSOR old = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
if (_IsDirty())
|
|
{
|
|
//Check to see if there is a change in the DPI value due to "Advanced->General" tab.
|
|
_ScaleSizesSinceDPIChanged();
|
|
// Update the "AppliedDPI" value in the registry.
|
|
HrRegSetDWORD(HKEY_CURRENT_USER, SZ_WINDOWMETRICS, SZ_APPLIEDDPI, m_nNewDPI);
|
|
LogStatus("DPI: SYSTEMMETRICS saved at %d DPI CBaseAppearancePage::OnApply\r\n", m_nNewDPI);
|
|
|
|
CDimmedWindow* pDimmedWindow = NULL;
|
|
if (!g_fInSetup)
|
|
{
|
|
pDimmedWindow = new CDimmedWindow(HINST_THISDLL);
|
|
if (pDimmedWindow)
|
|
{
|
|
pDimmedWindow->Create(30000);
|
|
}
|
|
}
|
|
|
|
hr = _SaveState(pDimmedWindow);
|
|
|
|
if (pDimmedWindow)
|
|
{
|
|
pDimmedWindow->Release();
|
|
}
|
|
|
|
if (FAILED(hr) && !g_fInSetup && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr))
|
|
{
|
|
// We want to display UI here. Especially if we fail.
|
|
HWND hwndParent = GetParent(m_hwndSchemeDropDown);
|
|
WCHAR szTitle[MAX_PATH];
|
|
|
|
LoadString(HINST_THISDLL, IDS_ERROR_TITLE_APPLYBASEAPPEARANCE2, szTitle, ARRAYSIZE(szTitle));
|
|
ErrorMessageBox(hwndParent, szTitle, IDS_ERROR_APPLYBASEAPPEARANCE, hr, NULL, (MB_OK | MB_ICONEXCLAMATION));
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
|
|
}
|
|
}
|
|
|
|
SetCursor(old);
|
|
}
|
|
|
|
if (PPOAACTION_OK == oaAction)
|
|
{
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IShellPropSheetExt Interface ***
|
|
//===========================
|
|
HRESULT CBaseAppearancePage::AddPages(IN LPFNSVADDPROPSHEETPAGE pfnAddPage, IN LPARAM lParam)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
PROPSHEETPAGE psp = {0};
|
|
|
|
psp.dwSize = sizeof(psp);
|
|
psp.hInstance = HINST_THISDLL;
|
|
psp.dwFlags = PSP_DEFAULT;
|
|
psp.lParam = (LPARAM) this;
|
|
|
|
psp.pszTemplate = MAKEINTRESOURCE(DLG_APPEARANCEPG);
|
|
psp.pfnDlgProc = CBaseAppearancePage::BaseAppearanceDlgProc;
|
|
|
|
HPROPSHEETPAGE hpsp = CreatePropertySheetPage(&psp);
|
|
if (hpsp)
|
|
{
|
|
if (pfnAddPage(hpsp, lParam))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
DestroyPropertySheetPage(hpsp);
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//===========================
|
|
// *** IUnknown Interface ***
|
|
//===========================
|
|
ULONG CBaseAppearancePage::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
|
|
ULONG CBaseAppearancePage::Release()
|
|
{
|
|
if (InterlockedDecrement(&m_cRef))
|
|
return m_cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
|
|
HRESULT CBaseAppearancePage::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CBaseAppearancePage, IObjectWithSite),
|
|
QITABENT(CBaseAppearancePage, IOleWindow),
|
|
QITABENT(CBaseAppearancePage, IPersist),
|
|
QITABENT(CBaseAppearancePage, IPropertyBag),
|
|
QITABENT(CBaseAppearancePage, IPreviewSystemMetrics),
|
|
QITABENT(CBaseAppearancePage, IBasePropPage),
|
|
QITABENTMULTI(CBaseAppearancePage, IShellPropSheetExt, IBasePropPage),
|
|
{ 0 },
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppvObj);
|
|
}
|
|
|
|
|
|
//===========================
|
|
// *** Class Methods ***
|
|
//===========================
|
|
CBaseAppearancePage::CBaseAppearancePage() : m_cRef(1), CObjectCLSID(&PPID_BaseAppearance)
|
|
{
|
|
DllAddRef();
|
|
|
|
// This needs to be allocated in Zero Inited Memory.
|
|
// Assert that all Member Variables are inited to Zero.
|
|
ASSERT(!m_pThemeManager);
|
|
ASSERT(!m_pSelectedThemeScheme);
|
|
ASSERT(!m_pSelectedStyle);
|
|
ASSERT(!m_pSelectedSize);
|
|
ASSERT(!m_hwndSchemeDropDown);
|
|
ASSERT(!m_hwndStyleDropDown);
|
|
ASSERT(!m_hwndSizeDropDown);
|
|
ASSERT(!m_pThemePreview);
|
|
ASSERT(!m_fIsDirty);
|
|
|
|
m_fInitialized = FALSE;
|
|
}
|
|
|
|
|
|
CBaseAppearancePage::~CBaseAppearancePage()
|
|
{
|
|
Str_SetPtrW(&m_pszLoadMSTheme, NULL);
|
|
|
|
ATOMICRELEASE(m_pThemeManager);
|
|
ATOMICRELEASE(m_pSelectedThemeScheme);
|
|
ATOMICRELEASE(m_pSelectedStyle);
|
|
ATOMICRELEASE(m_pSelectedSize);
|
|
ATOMICRELEASE(m_pThemePreview);
|
|
|
|
DllRelease();
|
|
}
|
|
|