|
|
/*****************************************************************************\
FILE: ThemeFile.cpp
DESCRIPTION: This is the Autmation Object to theme scheme object.
BryanSt 4/3/2000 (Bryan Starbuck) Copyright (C) Microsoft Corp 2000-2000. All rights reserved. \*****************************************************************************/
#include "priv.h"
#include <atlbase.h>
#include <mmsystem.h>
#include "ThSettingsPg.h"
#include "ThemeFile.h"
LPCTSTR s_pszCursorArray[SIZE_CURSOR_ARRAY] = { // different cursors
TEXT("Arrow"), TEXT("Help"), TEXT("AppStarting"), TEXT("Wait"), TEXT("NWPen"), TEXT("No"), TEXT("SizeNS"), TEXT("SizeWE"), TEXT("Crosshair"), TEXT("IBeam"), TEXT("SizeNWSE"), TEXT("SizeNESW"), TEXT("SizeAll"), TEXT("UpArrow"), TEXT("Link"), };
// This is a list of string pairs. The first string in the pair is the RegKey and the second is the default sound.
// NULL means to delete the key. If you use an environment string other than "%SystemRoot%", you need to
// update _ApplySounds();
#define SOUND_DEFAULT (UINT)-1
THEME_FALLBACK_VALUES s_ThemeSoundsValues[SIZE_SOUNDS_ARRAY] = { {TEXT("AppEvents\\Schemes\\Apps\\.Default\\.Default\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\AppGPFault\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\Close\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\DeviceConnect\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\DeviceDisconnect\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\DeviceFail\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\LowBatteryAlarm\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\MailBeep\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\Maximize\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\MenuCommand\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\MenuPopup\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\Minimize\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\Open\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\PrintComplete\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\RestoreDown\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\RestoreUp\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\RingIn\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\Ringout\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemExclamation\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemExit\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemHand\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemNotification\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemQuestion\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemStart\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\SystemStartMenu\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\WindowsLogoff\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\Explorer\\EmptyRecycleBin\\.Current"), SOUND_DEFAULT}, {TEXT("AppEvents\\Schemes\\Apps\\Explorer\\Navigating\\.Current"), SOUND_DEFAULT}, };
//===========================
// *** Class Internals & Helpers ***
//===========================
HRESULT CThemeFile::_GetCustomFont(LPCTSTR pszFontName, LOGFONT * pLogFont) { HRESULT hr = S_OK; TCHAR szFont[MAX_PATH]; if (GetPrivateProfileString(SZ_INISECTION_METRICS, pszFontName, SZ_EMPTY, szFont, ARRAYSIZE(szFont), m_pszThemeFile)) { if (TEXT('@') == szFont[0]) // Is the string indirect for MUI?
{ TCHAR szTemp[MAX_PATH];
if (SUCCEEDED(SHLoadIndirectString(szFont, szTemp, ARRAYSIZE(szTemp), NULL))) { StringCchCopy(szFont, ARRAYSIZE(szFont), szTemp); } }
if (TEXT('{') == szFont[0]) { LPTSTR pszStart = &szFont[1]; BOOL fHasMore = TRUE;
LPTSTR pszEnd = StrChr(pszStart, TEXT(',')); if (!pszEnd) { pszEnd = StrChr(pszStart, TEXT('}')); fHasMore = FALSE; }
if (pszEnd) { pszEnd[0] = 0; // Terminate Name.
StringCchCopy(pLogFont->lfFaceName, ARRAYSIZE(pLogFont->lfFaceName), pszStart); if (fHasMore) { pszStart = &pszEnd[1]; pszEnd = StrStr(pszStart, TEXT("pt")); if (pszEnd) { TCHAR szTemp[MAX_PATH];
pszEnd[0] = 0; // Terminate Name.
pszEnd += 2; // Skip past the "pt"
StringCchCopy(szTemp, ARRAYSIZE(szTemp), pszStart); PathRemoveBlanks(szTemp);
pLogFont->lfHeight = -MulDiv(StrToInt(szTemp), DPI_PERSISTED, 72); // Map pt size to lfHeight
pLogFont->lfHeight = min(-3, pLogFont->lfHeight); // Make sure the font doesn't get too small
pLogFont->lfHeight = max(-100, pLogFont->lfHeight); // Make sure the font doesn't get too large
if (TEXT(',') == pszEnd[0]) { pszStart = &pszEnd[1]; pszEnd = StrChr(pszStart, TEXT('}')); if (pszEnd) { pszEnd[0] = 0; // Terminate Name.
pLogFont->lfCharSet = (BYTE) StrToInt(pszStart); } } } } } } }
return hr; }
HRESULT CThemeFile::_LoadCustomFonts(void) { _GetCustomFont(TEXT("CaptionFont"), &(m_systemMetrics.schemeData.ncm.lfCaptionFont)); _GetCustomFont(TEXT("SmCaptionFont"), &(m_systemMetrics.schemeData.ncm.lfSmCaptionFont)); _GetCustomFont(TEXT("MenuFont"), &(m_systemMetrics.schemeData.ncm.lfMenuFont)); _GetCustomFont(TEXT("StatusFont"), &(m_systemMetrics.schemeData.ncm.lfStatusFont)); _GetCustomFont(TEXT("MessageFont"), &(m_systemMetrics.schemeData.ncm.lfMessageFont)); _GetCustomFont(TEXT("IconFont"), &(m_systemMetrics.schemeData.lfIconTitle));
return S_OK; }
// Load the settings in memory
HRESULT CThemeFile::_LoadLiveSettings(int * pnDPI) { HRESULT hr = S_OK;
if (m_pszThemeFile) { if (pnDPI) { *pnDPI = DPI_PERSISTED; }
// Get property bag with default settings.
if (_punkSite) { IPropertyBag * pPropertyBag;
hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag)); if (SUCCEEDED(hr)) { hr = SHPropertyBag_ReadByRef(pPropertyBag, SZ_PBPROP_SYSTEM_METRICS, (void *)&m_systemMetrics, sizeof(m_systemMetrics));
if (pnDPI && FAILED(SHPropertyBag_ReadInt(pPropertyBag, SZ_PBPROP_DPI_MODIFIED_VALUE, pnDPI))) { *pnDPI = DPI_PERSISTED; // Default to the default DPI.
} pPropertyBag->Release(); } } }
return hr; }
// Load the settings in the .theme file.
HRESULT CThemeFile::_LoadSettings(void) { int nCurrentDPI = DPI_PERSISTED; HRESULT hr = _LoadLiveSettings(&nCurrentDPI);
if (m_pszThemeFile) { BOOL fFontsFilter = _IsFiltered(THEMEFILTER_SMSTYLES); TCHAR szIconMetrics[2048];
if (m_systemMetrics.nIcon && m_systemMetrics.nSmallIcon) { ////////////////////////////////////////////
// Get the icon Metrics
// if we somehow come up with no icon metrics in the theme, just
// PUNT and leave cur settings
if (GetPrivateProfileString(SZ_INISECTION_METRICS, SZ_INIKEY_ICONMETRICS, SZ_EMPTY, szIconMetrics, ARRAYSIZE(szIconMetrics), m_pszThemeFile)) { // if something there to set
ICONMETRICSA iconMetricsA;
// translate stored data string to ICONMETRICS bytes
if ((sizeof(iconMetricsA) == WriteBytesToBuffer(szIconMetrics, (void *)&iconMetricsA, sizeof(iconMetricsA))) && // char str read from and binary bytes
(sizeof(iconMetricsA) == iconMetricsA.cbSize)) { // ICONMETRICS are stored in ANSI format in the Theme file so if
// we're living in a UNICODE world we need to convert from ANSI
// to UNICODE
ICONMETRICSW iconMetricsW;
if (!fFontsFilter) { ConvertIconMetricsToWIDE(&iconMetricsA, &iconMetricsW); m_systemMetrics.schemeData.lfIconTitle = iconMetricsW.lfFont; } } }
////////////////////////////////////////////
// Get Non-Client Metrics
// if we somehow come up with no icon metrics in the theme, just
// PUNT and leave cur settings
if (GetPrivateProfileString(SZ_INISECTION_METRICS, SZ_INIKEY_NONCLIENTMETRICS, SZ_EMPTY, szIconMetrics, ARRAYSIZE(szIconMetrics), m_pszThemeFile)) { BOOL fBordersFilter = _IsFiltered(THEMEFILTER_SMSIZES); NONCLIENTMETRICSA nonClientMetrics;
// if something there to set
// translate stored data string to ICONMETRICS bytes
if ((sizeof(nonClientMetrics) == WriteBytesToBuffer(szIconMetrics, (void *)&nonClientMetrics, sizeof(nonClientMetrics))) && // char str read from and binary bytes
(sizeof(nonClientMetrics) == nonClientMetrics.cbSize)) { // ICONMETRICS are stored in ANSI format in the Theme file so if
// we're living in a UNICODE world we need to convert from ANSI
// to UNICODE
NONCLIENTMETRICSW nonClientMetricsW = {0};
ConvertNCMetricsToWIDE(&nonClientMetrics, &nonClientMetricsW); nonClientMetricsW.cbSize = sizeof(nonClientMetricsW); // paranoid
// what we reset if the user checks Font names and styles
if (!fFontsFilter) { // only (some) font information
TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfCaptionFont), &(nonClientMetricsW.lfCaptionFont), TFC_STYLE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfSmCaptionFont), &(nonClientMetricsW.lfSmCaptionFont), TFC_STYLE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfMenuFont), &(nonClientMetricsW.lfMenuFont), TFC_STYLE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfStatusFont), &(nonClientMetricsW.lfStatusFont), TFC_STYLE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfMessageFont), &(nonClientMetricsW.lfMessageFont), TFC_STYLE); }
// what we reset if the user checks Font and window si&zes
if (!fBordersFilter) { // fonts
TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfCaptionFont), &(nonClientMetricsW.lfCaptionFont), TFC_SIZE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfSmCaptionFont), &(nonClientMetricsW.lfSmCaptionFont), TFC_SIZE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfMenuFont), &(nonClientMetricsW.lfMenuFont), TFC_SIZE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfStatusFont), &(nonClientMetricsW.lfStatusFont), TFC_SIZE); TransmitFontCharacteristics(&(m_systemMetrics.schemeData.ncm.lfMessageFont), &(nonClientMetricsW.lfMessageFont), TFC_SIZE);
// Since we are copying the font sizes, scale them to the current DPI.
// window elements sizes
m_systemMetrics.schemeData.ncm.iBorderWidth = nonClientMetricsW.iBorderWidth; m_systemMetrics.schemeData.ncm.iScrollWidth = nonClientMetricsW.iScrollWidth; m_systemMetrics.schemeData.ncm.iScrollHeight = nonClientMetricsW.iScrollHeight; m_systemMetrics.schemeData.ncm.iCaptionWidth = nonClientMetricsW.iCaptionWidth; m_systemMetrics.schemeData.ncm.iCaptionHeight = nonClientMetricsW.iCaptionHeight; m_systemMetrics.schemeData.ncm.iSmCaptionWidth = nonClientMetricsW.iSmCaptionWidth; m_systemMetrics.schemeData.ncm.iSmCaptionHeight = nonClientMetricsW.iSmCaptionHeight; m_systemMetrics.schemeData.ncm.iMenuWidth = nonClientMetricsW.iMenuWidth; m_systemMetrics.schemeData.ncm.iMenuHeight = nonClientMetricsW.iMenuHeight;
// Local custom fonts
_LoadCustomFonts();
if (nCurrentDPI != DPI_PERSISTED) { LogSystemMetrics("CThemeFile::_LoadSettings() BEFORE Loading from .theme", &m_systemMetrics); DPIConvert_SystemMetricsAll(TRUE, &m_systemMetrics, DPI_PERSISTED, nCurrentDPI); LogSystemMetrics("CThemeFile::_LoadSettings() AFTER Loading from .theme", &m_systemMetrics); }
// CHARSET: In Win2k, fontfix.cpp was used as a hack to change the CHARSET from one language to another.
// That doesn't work for many reasons: a) not called on roaming, b) not called for OS lang changes,
// c) won't fix the problem for strings with multiple languages, d) etc.
// Therefore, the SHELL team (BryanSt) had the NTUSER team (MSadek) agree to use DEFAULT_CHARSET all the time.
// If some app has bad logic testing the charset parameter, then the NTUSER team will shim that app to fix it.
// The shim would be really simple, on the return from a SystemParametersInfo(SPI_GETNONCLIENTMETRICS or ICONFONTS)
// just patch the lfCharSet param to the current charset.
// For all CHARSETs to DEFAULT_CHARSET
m_systemMetrics.schemeData.ncm.lfCaptionFont.lfCharSet = DEFAULT_CHARSET; m_systemMetrics.schemeData.ncm.lfSmCaptionFont.lfCharSet = DEFAULT_CHARSET; m_systemMetrics.schemeData.ncm.lfMenuFont.lfCharSet = DEFAULT_CHARSET; m_systemMetrics.schemeData.ncm.lfStatusFont.lfCharSet = DEFAULT_CHARSET; m_systemMetrics.schemeData.ncm.lfMessageFont.lfCharSet = DEFAULT_CHARSET; m_systemMetrics.schemeData.lfIconTitle.lfCharSet = DEFAULT_CHARSET; } } }
////////////////////////////////////////////
// Get Colors
BOOL fGrad = FALSE; // Are gradient captions enabled?
int nIndex; BOOL fColorFilter = _IsFiltered(THEMEFILTER_COLORS);
ClassicSystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, (LPVOID)&fGrad, 0); // Init fGrad
if (!fColorFilter) { for (nIndex = 0; nIndex < ARRAYSIZE(s_pszColorNames); nIndex++) { TCHAR szColor[MAX_PATH];
// get string from theme
if (!GetPrivateProfileString(SZ_INISECTION_COLORS, s_pszColorNames[nIndex], SZ_EMPTY, szColor, ARRAYSIZE(szColor), m_pszThemeFile)) { if ((nIndex == COLOR_GRADIENTACTIVECAPTION) && !szColor[0]) { // They didn't specify the COLOR_GRADIENTACTIVECAPTION color, so use COLOR_ACTIVECAPTION
GetPrivateProfileString(SZ_INISECTION_COLORS, s_pszColorNames[COLOR_ACTIVECAPTION], SZ_EMPTY, szColor, ARRAYSIZE(szColor), m_pszThemeFile); } if ((nIndex == COLOR_GRADIENTINACTIVECAPTION) && !szColor[0]) { // They didn't specify the COLOR_GRADIENTINACTIVECAPTION color, so use COLOR_INACTIVECAPTION
GetPrivateProfileString(SZ_INISECTION_COLORS, s_pszColorNames[COLOR_INACTIVECAPTION], SZ_EMPTY, szColor, ARRAYSIZE(szColor), m_pszThemeFile); } }
if (szColor[0]) { m_systemMetrics.schemeData.rgb[nIndex] = RGBStringToColor(szColor); } } } } else { AssertMsg((NULL != _punkSite), TEXT("The caller needs to set our site or we can't succeed because we can't find out the icon size.")); hr = E_INVALIDARG; }
hr = S_OK; }
return hr; }
HRESULT CThemeFile::_SaveSystemMetrics(SYSTEMMETRICSALL * pSystemMetrics) { HRESULT hr = _LoadSettings();
AssertMsg((NULL != m_pszThemeFile), TEXT("We don't have a file specified yet.")); if (SUCCEEDED(hr) && m_pszThemeFile) { int nCurrentDPI = DPI_PERSISTED;
_LoadLiveSettings(&nCurrentDPI); hr = SystemMetricsAll_Copy(pSystemMetrics, &m_systemMetrics); if (SUCCEEDED(hr)) { // Write the following:
LPWSTR pszStringOut; NONCLIENTMETRICSA nonClientMetricsA = {0}; SYSTEMMETRICSALL systemMetricsPDPI; // SYSMETS in persist DPI
SystemMetricsAll_Copy(pSystemMetrics, &systemMetricsPDPI); // Scale the values so they are persisted in a DPI independent way. (A.k.a., in 96 DPI)
LogSystemMetrics("CThemeFile::_SaveSystemMetrics() BEFORE scale to P-DPI for .theme file", &systemMetricsPDPI); DPIConvert_SystemMetricsAll(TRUE, &systemMetricsPDPI, nCurrentDPI, DPI_PERSISTED); LogSystemMetrics("CThemeFile::_SaveSystemMetrics() AFTER scale to P-DPI for .theme file", &systemMetricsPDPI);
ConvertNCMetricsToANSI(&(systemMetricsPDPI.schemeData.ncm), &nonClientMetricsA);
// #1 "NonclientMetrics"
hr = ConvertBinaryToINIByteString((BYTE *)&nonClientMetricsA, sizeof(nonClientMetricsA), &pszStringOut); if (SUCCEEDED(hr)) { hr = _putThemeSetting(SZ_INISECTION_METRICS, SZ_INIKEY_NONCLIENTMETRICS, FALSE, pszStringOut); LocalFree(pszStringOut);
if (SUCCEEDED(hr)) { // #2 "IconMetrics"
ICONMETRICSA iconMetricsA;
iconMetricsA.cbSize = sizeof(iconMetricsA); GetIconMetricsFromSysMetricsAll(&systemMetricsPDPI, &iconMetricsA, sizeof(iconMetricsA)); hr = ConvertBinaryToINIByteString((BYTE *)&iconMetricsA, sizeof(iconMetricsA), &pszStringOut); if (SUCCEEDED(hr)) { hr = _putThemeSetting(SZ_INISECTION_METRICS, SZ_INIKEY_ICONMETRICS, FALSE, pszStringOut); if (SUCCEEDED(hr)) { int nIndex;
for (nIndex = 0; nIndex < ARRAYSIZE(s_pszColorNames); nIndex++) { LPWSTR pszColor; DWORD dwColor = systemMetricsPDPI.schemeData.rgb[nIndex];
hr = ConvertBinaryToINIByteString((BYTE *)&dwColor, 3, &pszColor); if (SUCCEEDED(hr)) { DWORD cchSize = lstrlen(pszColor);
if (L' ' == pszColor[cchSize - 1]) { pszColor[cchSize - 1] = 0; }
hr = HrWritePrivateProfileStringW(SZ_INISECTION_COLORS, s_pszColorNames[nIndex], pszColor, m_pszThemeFile); LocalFree(pszColor); } }
// Delete the MUI version of the fonts because we just got new NONCLIENTMETRICs
_putThemeSetting(SZ_INISECTION_METRICS, TEXT("CaptionFont"), FALSE, NULL); _putThemeSetting(SZ_INISECTION_METRICS, TEXT("SmCaptionFont"), FALSE, NULL); _putThemeSetting(SZ_INISECTION_METRICS, TEXT("MenuFont"), FALSE, NULL); _putThemeSetting(SZ_INISECTION_METRICS, TEXT("StatusFont"), FALSE, NULL); _putThemeSetting(SZ_INISECTION_METRICS, TEXT("MessageFont"), FALSE, NULL); _putThemeSetting(SZ_INISECTION_METRICS, TEXT("IconFont"), FALSE, NULL); } LocalFree(pszStringOut); } } } } }
return hr; }
BOOL CThemeFile::_IsFiltered(IN DWORD dwFilter) { BOOL fFiltered = FALSE;
// Get property bag with default settings.
if (_punkSite) { IPropertyBag * pPropertyBag;
HRESULT hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag)); if (SUCCEEDED(hr)) { fFiltered = !SHPropertyBag_ReadBOOLDefRet(pPropertyBag, g_szCBNames[dwFilter], FALSE); pPropertyBag->Release(); } }
return fFiltered; }
HRESULT CThemeFile::_ApplySounds(void) { HRESULT hr = S_OK;
if (!_IsFiltered(THEMEFILTER_SOUNDS)) { int nIndex;
for (nIndex = 0; nIndex < ARRAYSIZE(s_ThemeSoundsValues); nIndex++) { CComBSTR bstrPath;
hr = _GetSound(s_ThemeSoundsValues[nIndex].pszRegKey, &bstrPath); if (SUCCEEDED(hr)) { DWORD dwError = SHRegSetPathW(HKEY_CURRENT_USER, s_ThemeSoundsValues[nIndex].pszRegKey, NULL, bstrPath, 0); hr = HRESULT_FROM_WIN32(dwError); } else {
// First delete the value because we many need to switch from REG_SZ to REG_EXPAND_SZ
// Ignore if this fails
HrRegDeleteValue(HKEY_CURRENT_USER, s_ThemeSoundsValues[nIndex].pszRegKey, NULL); hr = E_FAIL;
// The file didn't specify what to use, so reset to the default values.
if (s_ThemeSoundsValues[nIndex].nResourceID) { // Use the specified value.
TCHAR szReplacement[MAX_PATH]; DWORD dwType; DWORD cbSize;
if (s_ThemeSoundsValues[nIndex].nResourceID == SOUND_DEFAULT) { TCHAR szDefaultKey[MAX_PATH]; StringCchCopy(szDefaultKey, ARRAYSIZE(szDefaultKey), s_ThemeSoundsValues[nIndex].pszRegKey);
DWORD cchDefaultKey = lstrlen(szDefaultKey); DWORD cchCurrent = ARRAYSIZE(L".Current"); DWORD cchp = ARRAYSIZE(szDefaultKey) - cchDefaultKey - cchCurrent + 1; LPTSTR p = szDefaultKey + cchDefaultKey - cchCurrent + 1;
// Replace ".Current" with ".default"
if (*p == L'.') { StringCchCopy(p, cchp, L".Default"); cbSize = sizeof szReplacement; hr = HrSHGetValue(HKEY_CURRENT_USER, szDefaultKey, NULL, &dwType, (LPVOID) szReplacement, &cbSize); if (SUCCEEDED(hr)) { PathUnExpandEnvStringsWrap(szReplacement, ARRAYSIZE(szReplacement)); } } } else { if (0 != LoadString(HINST_THISDLL, s_ThemeSoundsValues[nIndex].nResourceID, szReplacement, ARRAYSIZE(szReplacement))) { hr = S_OK; } }
if (SUCCEEDED(hr)) { dwType = (StrStrW(szReplacement, L"%SystemRoot%")) ? REG_EXPAND_SZ : REG_SZ; cbSize = ((lstrlen(szReplacement) + 1) * sizeof(szReplacement[0]));
hr = HrSHSetValue(HKEY_CURRENT_USER, s_ThemeSoundsValues[nIndex].pszRegKey, NULL, dwType, (LPVOID) szReplacement, cbSize); } } else { // We leave the value deleted because the default was empty.
} } }
hr = S_OK; // We don't care if it fails.
// Need to flush buffer and ensure new sounds used for next events
sndPlaySoundW(NULL, SND_ASYNC | SND_NODEFAULT);
// Clear the current pointer scheme string from the registry so that Mouse
// cpl doesn't display a bogus name. Don't care if this fails.
RegSetValue(HKEY_CURRENT_USER, SZ_REGKEY_SOUNDS, REG_SZ, TEXT(".current"), 0); }
return hr; }
HRESULT CThemeFile::_ApplyCursors(void) { HRESULT hr = S_OK;
if (!_IsFiltered(THEMEFILTER_CURSORS)) { int nIndex;
for (nIndex = 0; nIndex < ARRAYSIZE(s_pszCursorArray); nIndex++) { BSTR bstrPath; hr = _getThemeSetting(SZ_INISECTION_CURSORS, s_pszCursorArray[nIndex], THEMESETTING_LOADINDIRECT, &bstrPath); if (FAILED(hr) || !bstrPath[0]) { // The caller didn't specify a value so delete the key so we use default values.
hr = HrRegDeleteValue(HKEY_CURRENT_USER, SZ_INISECTION_CURSORS, s_pszCursorArray[nIndex]); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { hr = S_OK; // it may already not exist, which is fine.
} } else if (SUCCEEDED(hr)) { hr = HrRegSetValueString(HKEY_CURRENT_USER, SZ_INISECTION_CURSORS, s_pszCursorArray[nIndex], bstrPath); } }
BSTR bstrCursor; if (SUCCEEDED(_getThemeSetting(SZ_INISECTION_CURSORS, SZ_INIKEY_CURSORSCHEME, THEMESETTING_LOADINDIRECT, &bstrCursor)) && bstrCursor && bstrCursor[0]) { // Set the cursor scheme
HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_CP_CURSORS, NULL, bstrCursor);
// GPease wants me to mark this regkey -1 so he knows it was changed from the display CPL. See
// him with questions.
HrRegSetDWORD(HKEY_CURRENT_USER, SZ_REGKEY_CP_CURSORS, SZ_REGVALUE_CURSOR_CURRENTSCHEME, 2); } else { HrRegDeleteValue(HKEY_CURRENT_USER, SZ_REGKEY_CP_CURSORS, NULL); HrRegDeleteValue(HKEY_CURRENT_USER, SZ_REGKEY_CP_CURSORS, SZ_REGVALUE_CURSOR_CURRENTSCHEME); }
// For the system to start using the new cursors.
SystemParametersInfoAsync(SPI_SETCURSORS, 0, 0, 0, SPIF_SENDCHANGE, NULL); }
return hr; }
HRESULT CThemeFile::_ApplyWebview(void) { HRESULT hr = S_OK;
// We aren't going to support this.
return hr; }
HRESULT CThemeFile::_ApplyThemeSettings(void) { HRESULT hr = E_INVALIDARG;
if (m_pszThemeFile) { HCURSOR hCursorOld = ::SetCursor(LoadCursor(NULL, IDC_WAIT));
hr = S_OK; if (!((METRIC_CHANGE | COLOR_CHANGE | SCHEME_CHANGE) & m_systemMetrics.dwChanged)) { // Only load settings if we haven't loaded the settings yet.
hr = _LoadSettings(); }
if (SUCCEEDED(hr)) { hr = _ApplySounds(); if (SUCCEEDED(hr)) { hr = _ApplyCursors(); if (SUCCEEDED(hr)) { hr = _ApplyWebview(); } } } // OTHERS:
// 1. Save Icon: SPI_SETICONMETRICS w/iconMetricsW.iHorzSpacing, iVertSpacing, (Policy bIconSpacing).
// 2. Save Icon: SPI_SETICONMETRICS w/iconMetricsW.lfFont (Policy bIconFont).
// 2. Save Icon: from Theme:"Control Panel\\Desktop\\WindowMetrics","Shell Icon Size" to reg same. (Policy bIconSpacing). Repeate for "Shell Small Icon Size"
::SetCursor(hCursorOld); }
return hr; }
HRESULT CThemeFile::_getThemeSetting(IN LPCWSTR pszIniSection, IN LPCWSTR pszIniKey, DWORD dwFlags, OUT BSTR * pbstrPath) { HRESULT hr = E_INVALIDARG;
if (pbstrPath) { *pbstrPath = 0; hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); if (m_pszThemeFile) { WCHAR szPath[MAX_PATH]; DWORD cbRead = 0;
szPath[0] = 0; if (THEMESETTING_LOADINDIRECT & dwFlags) { TCHAR szMUIIniKey[MAX_PATH];
StringCchPrintf(szMUIIniKey, ARRAYSIZE(szMUIIniKey), TEXT("%s.MUI"), pszIniKey); cbRead = SHGetIniStringW(pszIniSection, szMUIIniKey, szPath, ARRAYSIZE(szPath), m_pszThemeFile); }
if (0 == cbRead) { cbRead = SHGetIniStringW(pszIniSection, pszIniKey, szPath, ARRAYSIZE(szPath), m_pszThemeFile); }
if (cbRead) { if (L'@' == szPath[0]) { TCHAR szTemp[MAX_PATH];
if (SUCCEEDED(SHLoadIndirectString(szPath, szTemp, ARRAYSIZE(szTemp), NULL))) { StringCchCopy(szPath, ARRAYSIZE(szPath), szTemp); } }
hr = ExpandResourceDir(szPath, ARRAYSIZE(szPath)); hr = ExpandThemeTokens(m_pszThemeFile, szPath, ARRAYSIZE(szPath)); // Expand %ThemeDir% or %WinDir%
// Sometimes szPath won't be a path.
if (SUCCEEDED(hr) && !PathIsFileSpec(szPath)) { hr = ((CF_NOTFOUND == ConfirmFile(szPath, TRUE)) ? HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) : S_OK); }
if (SUCCEEDED(hr)) { hr = HrSysAllocString(szPath, pbstrPath); } } } }
return hr; }
// pszPath - NULL means delete value
HRESULT CThemeFile::_putThemeSetting(IN LPCWSTR pszIniSection, IN LPCWSTR pszIniKey, BOOL fUTF7, IN OPTIONAL LPWSTR pszPath) { HRESULT hr = E_INVALIDARG;
if (m_pszThemeFile) { TCHAR szPath[MAX_PATH]; LPCWSTR pszValue = pszPath;
szPath[0] = 0; if (pszValue && !PathIsRelative(pszValue) && PathFileExists(pszValue)) { if (PathUnExpandEnvStringsForUser(NULL, pszValue, szPath, ARRAYSIZE(szPath))) { pszValue = szPath; } }
StrReplaceToken(TEXT("%WinDir%\\"), TEXT("%WinDir%"), szPath, ARRAYSIZE(szPath)); StrReplaceToken(TEXT("%SystemRoot%\\"), TEXT("%WinDir%"), szPath, ARRAYSIZE(szPath)); if (fUTF7) { if (SHSetIniStringW(pszIniSection, pszIniKey, pszValue, m_pszThemeFile)) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } else { hr = HrWritePrivateProfileStringW(pszIniSection, pszIniKey, pszValue, m_pszThemeFile); }
TCHAR szMUIIniKey[MAX_PATH];
// Delete any ".MUI" copies because they are out of date.
StringCchPrintf(szMUIIniKey, ARRAYSIZE(szMUIIniKey), TEXT("%s.MUI"), pszIniKey); HrWritePrivateProfileStringW(pszIniSection, szMUIIniKey, NULL, m_pszThemeFile); }
return hr; }
HRESULT CThemeFile::_getIntSetting(IN LPCWSTR pszIniSection, IN LPCWSTR pszIniKey, int nDefault, OUT int * pnValue) { HRESULT hr = E_INVALIDARG;
if (pnValue) { *pnValue = 0; hr = E_FAIL; if (m_pszThemeFile) { *pnValue = GetPrivateProfileInt(pszIniSection, pszIniKey, nDefault, m_pszThemeFile); hr = S_OK; } }
return hr; }
//===========================
// *** ITheme Interface ***
//===========================
HRESULT CThemeFile::get_DisplayName(OUT BSTR * pbstrDisplayName) { HRESULT hr = E_INVALIDARG;
if (pbstrDisplayName) { WCHAR szDisplayName[MAX_PATH];
*pbstrDisplayName = NULL; hr = _getThemeSetting(SZ_INISECTION_THEME, SZ_INIKEY_DISPLAYNAME, THEMESETTING_NORMAL, pbstrDisplayName); if (FAILED(hr)) { LPCTSTR pszFileName = PathFindFileName(m_pszThemeFile);
hr = E_FAIL; if (pszFileName) { SHTCharToUnicode(pszFileName, szDisplayName, ARRAYSIZE(szDisplayName)); PathRemoveExtensionW(szDisplayName);
hr = HrSysAllocStringW(szDisplayName, pbstrDisplayName); } } }
return hr; }
HRESULT CThemeFile::put_DisplayName(IN BSTR bstrDisplayName) { HRESULT hr = E_INVALIDARG;
// NULL bstrDisplayName is allowed, it means to delete the name in the file
// so the filename will be used in the future.
if (bstrDisplayName) { hr = _putThemeSetting(SZ_INISECTION_THEME, SZ_INIKEY_DISPLAYNAME, TRUE, bstrDisplayName); } else { SHSetIniStringW(SZ_INISECTION_THEME, SZ_INIKEY_DISPLAYNAME, NULL, m_pszThemeFile); hr = S_OK; }
return hr; }
HRESULT CThemeFile::get_ScreenSaver(OUT BSTR * pbstrPath) { return _getThemeSetting(SZ_INISECTION_SCREENSAVER, SZ_INIKEY_SCREENSAVER, THEMESETTING_NORMAL, pbstrPath); }
HRESULT CThemeFile::put_ScreenSaver(IN BSTR bstrPath) { return _putThemeSetting(SZ_INISECTION_SCREENSAVER, SZ_INIKEY_SCREENSAVER, TRUE, bstrPath); }
HRESULT CThemeFile::get_Background(OUT BSTR * pbstrPath) { HRESULT hr = E_INVALIDARG;
if (pbstrPath) { hr = _getThemeSetting(SZ_INISECTION_BACKGROUND, SZ_INIKEY_BACKGROUND, THEMESETTING_LOADINDIRECT, pbstrPath); if (SUCCEEDED(hr)) { TCHAR szNone[MAX_PATH];
LoadString(HINST_THISDLL, IDS_NONE, szNone, ARRAYSIZE(szNone)); if (!StrCmpI(szNone, *pbstrPath)) { (*pbstrPath)[0] = 0; } } }
return hr; }
HRESULT CThemeFile::put_Background(IN BSTR bstrPath) { return _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_INIKEY_BACKGROUND, TRUE, bstrPath); }
HRESULT CThemeFile::get_BackgroundTile(OUT enumBkgdTile * pnTile) { HRESULT hr = E_INVALIDARG;
if (pnTile) { TCHAR szSize[10]; int tile = 0; // Zero is the default value to use if the registry is empty.
int stretch = 0;
if (SUCCEEDED(HrRegGetValueString(HKEY_CURRENT_USER, SZ_INISECTION_BACKGROUND, SZ_REGVALUE_TILEWALLPAPER, szSize, ARRAYSIZE(szSize)))) { tile = StrToInt(szSize); }
if (SUCCEEDED(HrRegGetValueString(HKEY_CURRENT_USER, SZ_INISECTION_BACKGROUND, SZ_REGVALUE_WALLPAPERSTYLE, szSize, ARRAYSIZE(szSize)))) { tile = (2 & StrToInt(szSize)); }
// If a theme is selected, and we are using a plus wall paper then
// find out if tiling is on, and what style to use from the ini file.
// Otherwise, we already got the information from the registry.
_getIntSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_TILEWALLPAPER, tile, &tile); _getIntSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_WALLPAPERSTYLE, stretch, &stretch);
stretch &= 2; _getIntSetting(SZ_INISECTION_MASTERSELECTOR, SZ_REGVALUE_STRETCH, stretch, &stretch);
if (tile) { *pnTile = BKDGT_TILE; } else if (stretch) { *pnTile = BKDGT_STRECH; } else { *pnTile = BKDGT_CENTER; }
hr = S_OK; }
return hr; }
HRESULT CThemeFile::put_BackgroundTile(IN enumBkgdTile nTile) { HRESULT hr = E_INVALIDARG;
switch (nTile) { case BKDGT_STRECH: hr = _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_TILEWALLPAPER, FALSE, TEXT("0")); hr = _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_WALLPAPERSTYLE, FALSE, TEXT("2")); break; case BKDGT_CENTER: hr = _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_TILEWALLPAPER, FALSE, TEXT("0")); hr = _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_WALLPAPERSTYLE, FALSE, TEXT("0")); break; case BKDGT_TILE: hr = _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_TILEWALLPAPER, FALSE, TEXT("1")); hr = _putThemeSetting(SZ_INISECTION_BACKGROUND, SZ_REGVALUE_WALLPAPERSTYLE, FALSE, TEXT("0")); break; };
return hr; }
HRESULT CThemeFile::get_VisualStyle(OUT BSTR * pbstrPath) { return _getThemeSetting(SZ_INISECTION_VISUALSTYLES, SZ_INIKEY_VISUALSTYLE, THEMESETTING_NORMAL, pbstrPath); }
HRESULT CThemeFile::put_VisualStyle(IN BSTR bstrPath) { return _putThemeSetting(SZ_INISECTION_VISUALSTYLES, SZ_INIKEY_VISUALSTYLE, TRUE, bstrPath); }
HRESULT CThemeFile::get_VisualStyleColor(OUT BSTR * pbstrPath) { return _getThemeSetting(SZ_INISECTION_VISUALSTYLES, SZ_INIKEY_VISUALSTYLECOLOR, THEMESETTING_NORMAL, pbstrPath); }
HRESULT CThemeFile::put_VisualStyleColor(IN BSTR bstrPath) { return _putThemeSetting(SZ_INISECTION_VISUALSTYLES, SZ_INIKEY_VISUALSTYLECOLOR, TRUE, bstrPath); }
HRESULT CThemeFile::get_VisualStyleSize(OUT BSTR * pbstrPath) { return _getThemeSetting(SZ_INISECTION_VISUALSTYLES, SZ_INIKEY_VISUALSTYLESIZE, THEMESETTING_NORMAL, pbstrPath); }
HRESULT CThemeFile::put_VisualStyleSize(IN BSTR bstrPath) { return _putThemeSetting(SZ_INISECTION_VISUALSTYLES, SZ_INIKEY_VISUALSTYLESIZE, TRUE, bstrPath); }
HRESULT CThemeFile::GetPath(IN VARIANT_BOOL fExpand, OUT BSTR * pbstrPath) { HRESULT hr = E_INVALIDARG;
if (pbstrPath && m_pszThemeFile) { TCHAR szPath[MAX_PATH];
StringCchCopy(szPath, ARRAYSIZE(szPath), m_pszThemeFile); if (VARIANT_TRUE == fExpand) { TCHAR szPathTemp[MAX_PATH]; if (SHExpandEnvironmentStrings(szPath, szPathTemp, ARRAYSIZE(szPathTemp))) { StringCchCopy(szPath, ARRAYSIZE(szPath), szPathTemp); } }
hr = HrSysAllocString(szPath, pbstrPath); }
return hr; }
HRESULT CThemeFile::SetPath(IN BSTR bstrPath) { HRESULT hr = E_INVALIDARG;
if (bstrPath) { Str_SetPtr(&m_pszThemeFile, bstrPath); hr = S_OK; }
return hr; }
HRESULT CThemeFile::GetCursor(IN BSTR bstrCursor, OUT BSTR * pbstrPath) { HRESULT hr = E_INVALIDARG;
if (pbstrPath) { *pbstrPath = NULL;
if (bstrCursor) { hr = _getThemeSetting(SZ_INISECTION_CURSORS, bstrCursor, THEMESETTING_LOADINDIRECT, pbstrPath); } }
return hr; }
HRESULT CThemeFile::SetCursor(IN BSTR bstrCursor, IN BSTR bstrPath) { HRESULT hr = E_INVALIDARG;
if (bstrCursor) { hr = _putThemeSetting(SZ_INISECTION_CURSORS, bstrCursor, TRUE, bstrPath); }
return hr; }
HRESULT CThemeFile::_GetSound(LPCWSTR pszSoundName, OUT BSTR * pbstrPath) { HRESULT hr = E_INVALIDARG;
if (pszSoundName && pbstrPath) { *pbstrPath = NULL; hr = _getThemeSetting(pszSoundName, SZ_INIKEY_DEFAULTVALUE, THEMESETTING_LOADINDIRECT, pbstrPath); }
return hr; }
HRESULT CThemeFile::GetSound(IN BSTR bstrSoundName, OUT BSTR * pbstrPath) { HRESULT hr = E_INVALIDARG;
if (pbstrPath) { *pbstrPath = NULL;
if (bstrSoundName) { hr = _GetSound(bstrSoundName, pbstrPath); if (FAILED(hr)) { int nIndex;
for (nIndex = 0; nIndex < ARRAYSIZE(s_ThemeSoundsValues); nIndex++) { if (!StrCmpI(bstrSoundName, s_ThemeSoundsValues[nIndex].pszRegKey)) { // First delete the value because we many need to switch from REG_SZ to REG_EXPAND_SZ
TCHAR szReplacement[MAX_PATH];
LoadString(HINST_THISDLL, s_ThemeSoundsValues[nIndex].nResourceID, szReplacement, ARRAYSIZE(szReplacement)); hr = HrSysAllocStringW(szReplacement, pbstrPath); break; } } } } }
return hr; }
HRESULT CThemeFile::SetSound(IN BSTR bstrSoundName, IN BSTR bstrPath) { HRESULT hr = E_INVALIDARG;
if (bstrSoundName && bstrPath) { hr = _putThemeSetting(bstrSoundName, SZ_INIKEY_DEFAULTVALUE, TRUE, bstrPath); }
return hr; }
HRESULT CThemeFile::GetIcon(IN BSTR bstrIconName, OUT BSTR * pbstrIconPath) { HRESULT hr = E_INVALIDARG;
if (pbstrIconPath) { *pbstrIconPath = NULL;
if (bstrIconName) { WCHAR szPath[MAX_URL_STRING]; WCHAR szIconType[MAX_PATH];
StringCchCopy(szPath, ARRAYSIZE(szPath), bstrIconName); LPWSTR pszSeparator = StrChrW(szPath, L':'); if (pszSeparator) { StringCchCopy(szIconType, ARRAYSIZE(szIconType), CharNext(pszSeparator)); pszSeparator[0] = 0; } else { // The caller should specify this but this is a safe fallback.
StringCchCopy(szIconType, ARRAYSIZE(szIconType), L"DefaultValue"); }
hr = _getThemeSetting(szPath, szIconType, THEMESETTING_NORMAL, pbstrIconPath); if (FAILED(hr)) { // The Plus! 98 format started adding "Software\Classes" to the path.
// So try that now.
// Plus!95 format: "[CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon]"
// Plus!98 format: "[Software\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon]"
WCHAR szPath98[MAX_URL_STRING];
StringCchPrintf(szPath98, ARRAYSIZE(szPath98), L"Software\\Classes\\%ls", szPath); hr = _getThemeSetting(szPath98, szIconType, THEMESETTING_NORMAL, pbstrIconPath); } } }
return hr; }
HRESULT CThemeFile::SetIcon(IN BSTR bstrIconName, IN BSTR bstrIconPath) { HRESULT hr = E_INVALIDARG;
if (bstrIconName && bstrIconPath) { WCHAR szPath[MAX_URL_STRING]; WCHAR szIconType[MAX_PATH];
StringCchCopy(szPath, ARRAYSIZE(szPath), bstrIconName); LPWSTR pszSeparator = StrChrW(szPath, L':'); if (pszSeparator) { StringCchCopy(szIconType, ARRAYSIZE(szIconType), CharNext(pszSeparator)); pszSeparator[0] = 0; } else { // The caller should specify this but this is a safe fallback.
StringCchCopy(szIconType, ARRAYSIZE(szIconType), L"DefaultValue"); }
hr = _putThemeSetting(szPath, szIconType, TRUE, bstrIconPath); }
return hr; }
//===========================
// *** IPropertyBag Interface ***
//===========================
HRESULT CThemeFile::Read(IN LPCOLESTR pszPropName, IN VARIANT * pVar, IN IErrorLog *pErrorLog) { HRESULT hr = E_INVALIDARG;
if (pszPropName && pVar) { if (!StrCmpW(pszPropName, SZ_PBPROP_SYSTEM_METRICS)) { hr = _LoadSettings();
// This is pretty ugly.
pVar->vt = VT_BYREF; pVar->byref = &m_systemMetrics; } else if (!StrCmpW(pszPropName, SZ_PBPROP_HASSYSMETRICS)) { hr = _LoadSettings();
pVar->vt = VT_BOOL; pVar->boolVal = VARIANT_FALSE; if (SUCCEEDED(hr)) { TCHAR szIconMetrics[2048]; if (GetPrivateProfileString(SZ_INISECTION_METRICS, SZ_INIKEY_ICONMETRICS, SZ_EMPTY, szIconMetrics, ARRAYSIZE(szIconMetrics), m_pszThemeFile)) { if (GetPrivateProfileString(SZ_INISECTION_METRICS, SZ_INIKEY_NONCLIENTMETRICS, SZ_EMPTY, szIconMetrics, ARRAYSIZE(szIconMetrics), m_pszThemeFile)) { GetPrivateProfileString(SZ_INISECTION_COLORS, s_pszColorNames[COLOR_ACTIVECAPTION], SZ_EMPTY, szIconMetrics, ARRAYSIZE(szIconMetrics), m_pszThemeFile); pVar->boolVal = (szIconMetrics[0] ? VARIANT_TRUE : VARIANT_FALSE); } } } } }
return hr; }
HRESULT CThemeFile::Write(IN LPCOLESTR pszPropName, IN VARIANT *pVar) { HRESULT hr = E_NOTIMPL;
if (pszPropName && pVar) { if (!StrCmpW(pszPropName, SZ_PBPROP_APPLY_THEMEFILE)) { VariantInit(pVar); hr = _ApplyThemeSettings(); // This will do nothing if already loaded.
} else if (!StrCmpW(pszPropName, SZ_PBPROP_SYSTEM_METRICS) && (VT_BYREF == pVar->vt) && pVar->byref) { SYSTEMMETRICSALL * pCurrent = (SYSTEMMETRICSALL *) pVar->byref;
// The caller will pass SYSTEMMETRICS in the live system DPI.
hr = _SaveSystemMetrics(pCurrent); } }
return hr; }
//===========================
// *** IUnknown Interface ***
//===========================
ULONG CThemeFile::AddRef() { return InterlockedIncrement(&m_cRef); }
ULONG CThemeFile::Release() { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
HRESULT CThemeFile::QueryInterface(REFIID riid, void **ppvObj) { static const QITAB qit[] = { QITABENT(CThemeFile, IObjectWithSite), QITABENT(CThemeFile, IPropertyBag), QITABENT(CThemeFile, ITheme), QITABENT(CThemeFile, IDispatch), { 0 }, };
return QISearch(this, qit, riid, ppvObj); }
//===========================
// *** Class Methods ***
//===========================
CThemeFile::CThemeFile(LPCTSTR pszThemeFile) : m_cRef(1) { DllAddRef();
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
m_dwCachedState = 0xFFFFFFFF;
InitFrost(); }
CThemeFile::~CThemeFile() { Str_SetPtr(&m_pszThemeFile, NULL);
DllRelease(); }
HRESULT CThemeFile_CreateInstance(IN LPCWSTR pszThemeFile, OUT ITheme ** ppTheme) { HRESULT hr = E_INVALIDARG;
if (ppTheme) { CThemeFile * pObject = new CThemeFile(pszThemeFile);
hr = E_OUTOFMEMORY; *ppTheme = NULL; if (pObject) { hr = pObject->SetPath((BSTR)pszThemeFile); if (SUCCEEDED(hr)) { hr = pObject->QueryInterface(IID_PPV_ARG(ITheme, ppTheme)); }
pObject->Release(); } }
return hr; }
|