windows-nt/Source/XPSP1/NT/shell/themes/themeui/regutil.cpp

830 lines
32 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*****************************************************************************\
FILE: regutil.cpp
DESCRIPTION:
This file will contain helper functions to load and save values to the
registry that are theme related.
BryanSt 3/24/2000
Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
\*****************************************************************************/
#include "priv.h"
#include "regutil.h"
EXTERN_C void FAR SetMagicColors(HDC, DWORD, WORD);
// strings for color names in "WIN.INI".
PTSTR s_pszColorNames[] = {
/* COLOR_SCROLLBAR */ TEXT("Scrollbar"), // 0
/* COLOR_DESKTOP */ TEXT("Background"),
/* COLOR_ACTIVECAPTION */ TEXT("ActiveTitle"),
/* COLOR_INACTIVECAPTION */ TEXT("InactiveTitle"),
/* COLOR_MENU */ TEXT("Menu"),
/* COLOR_WINDOW */ TEXT("Window"), // 5
/* COLOR_WINDOWFRAME */ TEXT("WindowFrame"),
/* COLOR_MENUTEXT */ TEXT("MenuText"),
/* COLOR_WINDOWTEXT */ TEXT("WindowText"),
/* COLOR_CAPTIONTEXT */ TEXT("TitleText"),
/* COLOR_ACTIVEBORDER */ TEXT("ActiveBorder"), // 10
/* COLOR_INACTIVEBORDER */ TEXT("InactiveBorder"),
/* COLOR_APPWORKSPACE */ TEXT("AppWorkspace"),
/* COLOR_HIGHLIGHT */ TEXT("Hilight"),
/* COLOR_HIGHLIGHTTEXT */ TEXT("HilightText"),
/* COLOR_3DFACE */ TEXT("ButtonFace"), // 15
/* COLOR_3DSHADOW */ TEXT("ButtonShadow"),
/* COLOR_GRAYTEXT */ TEXT("GrayText"),
/* COLOR_BTNTEXT */ TEXT("ButtonText"),
/* COLOR_INACTIVECAPTIONTEXT */ TEXT("InactiveTitleText"),
/* COLOR_3DHILIGHT */ TEXT("ButtonHilight"), // 20
/* COLOR_3DDKSHADOW */ TEXT("ButtonDkShadow"),
/* COLOR_3DLIGHT */ TEXT("ButtonLight"),
/* COLOR_INFOTEXT */ TEXT("InfoText"),
/* COLOR_INFOBK */ TEXT("InfoWindow"),
/* COLOR_3DALTFACE */ TEXT("ButtonAlternateFace"), // 25
/* COLOR_HOTLIGHT */ TEXT("HotTrackingColor"),
/* COLOR_GRADIENTACTIVECAPTION */ TEXT("GradientActiveTitle"),
/* COLOR_GRADIENTINACTIVECAPTION */ TEXT("GradientInactiveTitle"),
/* COLOR_MENUHILIGHT */ TEXT("MenuHilight"), // 29
/* COLOR_MENUBAR */ TEXT("MenuBar"), // 30
};
// What about: AppWorkSpace
#define SZ_DEFAULT_FONT TEXT("Tahoma")
/////////////////////////////////////////////////////////////////////
// Private Functions
/////////////////////////////////////////////////////////////////////
HRESULT DPIConvert_SystemMetricsAll(BOOL fScaleSizes, SYSTEMMETRICSALL * pStateToModify, int nFromDPI, int nToDPI)
{
pStateToModify->schemeData.ncm.lfCaptionFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfCaptionFont.lfHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.lfSmCaptionFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfSmCaptionFont.lfHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.lfMenuFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfMenuFont.lfHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.lfStatusFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfStatusFont.lfHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.lfMessageFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfMessageFont.lfHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.lfIconTitle.lfHeight = MulDiv(pStateToModify->schemeData.lfIconTitle.lfHeight, nToDPI, nFromDPI);
// Someone (NTUSER?) scales sizes for us. So we don't need to do that in some cases.
if (fScaleSizes)
{
pStateToModify->schemeData.ncm.iBorderWidth = MulDiv(pStateToModify->schemeData.ncm.iBorderWidth, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iScrollWidth = MulDiv(pStateToModify->schemeData.ncm.iScrollWidth, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iScrollHeight = MulDiv(pStateToModify->schemeData.ncm.iScrollHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iCaptionWidth = MulDiv(pStateToModify->schemeData.ncm.iCaptionWidth, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iCaptionHeight = MulDiv(pStateToModify->schemeData.ncm.iCaptionHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iSmCaptionWidth = MulDiv(pStateToModify->schemeData.ncm.iSmCaptionWidth, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iSmCaptionHeight = MulDiv(pStateToModify->schemeData.ncm.iSmCaptionHeight, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iMenuWidth = MulDiv(pStateToModify->schemeData.ncm.iMenuWidth, nToDPI, nFromDPI);
pStateToModify->schemeData.ncm.iMenuHeight = MulDiv(pStateToModify->schemeData.ncm.iMenuHeight, nToDPI, nFromDPI);
}
return S_OK;
}
HRESULT DPIConvert_SystemMetricsAll_PersistToLive(BOOL fScaleSizes, SYSTEMMETRICSALL * pStateToModify, int nNewDPI)
{
return DPIConvert_SystemMetricsAll(fScaleSizes, pStateToModify, DPI_PERSISTED, nNewDPI);
}
HRESULT DPIConvert_SystemMetricsAll_LiveToPersist(BOOL fScaleSizes, SYSTEMMETRICSALL * pStateToModify, int nNewDPI)
{
return DPIConvert_SystemMetricsAll(fScaleSizes, pStateToModify, nNewDPI, DPI_PERSISTED);
}
HRESULT Look_GetSchemeData(IN HKEY hkSchemes, IN LPCTSTR pszSchemeName, IN SCHEMEDATA *psd)
{
HRESULT hr;
DWORD dwType = REG_BINARY;
DWORD dwSize = sizeof(*psd);
hr = HrRegQueryValueEx(hkSchemes, pszSchemeName, NULL, &dwType, (LPBYTE)psd, &dwSize);
if (SUCCEEDED(hr))
{
hr = E_FAIL;
if (psd->version == SCHEME_VERSION)
{
hr = S_OK;
}
}
return hr; //Yes there is a current scheme and there is valid data!
}
// This function reads the current scheme's name and associated scheme data from registry.
//
// This function returns FALSE, if there is no current scheme.
HRESULT Look_GetCurSchemeNameAndData(IN SCHEMEDATA *psd, IN LPTSTR lpszSchemeName, IN int cbSize)
{
HKEY hkAppearance;
HRESULT hr;
//Get the current scheme.
hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_APPEARANCE, 0, KEY_READ, &hkAppearance);
if (SUCCEEDED(hr))
{
DWORD dwSize;
dwSize = cbSize;
hr = HrRegQueryValueEx(hkAppearance, REGSTR_KEY_CURRENT, NULL, NULL, (LPBYTE)lpszSchemeName, &dwSize);
if (SUCCEEDED(hr))
{
HKEY hkSchemes;
//Open the schemes key!
hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_LOOKSCHEMES, 0, KEY_READ, &hkSchemes);
if (SUCCEEDED(hr))
{
hr = Look_GetSchemeData(hkSchemes, lpszSchemeName, psd);
RegCloseKey(hkSchemes);
}
}
RegCloseKey(hkAppearance);
}
return hr; //Yes there is a current scheme and there is valid data!
}
/////////////////////////////////////////////////////////////////////
// Public Functions
/////////////////////////////////////////////////////////////////////
HRESULT IconSize_Load(IN int * pnDXIcon, IN int * pnDYIcon, IN int * pnIcon, IN int * pnSmallIcon)
{
TCHAR szSize[8];
DWORD cbSize = sizeof(szSize);
// default shell icon sizes
*pnIcon = ClassicGetSystemMetrics(SM_CXICON);
*pnSmallIcon = ((*pnIcon) / 2);
HRESULT hr = HrSHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE, NULL, (LPBYTE)szSize, &cbSize);
if (SUCCEEDED(hr))
{
*pnIcon = StrToInt(szSize);
}
cbSize = sizeof(szSize);
hr = HrSHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_SMALLICONSIZE, NULL, (LPBYTE)szSize, &cbSize);
if (SUCCEEDED(hr))
{
*pnSmallIcon = StrToInt(szSize);
}
*pnDXIcon = (ClassicGetSystemMetrics(SM_CXICONSPACING) - *pnIcon);
if (*pnDXIcon < 0)
{
*pnDXIcon = 0;
}
*pnDYIcon = (ClassicGetSystemMetrics(SM_CYICONSPACING) - *pnIcon);
if (*pnDYIcon < 0)
{
*pnDYIcon = 0;
}
return S_OK;
}
HRESULT IconSize_Save(IN int nDXIcon, IN int nDYIcon, IN int nIcon, IN int nSmallIcon)
{
HRESULT hr = E_INVALIDARG;
AssertMsg((0 != nIcon), TEXT("We should never save an icon size of zero."));
AssertMsg((0 != nSmallIcon), TEXT("We should never save an small icon size of zero."));
if (nIcon && nSmallIcon)
{
TCHAR szSize[8];
wnsprintf(szSize, ARRAYSIZE(szSize), TEXT("%d"), nIcon);
hr = HrSHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE,
REG_SZ, (LPBYTE)szSize, sizeof(szSize[0]) * (lstrlen(szSize) + 1));
#ifdef THE_SHELL_CAN_HANDLE_CUSTOM_SMALL_ICON_SIZES_YET
wnsprintf(szSize, ARRAYSIZE(szSize), TEXT("%d"), nSmallIcon);
hr = HrSHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_SMALLICONSIZE,
REG_SZ, (LPBYTE)szSize, sizeof(szSize[0]) * (lstrlen(szSize) + 1));
#endif
}
// WM_SETTINGCHANGE needs to be sent for this to update. The caller needs to do that.
return hr;
}
DWORD SetHighContrastAsync_WorkerThread(IN void *pv)
{
BOOL fHighContrast = (BOOL) PtrToInt(pv);
HIGHCONTRAST hc = {0};
TCHAR szFlags[MAX_PATH];
if (SUCCEEDED(HrRegGetValueString(HKEY_CURRENT_USER, SZ_REGKEY_ACCESS_HIGHCONTRAST, SZ_REGVALUE_ACCESS_HCFLAGS, szFlags, ARRAYSIZE(szFlags))))
{
DWORD dwFlags = StrToInt(szFlags);
// Do async:
hc.cbSize = sizeof(hc);
if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, 0))
{
BOOL fCurrentlySet = (dwFlags & HCF_HIGHCONTRASTON); // I check the flags in the registry because USER32 may be out of date.
// Only do the broadcast if it changed
if (fHighContrast != fCurrentlySet)
{
if (fHighContrast)
{
hc.dwFlags |= HCF_HIGHCONTRASTON; // Add the bit.
}
else
{
hc.dwFlags &= ~HCF_HIGHCONTRASTON; // Clear the bit.
}
wnsprintf(szFlags, ARRAYSIZE(szFlags), TEXT("%d"), hc.dwFlags);
HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_ACCESS_HIGHCONTRAST, SZ_REGVALUE_ACCESS_HCFLAGS, szFlags);
SendMessage(HWND_BROADCAST, WM_WININICHANGE, SPI_SETHIGHCONTRAST, (LPARAM)&hc);
}
}
}
return 0;
}
void AssertPositiveFontSizes(SYSTEMMETRICSALL * pState)
{
// NTUSER will incorrectly scale positive LOGFONT lfHeights so we need to verify
// that we always set negative sizes.
AssertMsg((0 > pState->schemeData.lfIconTitle.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfIconTitle)"));
AssertMsg((0 > pState->schemeData.ncm.lfCaptionFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfCaptionFont)"));
AssertMsg((0 > pState->schemeData.ncm.lfMenuFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfMenuFont)"));
AssertMsg((0 > pState->schemeData.ncm.lfMessageFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfMessageFont)"));
AssertMsg((0 > pState->schemeData.ncm.lfSmCaptionFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfSmCaptionFont)"));
AssertMsg((0 > pState->schemeData.ncm.lfStatusFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfStatusFont)"));
}
#define SZ_INILABLE_COLORS TEXT("colors") // colors section name
/*
** set all of the data to the system.
**
** COMPATIBILITY NOTE:
** EXCEL 5.0 people hook metrics changes off of WM_SYSCOLORCHANGE
** instead of WM_WININICHANGE. Windows 3.1's Desktop applet always sent
** both when the metrics were updated, so nobody noticed this bug.
** Be careful when re-arranging this function...
**
*/
HRESULT SystemMetricsAll_Set(IN SYSTEMMETRICSALL * pState, CDimmedWindow* pDimmedWindow)
{
// COMPATIBILITY:
// Do metrics first since the color stuff might cause USER to generate a
// WM_SYSCOLORCHANGE message and we don't want to send two of them...
TraceMsg(TF_THEMEUI_SYSMETRICS, "desk.cpl: _SetSysStuff");
SystemParametersInfoAsync(SPI_SETFLATMENU, NULL, IntToPtr(pState->fFlatMenus), 0, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
AssertMsg((0 != pState->nIcon), TEXT("We should never save an icon size of zero."));
AssertMsg((0 != pState->nSmallIcon), TEXT("We should never save an small icon size of zero."));
// NOTE: It would be nice to create one background thread and then make the 1 or 5 ClassicSystemParametersInfo()
// calls on that single thread.
if ((pState->dwChanged & METRIC_CHANGE) && pState->nIcon && pState->nSmallIcon)
{
HKEY hkey;
TraceMsg(TF_THEMEUI_SYSMETRICS, "desk.cpl: Metrics Changed");
TraceMsg(TF_THEMEUI_SYSMETRICS, "desk.cpl: Calling SPI_SETNONCLIENTMETRICS");
pState->schemeData.ncm.cbSize = sizeof(pState->schemeData.ncm);
AssertPositiveFontSizes(pState);
SystemParametersInfoAsync(SPI_SETNONCLIENTMETRICS, sizeof(pState->schemeData.ncm), (void far *)(LPNONCLIENTMETRICS)&(pState->schemeData.ncm),
sizeof(pState->schemeData.ncm), (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Calling SPI_SETICONTITLELOGFONT");
SystemParametersInfoAsync(SPI_SETICONTITLELOGFONT, sizeof(LOGFONT), (void far *)(LPLOGFONT)&(pState->schemeData.lfIconTitle),
sizeof(pState->schemeData.lfIconTitle), (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Calling SPI_ICONHORIZONTALSPACING");
SystemParametersInfoAsync(SPI_ICONHORIZONTALSPACING, pState->nDXIcon + pState->nIcon, NULL, 0, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Calling SPI_ICONVERTICALSPACING");
SystemParametersInfoAsync(SPI_ICONVERTICALSPACING, pState->nDYIcon + pState->nIcon, NULL, 0, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Done calling SPI's");
if (RegCreateKey(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, &hkey) == ERROR_SUCCESS)
{
TCHAR val[8];
AssertMsg((0 != pState->nIcon), TEXT("pState->nIcon should never be zero (0)."));
wsprintf(val, TEXT("%d"), pState->nIcon);
RegSetValueEx(hkey, SZ_REGVALUE_ICONSIZE, 0, REG_SZ, (LPBYTE)&val, SIZEOF(TCHAR) * (lstrlen(val) + 1));
#ifdef THE_SHELL_CAN_HANDLE_CUSTOM_SMALL_ICON_SIZES_YET
AssertMsg((0 != pState->nSmallIcon), TEXT("pState->nIcon should never be zero (0)."));
wsprintf(val, TEXT("%d"), pState->nSmallIcon);
RegSetValueEx(hkey, SZ_REGVALUE_SMALLICONSIZE, 0, REG_SZ, (LPBYTE)&val, SIZEOF(TCHAR) * (lstrlen(val) + 1));
#else
// RegDeleteValue(hkey, SZ_REGVALUE_SMALLICONSIZE);
#endif
RegCloseKey(hkey);
}
// WM_SETTINGCHANGE is sent at the end of the function
}
if (pState->dwChanged & COLOR_CHANGE)
{
int i;
int iColors[COLOR_MAX];
COLORREF rgbColors[COLOR_MAX];
TCHAR szRGB[32];
COLORREF rgb;
HKEY hk;
HDC hdc;
// restore magic colors back to Win31 defaults.
hdc = GetDC(NULL);
SetMagicColors(hdc, 0x00c0dcc0, 8); // money green
SetMagicColors(hdc, 0x00f0caa6, 9); // IBM blue
SetMagicColors(hdc, 0x00f0fbff, 246); // off white
ReleaseDC(NULL, hdc);
// -------------------------------------------------
// This call causes user to send a WM_SYSCOLORCHANGE
// -------------------------------------------------
for (i=0; i < COLOR_MAX; i++)
{
iColors[i] = i;
rgbColors[i] = pState->schemeData.rgb[i] & 0x00FFFFFF;
}
SetSysColors(ARRAYSIZE(rgbColors), iColors, rgbColors);
if (RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_COLORS, &hk) == ERROR_SUCCESS)
{
// write out the color information to win.ini
for (i = 0; i < COLOR_MAX; i++)
{
rgb = pState->schemeData.rgb[i];
wsprintf(szRGB, TEXT("%d %d %d"), GetRValue(rgb), GetGValue(rgb), GetBValue(rgb));
// For the time being we will update the INI file also.
WriteProfileString(SZ_INILABLE_COLORS, s_pszColorNames[i], szRGB);
// Update the registry (Be sure to include the terminating zero in the byte count!)
RegSetValueEx(hk, s_pszColorNames[i], 0L, REG_SZ, (LPBYTE)szRGB, SIZEOF(TCHAR) * (lstrlen(szRGB)+1));
TraceMsg(TF_THEMEUI_SYSMETRICS, "CPL:Write Color: %s=%s\n\r",s_pszColorNames[i], szRGB);
}
RegCloseKey(hk);
}
}
else if (pState->dwChanged & METRIC_CHANGE)
{
// COMPATIBILITY HACK:
// no colors were changed, but metrics were
// EXCEL 5.0 people tied metrics changes to WM_SYSCOLORCHANGE
// and ignore the WM_WININICHANGE (now called WM_SETTINGCHANGE)
// send a bogus WM_SYSCOLORCHANGE
PostMessageBroadAsync(WM_SYSCOLORCHANGE, 0, 0);
}
// if metrics changed at all send a WM_SETTINGCHANGE
if (pState->dwChanged & METRIC_CHANGE)
{
PostMessageBroadAsync(WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
}
#ifdef FEATURE_SETHIGHCONTRASTSPI
// Start up a new thread and send this:
SPICreateThread(SetHighContrastAsync_WorkerThread, (void *)pState->fHighContrast);
#endif // FEATURE_SETHIGHCONTRASTSPI
return S_OK;
}
HRESULT SystemMetricsAll_Get(IN SYSTEMMETRICSALL * pState)
{
HKEY hkey;
// sizes and fonts
pState->schemeData.ncm.cbSize = sizeof(pState->schemeData.ncm);
ClassicSystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(pState->schemeData.ncm), (void far *)(LPNONCLIENTMETRICS)&(pState->schemeData.ncm), FALSE);
ClassicSystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), (void far *)(LPLOGFONT)&(pState->schemeData.lfIconTitle), FALSE);
// default shell icon sizes
pState->nIcon = ClassicGetSystemMetrics(SM_CXICON);
pState->nSmallIcon = pState->nIcon / 2;
ClassicSystemParametersInfo(SPI_GETFLATMENU, NULL, &pState->fFlatMenus, 0);
if (RegOpenKey(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, &hkey) == ERROR_SUCCESS)
{
TCHAR val[8];
LONG len = sizeof(val);
if (RegQueryValueEx(hkey, SZ_REGVALUE_ICONSIZE, 0, NULL, (LPBYTE)&val, (LPDWORD)&len) == ERROR_SUCCESS)
{
pState->nIcon = StrToInt(val);
}
len = SIZEOF(val);
if (RegQueryValueEx(hkey, SZ_REGVALUE_SMALLICONSIZE, 0, NULL, (LPBYTE)&val, (LPDWORD)&len) == ERROR_SUCCESS)
{
pState->nSmallIcon = StrToInt(val);
}
RegCloseKey(hkey);
}
pState->nDXIcon = ClassicGetSystemMetrics(SM_CXICONSPACING) - pState->nIcon;
if (pState->nDXIcon < 0)
{
pState->nDXIcon = 0;
}
pState->nDYIcon = ClassicGetSystemMetrics(SM_CYICONSPACING) - pState->nIcon;
if (pState->nDYIcon < 0)
{
pState->nDYIcon = 0;
}
// system colors
for (int nIndex = 0; nIndex < COLOR_MAX; nIndex++)
{
pState->schemeData.rgb[nIndex] = GetSysColor(nIndex);
}
HIGHCONTRAST hc = {0};
TCHAR szTemp[MAX_PATH];
szTemp[0] = 0;
hc.cbSize = sizeof(hc);
if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, 0))
{
pState->fHighContrast = ((hc.dwFlags & HCF_HIGHCONTRASTON) ? TRUE : FALSE);
}
else
{
pState->fHighContrast = FALSE;
}
return S_OK;
}
HRESULT SystemMetricsAll_Copy(IN SYSTEMMETRICSALL * pStateSource, IN SYSTEMMETRICSALL * pStateDest)
{
CopyMemory(pStateDest, pStateSource, sizeof(*pStateDest));
return S_OK;
}
HRESULT SystemMetricsAll_Load(IN IThemeSize * pSizeToLoadFrom, IN SYSTEMMETRICSALL * pStateToLoad, IN const int * pnNewDPI)
{
HRESULT hr = E_INVALIDARG;
if (pSizeToLoadFrom && pStateToLoad)
{
pStateToLoad->schemeData.ncm.cbSize = sizeof(pStateToLoad->schemeData.ncm);
pStateToLoad->schemeData.version = SCHEME_VERSION;
pStateToLoad->schemeData.wDummy = 0;
// Load Behavior System Metrics
IPropertyBag * pPropertyBag;
VARIANT var;
var.boolVal = VARIANT_FALSE;
hr = pSizeToLoadFrom->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
if (SUCCEEDED(hr))
{
hr = pPropertyBag->Read(SZ_PBPROP_VSBEHAVIOR_FLATMENUS, &var, NULL);
pPropertyBag->Release();
}
if (SUCCEEDED(hr))
{
pStateToLoad->fFlatMenus = (VARIANT_TRUE == var.boolVal);
// Load Fonts
hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_CAPTIONFONT, &pStateToLoad->schemeData.ncm.lfCaptionFont);
if (SUCCEEDED(hr))
{
hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_SMCAPTIONFONT, &pStateToLoad->schemeData.ncm.lfSmCaptionFont);
hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_MENUFONT, &pStateToLoad->schemeData.ncm.lfMenuFont);
hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_STATUSFONT, &pStateToLoad->schemeData.ncm.lfStatusFont);
hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_MESSAGEFONT, &pStateToLoad->schemeData.ncm.lfMessageFont);
hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_ICONTITLEFONT, &pStateToLoad->schemeData.lfIconTitle);
// Load Sizes
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_BORDERWIDTH, &pStateToLoad->schemeData.ncm.iBorderWidth);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SCROLLWIDTH, &pStateToLoad->schemeData.ncm.iScrollWidth);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SCROLLHEIGHT, &pStateToLoad->schemeData.ncm.iScrollHeight);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_CAPTIONWIDTH, &pStateToLoad->schemeData.ncm.iCaptionWidth);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_CAPTIONHEIGHT, &pStateToLoad->schemeData.ncm.iCaptionHeight);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SMCAPTIONWIDTH, &pStateToLoad->schemeData.ncm.iSmCaptionWidth);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SMCAPTIONHEIGHT, &pStateToLoad->schemeData.ncm.iSmCaptionHeight);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_MENUWIDTH, &pStateToLoad->schemeData.ncm.iMenuWidth);
hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_MENUHEIGHT, &pStateToLoad->schemeData.ncm.iMenuHeight);
// Load Color
hr = S_OK;
for (int nIndex = 0; SUCCEEDED(hr) && (nIndex < ARRAYSIZE(pStateToLoad->schemeData.rgb)); nIndex++)
{
hr = pSizeToLoadFrom->get_SystemMetricColor(nIndex, &pStateToLoad->schemeData.rgb[nIndex]);
}
if (pnNewDPI)
{
// We need to scale the fonts to fit correctly on the current monitor's DPI.
LogSystemMetrics("SystemMetricsAll_Load() BEFORE P->DPI loading AppearSchm", pStateToLoad);
DPIConvert_SystemMetricsAll_PersistToLive(TRUE, pStateToLoad, *pnNewDPI);
LogSystemMetrics("SystemMetricsAll_Load() AFTER P->DPI loading AppearSchm", pStateToLoad);
}
}
}
}
if (SUCCEEDED(hr))
{
hr = IconSize_Load(&pStateToLoad->nDXIcon, &pStateToLoad->nDYIcon, &pStateToLoad->nIcon, &pStateToLoad->nSmallIcon);
}
if (SUCCEEDED(hr))
{
enumThemeContrastLevels ContrastLevel = CONTRAST_NORMAL;
if (FAILED(pSizeToLoadFrom->get_ContrastLevel(&ContrastLevel)))
{
ContrastLevel = CONTRAST_NORMAL;
}
pStateToLoad->fHighContrast = ((CONTRAST_NORMAL == ContrastLevel) ? FALSE : TRUE);
}
return hr;
}
// Copy the settings from pStateToLoad to pSizeToLoadFrom.
HRESULT SystemMetricsAll_Save(IN SYSTEMMETRICSALL * pState, IN IThemeSize * pSizeToSaveTo, IN const int * pnNewDPI)
{
HRESULT hr = E_INVALIDARG;
if (pSizeToSaveTo && pState)
{
pState->schemeData.ncm.cbSize = sizeof(pState->schemeData.ncm);
pState->schemeData.version = SCHEME_VERSION;
pState->schemeData.wDummy = 0;
// Load Behavior System Metrics
IPropertyBag * pPropertyBag;
hr = pSizeToSaveTo->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
if (SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BOOL;
var.boolVal = (pState->fFlatMenus ? VARIANT_TRUE : VARIANT_FALSE);
hr = pPropertyBag->Write(SZ_PBPROP_VSBEHAVIOR_FLATMENUS, &var);
pPropertyBag->Release();
}
if (pnNewDPI)
{
// We need to scale the fonts & sizes to be current DPI independent
LogSystemMetrics("SystemMetricsAll_Save() BEFORE DPI->P to save AppearSchm", pState);
DPIConvert_SystemMetricsAll_LiveToPersist(TRUE, pState, *pnNewDPI);
LogSystemMetrics("SystemMetricsAll_Save() AFTER DPI->P to save AppearSchm", pState);
}
// Load Fonts
hr = pSizeToSaveTo->PutSystemMetricFont(SMF_CAPTIONFONT, &pState->schemeData.ncm.lfCaptionFont);
hr = pSizeToSaveTo->PutSystemMetricFont(SMF_SMCAPTIONFONT, &pState->schemeData.ncm.lfSmCaptionFont);
hr = pSizeToSaveTo->PutSystemMetricFont(SMF_MENUFONT, &pState->schemeData.ncm.lfMenuFont);
hr = pSizeToSaveTo->PutSystemMetricFont(SMF_STATUSFONT, &pState->schemeData.ncm.lfStatusFont);
hr = pSizeToSaveTo->PutSystemMetricFont(SMF_MESSAGEFONT, &pState->schemeData.ncm.lfMessageFont);
hr = pSizeToSaveTo->PutSystemMetricFont(SMF_ICONTITLEFONT, &pState->schemeData.lfIconTitle);
// Load Sizes
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_BORDERWIDTH, pState->schemeData.ncm.iBorderWidth);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SCROLLWIDTH, pState->schemeData.ncm.iScrollWidth);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SCROLLHEIGHT, pState->schemeData.ncm.iScrollHeight);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_CAPTIONWIDTH, pState->schemeData.ncm.iCaptionWidth);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_CAPTIONHEIGHT, pState->schemeData.ncm.iCaptionHeight);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SMCAPTIONWIDTH, pState->schemeData.ncm.iSmCaptionWidth);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SMCAPTIONHEIGHT, pState->schemeData.ncm.iSmCaptionHeight);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_MENUWIDTH, pState->schemeData.ncm.iMenuWidth);
hr = pSizeToSaveTo->put_SystemMetricSize(SMS_MENUHEIGHT, pState->schemeData.ncm.iMenuHeight);
// Load Color
for (int nIndex = 0; nIndex < ARRAYSIZE(pState->schemeData.rgb); nIndex++)
{
hr = pSizeToSaveTo->put_SystemMetricColor(nIndex, pState->schemeData.rgb[nIndex]);
}
}
// We don't save the icon info if it is zero. It should never be NULL in normal cases, except when
// we are converting the settings in the upgrade case.
if (SUCCEEDED(hr) && pState->nIcon)
{
hr = IconSize_Save(pState->nDXIcon, pState->nDYIcon, pState->nIcon, pState->nSmallIcon);
}
if (SUCCEEDED(hr))
{
enumThemeContrastLevels ContrastLevel = (pState->fHighContrast ? CONTRAST_HIGHBLACK : CONTRAST_NORMAL);
pSizeToSaveTo->put_ContrastLevel(ContrastLevel);
}
return hr;
}
BOOL _GetRegValueString(HKEY hKey, LPCTSTR lpszValName, LPTSTR pszString, int cchSize)
{
DWORD cbSize = sizeof(pszString[0]) * cchSize;
DWORD dwType;
DWORD dwError = RegQueryValueEx(hKey, lpszValName, NULL, &dwType, (LPBYTE)pszString, &cbSize);
return (ERROR_SUCCESS == dwError);
}
//------------------------------------------------------------------------------------
// SetRegValueString()
//
// Just a little helper routine that takes string and writes it to the registry.
// Returns: success writing to Registry, should be always TRUE.
//------------------------------------------------------------------------------------
BOOL SetRegValueString(HKEY hMainKey, LPCTSTR pszSubKey, LPCTSTR pszRegValue, LPCTSTR pszString)
{
HKEY hKey;
BOOL fSucceeded = FALSE;
DWORD dwDisposition;
DWORD dwError = RegCreateKeyEx(hMainKey, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
if (ERROR_SUCCESS == dwError)
{
dwError = SHRegSetPath(hKey, NULL, pszRegValue, pszString, 0);
if (ERROR_SUCCESS == dwError)
{
fSucceeded = TRUE;
}
RegCloseKey(hKey);
}
return fSucceeded;
}
//------------------------------------------------------------------------------------
// GetRegValueString()
//
// Just a little helper routine, gets an individual string value from the
// registry and returns it to the caller. Takes care of registry headaches,
// including a paranoid length check before getting the string.
//
// Returns: success of string retrieval
//------------------------------------------------------------------------------------
BOOL GetRegValueString( HKEY hMainKey, LPCTSTR lpszSubKey, LPCTSTR lpszValName, LPTSTR lpszValue, int iMaxSize )
{
HKEY hKey; // cur open key
LONG lRet = RegOpenKeyEx( hMainKey, lpszSubKey, (DWORD)0, KEY_QUERY_VALUE, (PHKEY)&hKey );
if( lRet == ERROR_SUCCESS )
{
BOOL fRet = _GetRegValueString(hKey, lpszValName, lpszValue, iMaxSize);
// close subkey
RegCloseKey( hKey );
return fRet;
}
return FALSE;
}
//------------------------------------------------------------------------------------
// SetRegValueDword()
//
// Just a little helper routine that takes an dword and writes it to the
// supplied location.
//
// Returns: success writing to Registry, should be always TRUE.
//------------------------------------------------------------------------------------
BOOL SetRegValueDword( HKEY hk, LPCTSTR pSubKey, LPCTSTR pValue, DWORD dwVal )
{
HKEY hkey = NULL;
BOOL bRet = FALSE;
if (ERROR_SUCCESS == RegOpenKey( hk, pSubKey, &hkey ))
{
if (ERROR_SUCCESS == RegSetValueEx(hkey, pValue, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD)))
{
bRet = TRUE;
}
}
if (hkey)
{
RegCloseKey( hkey );
}
return bRet;
}
//------------------------------------------------------------------------------------
// GetRegValueDword()
//
// Just a little helper routine that takes an dword and writes it to the
// supplied location.
//
// Returns: success writing to Registry, should be always TRUE.
//------------------------------------------------------------------------------------
DWORD GetRegValueDword( HKEY hk, LPCTSTR pSubKey, LPCTSTR pValue )
{
HKEY hkey = NULL;
DWORD dwVal = REG_BAD_DWORD;
if (ERROR_SUCCESS == RegOpenKey( hk, pSubKey, &hkey ))
{
DWORD dwType, dwSize = sizeof(DWORD);
RegQueryValueEx( hkey, pValue, NULL, &dwType, (LPBYTE)&dwVal, &dwSize );
}
if (hkey)
{
RegCloseKey( hkey );
}
return dwVal;
}
//------------------------------------------------------------------------------------
// SetRegValueInt()
//
// Just a little helper routine that takes an int and writes it as a string to the
// registry.
//
// Returns: success writing to Registry, should be always TRUE.
//------------------------------------------------------------------------------------
BOOL SetRegValueInt( HKEY hMainKey, LPCTSTR lpszSubKey, LPCTSTR lpszValName, int iValue )
{
TCHAR szValue[16];
wnsprintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), iValue);
return SetRegValueString( hMainKey, lpszSubKey, lpszValName, szValue );
}
//------------------------------------------------------------------------------------
// GetRegValueInt()
//
// Just a little helper routine, gets an individual string value from the
// registry and returns it to the caller as an int. Takes care of registry headaches,
// including a paranoid length check before getting the string.
//
// Returns: success of string retrieval
//------------------------------------------------------------------------------------
BOOL GetRegValueInt(HKEY hMainKey, LPCTSTR lpszSubKey, LPCTSTR lpszValName, int* piValue)
{
TCHAR szValue[16];
szValue[0] = 0;
BOOL bOK = GetRegValueString( hMainKey, lpszSubKey, lpszValName, szValue, ARRAYSIZE(szValue));
*piValue = StrToInt(szValue);
return bOK;
}