Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

829 lines
32 KiB

  1. /*****************************************************************************\
  2. FILE: regutil.cpp
  3. DESCRIPTION:
  4. This file will contain helper functions to load and save values to the
  5. registry that are theme related.
  6. BryanSt 3/24/2000
  7. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  8. \*****************************************************************************/
  9. #include "priv.h"
  10. #include "regutil.h"
  11. EXTERN_C void FAR SetMagicColors(HDC, DWORD, WORD);
  12. // strings for color names in "WIN.INI".
  13. PTSTR s_pszColorNames[] = {
  14. /* COLOR_SCROLLBAR */ TEXT("Scrollbar"), // 0
  15. /* COLOR_DESKTOP */ TEXT("Background"),
  16. /* COLOR_ACTIVECAPTION */ TEXT("ActiveTitle"),
  17. /* COLOR_INACTIVECAPTION */ TEXT("InactiveTitle"),
  18. /* COLOR_MENU */ TEXT("Menu"),
  19. /* COLOR_WINDOW */ TEXT("Window"), // 5
  20. /* COLOR_WINDOWFRAME */ TEXT("WindowFrame"),
  21. /* COLOR_MENUTEXT */ TEXT("MenuText"),
  22. /* COLOR_WINDOWTEXT */ TEXT("WindowText"),
  23. /* COLOR_CAPTIONTEXT */ TEXT("TitleText"),
  24. /* COLOR_ACTIVEBORDER */ TEXT("ActiveBorder"), // 10
  25. /* COLOR_INACTIVEBORDER */ TEXT("InactiveBorder"),
  26. /* COLOR_APPWORKSPACE */ TEXT("AppWorkspace"),
  27. /* COLOR_HIGHLIGHT */ TEXT("Hilight"),
  28. /* COLOR_HIGHLIGHTTEXT */ TEXT("HilightText"),
  29. /* COLOR_3DFACE */ TEXT("ButtonFace"), // 15
  30. /* COLOR_3DSHADOW */ TEXT("ButtonShadow"),
  31. /* COLOR_GRAYTEXT */ TEXT("GrayText"),
  32. /* COLOR_BTNTEXT */ TEXT("ButtonText"),
  33. /* COLOR_INACTIVECAPTIONTEXT */ TEXT("InactiveTitleText"),
  34. /* COLOR_3DHILIGHT */ TEXT("ButtonHilight"), // 20
  35. /* COLOR_3DDKSHADOW */ TEXT("ButtonDkShadow"),
  36. /* COLOR_3DLIGHT */ TEXT("ButtonLight"),
  37. /* COLOR_INFOTEXT */ TEXT("InfoText"),
  38. /* COLOR_INFOBK */ TEXT("InfoWindow"),
  39. /* COLOR_3DALTFACE */ TEXT("ButtonAlternateFace"), // 25
  40. /* COLOR_HOTLIGHT */ TEXT("HotTrackingColor"),
  41. /* COLOR_GRADIENTACTIVECAPTION */ TEXT("GradientActiveTitle"),
  42. /* COLOR_GRADIENTINACTIVECAPTION */ TEXT("GradientInactiveTitle"),
  43. /* COLOR_MENUHILIGHT */ TEXT("MenuHilight"), // 29
  44. /* COLOR_MENUBAR */ TEXT("MenuBar"), // 30
  45. };
  46. // What about: AppWorkSpace
  47. #define SZ_DEFAULT_FONT TEXT("Tahoma")
  48. /////////////////////////////////////////////////////////////////////
  49. // Private Functions
  50. /////////////////////////////////////////////////////////////////////
  51. HRESULT DPIConvert_SystemMetricsAll(BOOL fScaleSizes, SYSTEMMETRICSALL * pStateToModify, int nFromDPI, int nToDPI)
  52. {
  53. pStateToModify->schemeData.ncm.lfCaptionFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfCaptionFont.lfHeight, nToDPI, nFromDPI);
  54. pStateToModify->schemeData.ncm.lfSmCaptionFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfSmCaptionFont.lfHeight, nToDPI, nFromDPI);
  55. pStateToModify->schemeData.ncm.lfMenuFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfMenuFont.lfHeight, nToDPI, nFromDPI);
  56. pStateToModify->schemeData.ncm.lfStatusFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfStatusFont.lfHeight, nToDPI, nFromDPI);
  57. pStateToModify->schemeData.ncm.lfMessageFont.lfHeight = MulDiv(pStateToModify->schemeData.ncm.lfMessageFont.lfHeight, nToDPI, nFromDPI);
  58. pStateToModify->schemeData.lfIconTitle.lfHeight = MulDiv(pStateToModify->schemeData.lfIconTitle.lfHeight, nToDPI, nFromDPI);
  59. // Someone (NTUSER?) scales sizes for us. So we don't need to do that in some cases.
  60. if (fScaleSizes)
  61. {
  62. pStateToModify->schemeData.ncm.iBorderWidth = MulDiv(pStateToModify->schemeData.ncm.iBorderWidth, nToDPI, nFromDPI);
  63. pStateToModify->schemeData.ncm.iScrollWidth = MulDiv(pStateToModify->schemeData.ncm.iScrollWidth, nToDPI, nFromDPI);
  64. pStateToModify->schemeData.ncm.iScrollHeight = MulDiv(pStateToModify->schemeData.ncm.iScrollHeight, nToDPI, nFromDPI);
  65. pStateToModify->schemeData.ncm.iCaptionWidth = MulDiv(pStateToModify->schemeData.ncm.iCaptionWidth, nToDPI, nFromDPI);
  66. pStateToModify->schemeData.ncm.iCaptionHeight = MulDiv(pStateToModify->schemeData.ncm.iCaptionHeight, nToDPI, nFromDPI);
  67. pStateToModify->schemeData.ncm.iSmCaptionWidth = MulDiv(pStateToModify->schemeData.ncm.iSmCaptionWidth, nToDPI, nFromDPI);
  68. pStateToModify->schemeData.ncm.iSmCaptionHeight = MulDiv(pStateToModify->schemeData.ncm.iSmCaptionHeight, nToDPI, nFromDPI);
  69. pStateToModify->schemeData.ncm.iMenuWidth = MulDiv(pStateToModify->schemeData.ncm.iMenuWidth, nToDPI, nFromDPI);
  70. pStateToModify->schemeData.ncm.iMenuHeight = MulDiv(pStateToModify->schemeData.ncm.iMenuHeight, nToDPI, nFromDPI);
  71. }
  72. return S_OK;
  73. }
  74. HRESULT DPIConvert_SystemMetricsAll_PersistToLive(BOOL fScaleSizes, SYSTEMMETRICSALL * pStateToModify, int nNewDPI)
  75. {
  76. return DPIConvert_SystemMetricsAll(fScaleSizes, pStateToModify, DPI_PERSISTED, nNewDPI);
  77. }
  78. HRESULT DPIConvert_SystemMetricsAll_LiveToPersist(BOOL fScaleSizes, SYSTEMMETRICSALL * pStateToModify, int nNewDPI)
  79. {
  80. return DPIConvert_SystemMetricsAll(fScaleSizes, pStateToModify, nNewDPI, DPI_PERSISTED);
  81. }
  82. HRESULT Look_GetSchemeData(IN HKEY hkSchemes, IN LPCTSTR pszSchemeName, IN SCHEMEDATA *psd)
  83. {
  84. HRESULT hr;
  85. DWORD dwType = REG_BINARY;
  86. DWORD dwSize = sizeof(*psd);
  87. hr = HrRegQueryValueEx(hkSchemes, pszSchemeName, NULL, &dwType, (LPBYTE)psd, &dwSize);
  88. if (SUCCEEDED(hr))
  89. {
  90. hr = E_FAIL;
  91. if (psd->version == SCHEME_VERSION)
  92. {
  93. hr = S_OK;
  94. }
  95. }
  96. return hr; //Yes there is a current scheme and there is valid data!
  97. }
  98. // This function reads the current scheme's name and associated scheme data from registry.
  99. //
  100. // This function returns FALSE, if there is no current scheme.
  101. HRESULT Look_GetCurSchemeNameAndData(IN SCHEMEDATA *psd, IN LPTSTR lpszSchemeName, IN int cbSize)
  102. {
  103. HKEY hkAppearance;
  104. HRESULT hr;
  105. //Get the current scheme.
  106. hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_APPEARANCE, 0, KEY_READ, &hkAppearance);
  107. if (SUCCEEDED(hr))
  108. {
  109. DWORD dwSize;
  110. dwSize = cbSize;
  111. hr = HrRegQueryValueEx(hkAppearance, REGSTR_KEY_CURRENT, NULL, NULL, (LPBYTE)lpszSchemeName, &dwSize);
  112. if (SUCCEEDED(hr))
  113. {
  114. HKEY hkSchemes;
  115. //Open the schemes key!
  116. hr = HrRegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_LOOKSCHEMES, 0, KEY_READ, &hkSchemes);
  117. if (SUCCEEDED(hr))
  118. {
  119. hr = Look_GetSchemeData(hkSchemes, lpszSchemeName, psd);
  120. RegCloseKey(hkSchemes);
  121. }
  122. }
  123. RegCloseKey(hkAppearance);
  124. }
  125. return hr; //Yes there is a current scheme and there is valid data!
  126. }
  127. /////////////////////////////////////////////////////////////////////
  128. // Public Functions
  129. /////////////////////////////////////////////////////////////////////
  130. HRESULT IconSize_Load(IN int * pnDXIcon, IN int * pnDYIcon, IN int * pnIcon, IN int * pnSmallIcon)
  131. {
  132. TCHAR szSize[8];
  133. DWORD cbSize = sizeof(szSize);
  134. // default shell icon sizes
  135. *pnIcon = ClassicGetSystemMetrics(SM_CXICON);
  136. *pnSmallIcon = ((*pnIcon) / 2);
  137. HRESULT hr = HrSHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE, NULL, (LPBYTE)szSize, &cbSize);
  138. if (SUCCEEDED(hr))
  139. {
  140. *pnIcon = StrToInt(szSize);
  141. }
  142. cbSize = sizeof(szSize);
  143. hr = HrSHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_SMALLICONSIZE, NULL, (LPBYTE)szSize, &cbSize);
  144. if (SUCCEEDED(hr))
  145. {
  146. *pnSmallIcon = StrToInt(szSize);
  147. }
  148. *pnDXIcon = (ClassicGetSystemMetrics(SM_CXICONSPACING) - *pnIcon);
  149. if (*pnDXIcon < 0)
  150. {
  151. *pnDXIcon = 0;
  152. }
  153. *pnDYIcon = (ClassicGetSystemMetrics(SM_CYICONSPACING) - *pnIcon);
  154. if (*pnDYIcon < 0)
  155. {
  156. *pnDYIcon = 0;
  157. }
  158. return S_OK;
  159. }
  160. HRESULT IconSize_Save(IN int nDXIcon, IN int nDYIcon, IN int nIcon, IN int nSmallIcon)
  161. {
  162. HRESULT hr = E_INVALIDARG;
  163. AssertMsg((0 != nIcon), TEXT("We should never save an icon size of zero."));
  164. AssertMsg((0 != nSmallIcon), TEXT("We should never save an small icon size of zero."));
  165. if (nIcon && nSmallIcon)
  166. {
  167. TCHAR szSize[8];
  168. wnsprintf(szSize, ARRAYSIZE(szSize), TEXT("%d"), nIcon);
  169. hr = HrSHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE,
  170. REG_SZ, (LPBYTE)szSize, sizeof(szSize[0]) * (lstrlen(szSize) + 1));
  171. #ifdef THE_SHELL_CAN_HANDLE_CUSTOM_SMALL_ICON_SIZES_YET
  172. wnsprintf(szSize, ARRAYSIZE(szSize), TEXT("%d"), nSmallIcon);
  173. hr = HrSHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_SMALLICONSIZE,
  174. REG_SZ, (LPBYTE)szSize, sizeof(szSize[0]) * (lstrlen(szSize) + 1));
  175. #endif
  176. }
  177. // WM_SETTINGCHANGE needs to be sent for this to update. The caller needs to do that.
  178. return hr;
  179. }
  180. DWORD SetHighContrastAsync_WorkerThread(IN void *pv)
  181. {
  182. BOOL fHighContrast = (BOOL) PtrToInt(pv);
  183. HIGHCONTRAST hc = {0};
  184. TCHAR szFlags[MAX_PATH];
  185. if (SUCCEEDED(HrRegGetValueString(HKEY_CURRENT_USER, SZ_REGKEY_ACCESS_HIGHCONTRAST, SZ_REGVALUE_ACCESS_HCFLAGS, szFlags, ARRAYSIZE(szFlags))))
  186. {
  187. DWORD dwFlags = StrToInt(szFlags);
  188. // Do async:
  189. hc.cbSize = sizeof(hc);
  190. if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, 0))
  191. {
  192. BOOL fCurrentlySet = (dwFlags & HCF_HIGHCONTRASTON); // I check the flags in the registry because USER32 may be out of date.
  193. // Only do the broadcast if it changed
  194. if (fHighContrast != fCurrentlySet)
  195. {
  196. if (fHighContrast)
  197. {
  198. hc.dwFlags |= HCF_HIGHCONTRASTON; // Add the bit.
  199. }
  200. else
  201. {
  202. hc.dwFlags &= ~HCF_HIGHCONTRASTON; // Clear the bit.
  203. }
  204. wnsprintf(szFlags, ARRAYSIZE(szFlags), TEXT("%d"), hc.dwFlags);
  205. HrRegSetValueString(HKEY_CURRENT_USER, SZ_REGKEY_ACCESS_HIGHCONTRAST, SZ_REGVALUE_ACCESS_HCFLAGS, szFlags);
  206. SendMessage(HWND_BROADCAST, WM_WININICHANGE, SPI_SETHIGHCONTRAST, (LPARAM)&hc);
  207. }
  208. }
  209. }
  210. return 0;
  211. }
  212. void AssertPositiveFontSizes(SYSTEMMETRICSALL * pState)
  213. {
  214. // NTUSER will incorrectly scale positive LOGFONT lfHeights so we need to verify
  215. // that we always set negative sizes.
  216. AssertMsg((0 > pState->schemeData.lfIconTitle.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfIconTitle)"));
  217. AssertMsg((0 > pState->schemeData.ncm.lfCaptionFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfCaptionFont)"));
  218. AssertMsg((0 > pState->schemeData.ncm.lfMenuFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfMenuFont)"));
  219. AssertMsg((0 > pState->schemeData.ncm.lfMessageFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfMessageFont)"));
  220. AssertMsg((0 > pState->schemeData.ncm.lfSmCaptionFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfSmCaptionFont)"));
  221. AssertMsg((0 > pState->schemeData.ncm.lfStatusFont.lfHeight), TEXT("LOGFONT sizes must be negative because of a NTUSER bug. (lfStatusFont)"));
  222. }
  223. #define SZ_INILABLE_COLORS TEXT("colors") // colors section name
  224. /*
  225. ** set all of the data to the system.
  226. **
  227. ** COMPATIBILITY NOTE:
  228. ** EXCEL 5.0 people hook metrics changes off of WM_SYSCOLORCHANGE
  229. ** instead of WM_WININICHANGE. Windows 3.1's Desktop applet always sent
  230. ** both when the metrics were updated, so nobody noticed this bug.
  231. ** Be careful when re-arranging this function...
  232. **
  233. */
  234. HRESULT SystemMetricsAll_Set(IN SYSTEMMETRICSALL * pState, CDimmedWindow* pDimmedWindow)
  235. {
  236. // COMPATIBILITY:
  237. // Do metrics first since the color stuff might cause USER to generate a
  238. // WM_SYSCOLORCHANGE message and we don't want to send two of them...
  239. TraceMsg(TF_THEMEUI_SYSMETRICS, "desk.cpl: _SetSysStuff");
  240. SystemParametersInfoAsync(SPI_SETFLATMENU, NULL, IntToPtr(pState->fFlatMenus), 0, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
  241. AssertMsg((0 != pState->nIcon), TEXT("We should never save an icon size of zero."));
  242. AssertMsg((0 != pState->nSmallIcon), TEXT("We should never save an small icon size of zero."));
  243. // NOTE: It would be nice to create one background thread and then make the 1 or 5 ClassicSystemParametersInfo()
  244. // calls on that single thread.
  245. if ((pState->dwChanged & METRIC_CHANGE) && pState->nIcon && pState->nSmallIcon)
  246. {
  247. HKEY hkey;
  248. TraceMsg(TF_THEMEUI_SYSMETRICS, "desk.cpl: Metrics Changed");
  249. TraceMsg(TF_THEMEUI_SYSMETRICS, "desk.cpl: Calling SPI_SETNONCLIENTMETRICS");
  250. pState->schemeData.ncm.cbSize = sizeof(pState->schemeData.ncm);
  251. AssertPositiveFontSizes(pState);
  252. SystemParametersInfoAsync(SPI_SETNONCLIENTMETRICS, sizeof(pState->schemeData.ncm), (void far *)(LPNONCLIENTMETRICS)&(pState->schemeData.ncm),
  253. sizeof(pState->schemeData.ncm), (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
  254. TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Calling SPI_SETICONTITLELOGFONT");
  255. SystemParametersInfoAsync(SPI_SETICONTITLELOGFONT, sizeof(LOGFONT), (void far *)(LPLOGFONT)&(pState->schemeData.lfIconTitle),
  256. sizeof(pState->schemeData.lfIconTitle), (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
  257. TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Calling SPI_ICONHORIZONTALSPACING");
  258. SystemParametersInfoAsync(SPI_ICONHORIZONTALSPACING, pState->nDXIcon + pState->nIcon, NULL, 0, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
  259. TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Calling SPI_ICONVERTICALSPACING");
  260. SystemParametersInfoAsync(SPI_ICONVERTICALSPACING, pState->nDYIcon + pState->nIcon, NULL, 0, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE), pDimmedWindow);
  261. TraceMsg(TF_THEMEUI_SYSMETRICS,"desk.cpl: Done calling SPI's");
  262. if (RegCreateKey(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, &hkey) == ERROR_SUCCESS)
  263. {
  264. TCHAR val[8];
  265. AssertMsg((0 != pState->nIcon), TEXT("pState->nIcon should never be zero (0)."));
  266. wsprintf(val, TEXT("%d"), pState->nIcon);
  267. RegSetValueEx(hkey, SZ_REGVALUE_ICONSIZE, 0, REG_SZ, (LPBYTE)&val, SIZEOF(TCHAR) * (lstrlen(val) + 1));
  268. #ifdef THE_SHELL_CAN_HANDLE_CUSTOM_SMALL_ICON_SIZES_YET
  269. AssertMsg((0 != pState->nSmallIcon), TEXT("pState->nIcon should never be zero (0)."));
  270. wsprintf(val, TEXT("%d"), pState->nSmallIcon);
  271. RegSetValueEx(hkey, SZ_REGVALUE_SMALLICONSIZE, 0, REG_SZ, (LPBYTE)&val, SIZEOF(TCHAR) * (lstrlen(val) + 1));
  272. #else
  273. // RegDeleteValue(hkey, SZ_REGVALUE_SMALLICONSIZE);
  274. #endif
  275. RegCloseKey(hkey);
  276. }
  277. // WM_SETTINGCHANGE is sent at the end of the function
  278. }
  279. if (pState->dwChanged & COLOR_CHANGE)
  280. {
  281. int i;
  282. int iColors[COLOR_MAX];
  283. COLORREF rgbColors[COLOR_MAX];
  284. TCHAR szRGB[32];
  285. COLORREF rgb;
  286. HKEY hk;
  287. HDC hdc;
  288. // restore magic colors back to Win31 defaults.
  289. hdc = GetDC(NULL);
  290. SetMagicColors(hdc, 0x00c0dcc0, 8); // money green
  291. SetMagicColors(hdc, 0x00f0caa6, 9); // IBM blue
  292. SetMagicColors(hdc, 0x00f0fbff, 246); // off white
  293. ReleaseDC(NULL, hdc);
  294. // -------------------------------------------------
  295. // This call causes user to send a WM_SYSCOLORCHANGE
  296. // -------------------------------------------------
  297. for (i=0; i < COLOR_MAX; i++)
  298. {
  299. iColors[i] = i;
  300. rgbColors[i] = pState->schemeData.rgb[i] & 0x00FFFFFF;
  301. }
  302. SetSysColors(ARRAYSIZE(rgbColors), iColors, rgbColors);
  303. if (RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_COLORS, &hk) == ERROR_SUCCESS)
  304. {
  305. // write out the color information to win.ini
  306. for (i = 0; i < COLOR_MAX; i++)
  307. {
  308. rgb = pState->schemeData.rgb[i];
  309. wsprintf(szRGB, TEXT("%d %d %d"), GetRValue(rgb), GetGValue(rgb), GetBValue(rgb));
  310. // For the time being we will update the INI file also.
  311. WriteProfileString(SZ_INILABLE_COLORS, s_pszColorNames[i], szRGB);
  312. // Update the registry (Be sure to include the terminating zero in the byte count!)
  313. RegSetValueEx(hk, s_pszColorNames[i], 0L, REG_SZ, (LPBYTE)szRGB, SIZEOF(TCHAR) * (lstrlen(szRGB)+1));
  314. TraceMsg(TF_THEMEUI_SYSMETRICS, "CPL:Write Color: %s=%s\n\r",s_pszColorNames[i], szRGB);
  315. }
  316. RegCloseKey(hk);
  317. }
  318. }
  319. else if (pState->dwChanged & METRIC_CHANGE)
  320. {
  321. // COMPATIBILITY HACK:
  322. // no colors were changed, but metrics were
  323. // EXCEL 5.0 people tied metrics changes to WM_SYSCOLORCHANGE
  324. // and ignore the WM_WININICHANGE (now called WM_SETTINGCHANGE)
  325. // send a bogus WM_SYSCOLORCHANGE
  326. PostMessageBroadAsync(WM_SYSCOLORCHANGE, 0, 0);
  327. }
  328. // if metrics changed at all send a WM_SETTINGCHANGE
  329. if (pState->dwChanged & METRIC_CHANGE)
  330. {
  331. PostMessageBroadAsync(WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
  332. }
  333. #ifdef FEATURE_SETHIGHCONTRASTSPI
  334. // Start up a new thread and send this:
  335. SPICreateThread(SetHighContrastAsync_WorkerThread, (void *)pState->fHighContrast);
  336. #endif // FEATURE_SETHIGHCONTRASTSPI
  337. return S_OK;
  338. }
  339. HRESULT SystemMetricsAll_Get(IN SYSTEMMETRICSALL * pState)
  340. {
  341. HKEY hkey;
  342. // sizes and fonts
  343. pState->schemeData.ncm.cbSize = sizeof(pState->schemeData.ncm);
  344. ClassicSystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(pState->schemeData.ncm), (void far *)(LPNONCLIENTMETRICS)&(pState->schemeData.ncm), FALSE);
  345. ClassicSystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), (void far *)(LPLOGFONT)&(pState->schemeData.lfIconTitle), FALSE);
  346. // default shell icon sizes
  347. pState->nIcon = ClassicGetSystemMetrics(SM_CXICON);
  348. pState->nSmallIcon = pState->nIcon / 2;
  349. ClassicSystemParametersInfo(SPI_GETFLATMENU, NULL, &pState->fFlatMenus, 0);
  350. if (RegOpenKey(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, &hkey) == ERROR_SUCCESS)
  351. {
  352. TCHAR val[8];
  353. LONG len = sizeof(val);
  354. if (RegQueryValueEx(hkey, SZ_REGVALUE_ICONSIZE, 0, NULL, (LPBYTE)&val, (LPDWORD)&len) == ERROR_SUCCESS)
  355. {
  356. pState->nIcon = StrToInt(val);
  357. }
  358. len = SIZEOF(val);
  359. if (RegQueryValueEx(hkey, SZ_REGVALUE_SMALLICONSIZE, 0, NULL, (LPBYTE)&val, (LPDWORD)&len) == ERROR_SUCCESS)
  360. {
  361. pState->nSmallIcon = StrToInt(val);
  362. }
  363. RegCloseKey(hkey);
  364. }
  365. pState->nDXIcon = ClassicGetSystemMetrics(SM_CXICONSPACING) - pState->nIcon;
  366. if (pState->nDXIcon < 0)
  367. {
  368. pState->nDXIcon = 0;
  369. }
  370. pState->nDYIcon = ClassicGetSystemMetrics(SM_CYICONSPACING) - pState->nIcon;
  371. if (pState->nDYIcon < 0)
  372. {
  373. pState->nDYIcon = 0;
  374. }
  375. // system colors
  376. for (int nIndex = 0; nIndex < COLOR_MAX; nIndex++)
  377. {
  378. pState->schemeData.rgb[nIndex] = GetSysColor(nIndex);
  379. }
  380. HIGHCONTRAST hc = {0};
  381. TCHAR szTemp[MAX_PATH];
  382. szTemp[0] = 0;
  383. hc.cbSize = sizeof(hc);
  384. if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, 0))
  385. {
  386. pState->fHighContrast = ((hc.dwFlags & HCF_HIGHCONTRASTON) ? TRUE : FALSE);
  387. }
  388. else
  389. {
  390. pState->fHighContrast = FALSE;
  391. }
  392. return S_OK;
  393. }
  394. HRESULT SystemMetricsAll_Copy(IN SYSTEMMETRICSALL * pStateSource, IN SYSTEMMETRICSALL * pStateDest)
  395. {
  396. CopyMemory(pStateDest, pStateSource, sizeof(*pStateDest));
  397. return S_OK;
  398. }
  399. HRESULT SystemMetricsAll_Load(IN IThemeSize * pSizeToLoadFrom, IN SYSTEMMETRICSALL * pStateToLoad, IN const int * pnNewDPI)
  400. {
  401. HRESULT hr = E_INVALIDARG;
  402. if (pSizeToLoadFrom && pStateToLoad)
  403. {
  404. pStateToLoad->schemeData.ncm.cbSize = sizeof(pStateToLoad->schemeData.ncm);
  405. pStateToLoad->schemeData.version = SCHEME_VERSION;
  406. pStateToLoad->schemeData.wDummy = 0;
  407. // Load Behavior System Metrics
  408. IPropertyBag * pPropertyBag;
  409. VARIANT var;
  410. var.boolVal = VARIANT_FALSE;
  411. hr = pSizeToLoadFrom->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  412. if (SUCCEEDED(hr))
  413. {
  414. hr = pPropertyBag->Read(SZ_PBPROP_VSBEHAVIOR_FLATMENUS, &var, NULL);
  415. pPropertyBag->Release();
  416. }
  417. if (SUCCEEDED(hr))
  418. {
  419. pStateToLoad->fFlatMenus = (VARIANT_TRUE == var.boolVal);
  420. // Load Fonts
  421. hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_CAPTIONFONT, &pStateToLoad->schemeData.ncm.lfCaptionFont);
  422. if (SUCCEEDED(hr))
  423. {
  424. hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_SMCAPTIONFONT, &pStateToLoad->schemeData.ncm.lfSmCaptionFont);
  425. hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_MENUFONT, &pStateToLoad->schemeData.ncm.lfMenuFont);
  426. hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_STATUSFONT, &pStateToLoad->schemeData.ncm.lfStatusFont);
  427. hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_MESSAGEFONT, &pStateToLoad->schemeData.ncm.lfMessageFont);
  428. hr = pSizeToLoadFrom->GetSystemMetricFont(SMF_ICONTITLEFONT, &pStateToLoad->schemeData.lfIconTitle);
  429. // Load Sizes
  430. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_BORDERWIDTH, &pStateToLoad->schemeData.ncm.iBorderWidth);
  431. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SCROLLWIDTH, &pStateToLoad->schemeData.ncm.iScrollWidth);
  432. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SCROLLHEIGHT, &pStateToLoad->schemeData.ncm.iScrollHeight);
  433. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_CAPTIONWIDTH, &pStateToLoad->schemeData.ncm.iCaptionWidth);
  434. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_CAPTIONHEIGHT, &pStateToLoad->schemeData.ncm.iCaptionHeight);
  435. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SMCAPTIONWIDTH, &pStateToLoad->schemeData.ncm.iSmCaptionWidth);
  436. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_SMCAPTIONHEIGHT, &pStateToLoad->schemeData.ncm.iSmCaptionHeight);
  437. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_MENUWIDTH, &pStateToLoad->schemeData.ncm.iMenuWidth);
  438. hr = pSizeToLoadFrom->get_SystemMetricSize(SMS_MENUHEIGHT, &pStateToLoad->schemeData.ncm.iMenuHeight);
  439. // Load Color
  440. hr = S_OK;
  441. for (int nIndex = 0; SUCCEEDED(hr) && (nIndex < ARRAYSIZE(pStateToLoad->schemeData.rgb)); nIndex++)
  442. {
  443. hr = pSizeToLoadFrom->get_SystemMetricColor(nIndex, &pStateToLoad->schemeData.rgb[nIndex]);
  444. }
  445. if (pnNewDPI)
  446. {
  447. // We need to scale the fonts to fit correctly on the current monitor's DPI.
  448. LogSystemMetrics("SystemMetricsAll_Load() BEFORE P->DPI loading AppearSchm", pStateToLoad);
  449. DPIConvert_SystemMetricsAll_PersistToLive(TRUE, pStateToLoad, *pnNewDPI);
  450. LogSystemMetrics("SystemMetricsAll_Load() AFTER P->DPI loading AppearSchm", pStateToLoad);
  451. }
  452. }
  453. }
  454. }
  455. if (SUCCEEDED(hr))
  456. {
  457. hr = IconSize_Load(&pStateToLoad->nDXIcon, &pStateToLoad->nDYIcon, &pStateToLoad->nIcon, &pStateToLoad->nSmallIcon);
  458. }
  459. if (SUCCEEDED(hr))
  460. {
  461. enumThemeContrastLevels ContrastLevel = CONTRAST_NORMAL;
  462. if (FAILED(pSizeToLoadFrom->get_ContrastLevel(&ContrastLevel)))
  463. {
  464. ContrastLevel = CONTRAST_NORMAL;
  465. }
  466. pStateToLoad->fHighContrast = ((CONTRAST_NORMAL == ContrastLevel) ? FALSE : TRUE);
  467. }
  468. return hr;
  469. }
  470. // Copy the settings from pStateToLoad to pSizeToLoadFrom.
  471. HRESULT SystemMetricsAll_Save(IN SYSTEMMETRICSALL * pState, IN IThemeSize * pSizeToSaveTo, IN const int * pnNewDPI)
  472. {
  473. HRESULT hr = E_INVALIDARG;
  474. if (pSizeToSaveTo && pState)
  475. {
  476. pState->schemeData.ncm.cbSize = sizeof(pState->schemeData.ncm);
  477. pState->schemeData.version = SCHEME_VERSION;
  478. pState->schemeData.wDummy = 0;
  479. // Load Behavior System Metrics
  480. IPropertyBag * pPropertyBag;
  481. hr = pSizeToSaveTo->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag));
  482. if (SUCCEEDED(hr))
  483. {
  484. VARIANT var;
  485. var.vt = VT_BOOL;
  486. var.boolVal = (pState->fFlatMenus ? VARIANT_TRUE : VARIANT_FALSE);
  487. hr = pPropertyBag->Write(SZ_PBPROP_VSBEHAVIOR_FLATMENUS, &var);
  488. pPropertyBag->Release();
  489. }
  490. if (pnNewDPI)
  491. {
  492. // We need to scale the fonts & sizes to be current DPI independent
  493. LogSystemMetrics("SystemMetricsAll_Save() BEFORE DPI->P to save AppearSchm", pState);
  494. DPIConvert_SystemMetricsAll_LiveToPersist(TRUE, pState, *pnNewDPI);
  495. LogSystemMetrics("SystemMetricsAll_Save() AFTER DPI->P to save AppearSchm", pState);
  496. }
  497. // Load Fonts
  498. hr = pSizeToSaveTo->PutSystemMetricFont(SMF_CAPTIONFONT, &pState->schemeData.ncm.lfCaptionFont);
  499. hr = pSizeToSaveTo->PutSystemMetricFont(SMF_SMCAPTIONFONT, &pState->schemeData.ncm.lfSmCaptionFont);
  500. hr = pSizeToSaveTo->PutSystemMetricFont(SMF_MENUFONT, &pState->schemeData.ncm.lfMenuFont);
  501. hr = pSizeToSaveTo->PutSystemMetricFont(SMF_STATUSFONT, &pState->schemeData.ncm.lfStatusFont);
  502. hr = pSizeToSaveTo->PutSystemMetricFont(SMF_MESSAGEFONT, &pState->schemeData.ncm.lfMessageFont);
  503. hr = pSizeToSaveTo->PutSystemMetricFont(SMF_ICONTITLEFONT, &pState->schemeData.lfIconTitle);
  504. // Load Sizes
  505. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_BORDERWIDTH, pState->schemeData.ncm.iBorderWidth);
  506. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SCROLLWIDTH, pState->schemeData.ncm.iScrollWidth);
  507. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SCROLLHEIGHT, pState->schemeData.ncm.iScrollHeight);
  508. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_CAPTIONWIDTH, pState->schemeData.ncm.iCaptionWidth);
  509. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_CAPTIONHEIGHT, pState->schemeData.ncm.iCaptionHeight);
  510. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SMCAPTIONWIDTH, pState->schemeData.ncm.iSmCaptionWidth);
  511. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_SMCAPTIONHEIGHT, pState->schemeData.ncm.iSmCaptionHeight);
  512. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_MENUWIDTH, pState->schemeData.ncm.iMenuWidth);
  513. hr = pSizeToSaveTo->put_SystemMetricSize(SMS_MENUHEIGHT, pState->schemeData.ncm.iMenuHeight);
  514. // Load Color
  515. for (int nIndex = 0; nIndex < ARRAYSIZE(pState->schemeData.rgb); nIndex++)
  516. {
  517. hr = pSizeToSaveTo->put_SystemMetricColor(nIndex, pState->schemeData.rgb[nIndex]);
  518. }
  519. }
  520. // We don't save the icon info if it is zero. It should never be NULL in normal cases, except when
  521. // we are converting the settings in the upgrade case.
  522. if (SUCCEEDED(hr) && pState->nIcon)
  523. {
  524. hr = IconSize_Save(pState->nDXIcon, pState->nDYIcon, pState->nIcon, pState->nSmallIcon);
  525. }
  526. if (SUCCEEDED(hr))
  527. {
  528. enumThemeContrastLevels ContrastLevel = (pState->fHighContrast ? CONTRAST_HIGHBLACK : CONTRAST_NORMAL);
  529. pSizeToSaveTo->put_ContrastLevel(ContrastLevel);
  530. }
  531. return hr;
  532. }
  533. BOOL _GetRegValueString(HKEY hKey, LPCTSTR lpszValName, LPTSTR pszString, int cchSize)
  534. {
  535. DWORD cbSize = sizeof(pszString[0]) * cchSize;
  536. DWORD dwType;
  537. DWORD dwError = RegQueryValueEx(hKey, lpszValName, NULL, &dwType, (LPBYTE)pszString, &cbSize);
  538. return (ERROR_SUCCESS == dwError);
  539. }
  540. //------------------------------------------------------------------------------------
  541. // SetRegValueString()
  542. //
  543. // Just a little helper routine that takes string and writes it to the registry.
  544. // Returns: success writing to Registry, should be always TRUE.
  545. //------------------------------------------------------------------------------------
  546. BOOL SetRegValueString(HKEY hMainKey, LPCTSTR pszSubKey, LPCTSTR pszRegValue, LPCTSTR pszString)
  547. {
  548. HKEY hKey;
  549. BOOL fSucceeded = FALSE;
  550. DWORD dwDisposition;
  551. DWORD dwError = RegCreateKeyEx(hMainKey, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
  552. if (ERROR_SUCCESS == dwError)
  553. {
  554. dwError = SHRegSetPath(hKey, NULL, pszRegValue, pszString, 0);
  555. if (ERROR_SUCCESS == dwError)
  556. {
  557. fSucceeded = TRUE;
  558. }
  559. RegCloseKey(hKey);
  560. }
  561. return fSucceeded;
  562. }
  563. //------------------------------------------------------------------------------------
  564. // GetRegValueString()
  565. //
  566. // Just a little helper routine, gets an individual string value from the
  567. // registry and returns it to the caller. Takes care of registry headaches,
  568. // including a paranoid length check before getting the string.
  569. //
  570. // Returns: success of string retrieval
  571. //------------------------------------------------------------------------------------
  572. BOOL GetRegValueString( HKEY hMainKey, LPCTSTR lpszSubKey, LPCTSTR lpszValName, LPTSTR lpszValue, int iMaxSize )
  573. {
  574. HKEY hKey; // cur open key
  575. LONG lRet = RegOpenKeyEx( hMainKey, lpszSubKey, (DWORD)0, KEY_QUERY_VALUE, (PHKEY)&hKey );
  576. if( lRet == ERROR_SUCCESS )
  577. {
  578. BOOL fRet = _GetRegValueString(hKey, lpszValName, lpszValue, iMaxSize);
  579. // close subkey
  580. RegCloseKey( hKey );
  581. return fRet;
  582. }
  583. return FALSE;
  584. }
  585. //------------------------------------------------------------------------------------
  586. // SetRegValueDword()
  587. //
  588. // Just a little helper routine that takes an dword and writes it to the
  589. // supplied location.
  590. //
  591. // Returns: success writing to Registry, should be always TRUE.
  592. //------------------------------------------------------------------------------------
  593. BOOL SetRegValueDword( HKEY hk, LPCTSTR pSubKey, LPCTSTR pValue, DWORD dwVal )
  594. {
  595. HKEY hkey = NULL;
  596. BOOL bRet = FALSE;
  597. if (ERROR_SUCCESS == RegOpenKey( hk, pSubKey, &hkey ))
  598. {
  599. if (ERROR_SUCCESS == RegSetValueEx(hkey, pValue, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD)))
  600. {
  601. bRet = TRUE;
  602. }
  603. }
  604. if (hkey)
  605. {
  606. RegCloseKey( hkey );
  607. }
  608. return bRet;
  609. }
  610. //------------------------------------------------------------------------------------
  611. // GetRegValueDword()
  612. //
  613. // Just a little helper routine that takes an dword and writes it to the
  614. // supplied location.
  615. //
  616. // Returns: success writing to Registry, should be always TRUE.
  617. //------------------------------------------------------------------------------------
  618. DWORD GetRegValueDword( HKEY hk, LPCTSTR pSubKey, LPCTSTR pValue )
  619. {
  620. HKEY hkey = NULL;
  621. DWORD dwVal = REG_BAD_DWORD;
  622. if (ERROR_SUCCESS == RegOpenKey( hk, pSubKey, &hkey ))
  623. {
  624. DWORD dwType, dwSize = sizeof(DWORD);
  625. RegQueryValueEx( hkey, pValue, NULL, &dwType, (LPBYTE)&dwVal, &dwSize );
  626. }
  627. if (hkey)
  628. {
  629. RegCloseKey( hkey );
  630. }
  631. return dwVal;
  632. }
  633. //------------------------------------------------------------------------------------
  634. // SetRegValueInt()
  635. //
  636. // Just a little helper routine that takes an int and writes it as a string to the
  637. // registry.
  638. //
  639. // Returns: success writing to Registry, should be always TRUE.
  640. //------------------------------------------------------------------------------------
  641. BOOL SetRegValueInt( HKEY hMainKey, LPCTSTR lpszSubKey, LPCTSTR lpszValName, int iValue )
  642. {
  643. TCHAR szValue[16];
  644. wnsprintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), iValue);
  645. return SetRegValueString( hMainKey, lpszSubKey, lpszValName, szValue );
  646. }
  647. //------------------------------------------------------------------------------------
  648. // GetRegValueInt()
  649. //
  650. // Just a little helper routine, gets an individual string value from the
  651. // registry and returns it to the caller as an int. Takes care of registry headaches,
  652. // including a paranoid length check before getting the string.
  653. //
  654. // Returns: success of string retrieval
  655. //------------------------------------------------------------------------------------
  656. BOOL GetRegValueInt(HKEY hMainKey, LPCTSTR lpszSubKey, LPCTSTR lpszValName, int* piValue)
  657. {
  658. TCHAR szValue[16];
  659. szValue[0] = 0;
  660. BOOL bOK = GetRegValueString( hMainKey, lpszSubKey, lpszValName, szValue, ARRAYSIZE(szValue));
  661. *piValue = StrToInt(szValue);
  662. return bOK;
  663. }