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

560 lines
17 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // File: plustab.cpp
  4. //
  5. // Main Implementation of the Effects page
  6. //
  7. //---------------------------------------------------------------------------
  8. #include "priv.h"
  9. #pragma hdrstop
  10. #include "shlwapip.h"
  11. #include "shlguidp.h"
  12. #include "EffectsAdvPg.h"
  13. #include "store.h"
  14. #include "regutil.h"
  15. // OLE-Registry magic number
  16. GUID CLSID_EffectsPage = { 0x41e300e0, 0x78b6, 0x11ce,{0x84, 0x9b, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
  17. #define SPI_GETKEYBOARDINDICATORS SPI_GETMENUUNDERLINES//0x100A
  18. #define SPI_SETKEYBOARDINDICATORS SPI_SETMENUUNDERLINES//0x100B
  19. #define SPI_GETFONTCLEARTYPE 116
  20. #define SPI_SETFONTCLEARTYPE 117
  21. // Handle to the DLL
  22. extern HINSTANCE g_hInst;
  23. // vars needed for new shell api
  24. #define SZ_SHELL32 TEXT("shell32.dll")
  25. #define SZ_SHUPDATERECYCLEBINICON "SHUpdateRecycleBinIcon" // Parameter for GetProcAddr()... DO NOT TEXT("") IT!
  26. typedef void (* PFNSHUPDATERECYCLEBINICON)( void );
  27. int GetBitsPerPixel(void)
  28. {
  29. int iBitsPerPixel = 8;
  30. HDC hDC = GetDC(NULL);
  31. if (hDC)
  32. {
  33. iBitsPerPixel = GetDeviceCaps(hDC, BITSPIXEL);
  34. ReleaseDC(NULL, hDC);
  35. }
  36. return iBitsPerPixel;
  37. }
  38. int GetIconState(void)
  39. {
  40. BOOL bRet;
  41. int iSize;
  42. bRet = GetRegValueInt(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE, &iSize);
  43. if (bRet == FALSE)
  44. return ICON_DEFAULT;
  45. if (iSize == ICON_DEFAULT_NORMAL)
  46. return ICON_DEFAULT;
  47. else if (iSize == ICON_DEFAULT_LARGE)
  48. return ICON_LARGE;
  49. return ICON_INDETERMINATE;
  50. }
  51. BOOL ChangeIconSizes(int iOldState, int iNewState)
  52. {
  53. BOOL bRet;
  54. int iOldSize, iNewSize;
  55. int iHorz;
  56. int iVert;
  57. // Don't bother if nothing changed
  58. if (iOldState == iNewState)
  59. return FALSE;
  60. // Get New Size
  61. switch (iNewState)
  62. {
  63. case ICON_DEFAULT:
  64. iNewSize = ICON_DEFAULT_NORMAL;
  65. break;
  66. case ICON_LARGE:
  67. iNewSize = ICON_DEFAULT_LARGE;
  68. break;
  69. case ICON_INDETERMINATE:
  70. // Don't bother to change anything
  71. return FALSE;
  72. default:
  73. return FALSE;
  74. }
  75. // Get Original Size
  76. bRet = GetRegValueInt(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE, &iOldSize);
  77. if (!bRet)
  78. {
  79. // Try geting system default instead
  80. iOldSize = ClassicGetSystemMetrics(SM_CXICON);
  81. }
  82. // Don't need to change size if nothing has really changed
  83. if (iNewSize == iOldSize)
  84. return FALSE;
  85. // Get new horizontal spacing
  86. iHorz = ClassicGetSystemMetrics(SM_CXICONSPACING);
  87. iHorz -= iOldSize;
  88. if (iHorz < 0)
  89. {
  90. iHorz = 0;
  91. }
  92. iHorz += iNewSize;
  93. // Get new vertical spacing
  94. iVert = ClassicGetSystemMetrics(SM_CYICONSPACING);
  95. iVert -= iOldSize;
  96. if (iVert < 0)
  97. {
  98. iVert = 0;
  99. }
  100. iVert += iNewSize;
  101. // Set New sizes and spacing
  102. bRet = SetRegValueInt(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONSIZE, iNewSize);
  103. if (!bRet)
  104. return FALSE;
  105. // We don't need to call the Async version because this function is called on a background thread.
  106. ClassicSystemParametersInfo(SPI_ICONHORIZONTALSPACING, iHorz, NULL, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE));
  107. ClassicSystemParametersInfo(SPI_ICONVERTICALSPACING, iVert, NULL, (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE));
  108. // We need to do this in order to force DefView to update.
  109. // BUG:194437
  110. ICONMETRICS iconMetrics;
  111. iconMetrics.cbSize = sizeof(iconMetrics);
  112. ClassicSystemParametersInfo(SPI_GETICONMETRICS, sizeof(iconMetrics), &iconMetrics, 0);
  113. ClassicSystemParametersInfo(SPI_SETICONMETRICS, sizeof(iconMetrics), &iconMetrics, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
  114. // We did change the sizes
  115. return TRUE;
  116. }
  117. //
  118. // GetAnimations
  119. //
  120. // Get current state of animations (windows / menus / etc.).
  121. //
  122. WPARAM GetAnimations(DWORD *pdwEffect)
  123. {
  124. BOOL fMenu = FALSE, fWindow = FALSE, fCombo = FALSE, fSmooth = FALSE, fList = FALSE, fFade = FALSE;
  125. ANIMATIONINFO ai;
  126. ai.cbSize = sizeof(ai);
  127. if (ClassicSystemParametersInfo(SPI_GETANIMATION, sizeof(ai), (PVOID)&ai, 0 ))
  128. {
  129. fWindow = (ai.iMinAnimate) ? TRUE : FALSE;
  130. }
  131. ClassicSystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, (PVOID)&fCombo, 0 );
  132. ClassicSystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, (PVOID)&fList, 0 );
  133. ClassicSystemParametersInfo(SPI_GETMENUANIMATION, 0, (PVOID)&fMenu, 0 );
  134. fSmooth = GetRegValueDword(HKEY_CURRENT_USER, SZ_REGKEY_CPDESKTOP, SZ_REGVALUE_SMOOTHSCROLL);
  135. if (fSmooth == REG_BAD_DWORD)
  136. {
  137. fSmooth = 1;
  138. }
  139. ClassicSystemParametersInfo(SPI_GETMENUFADE, 0, (PVOID)&fFade, 0 );
  140. *pdwEffect = (fFade ? MENU_EFFECT_FADE : MENU_EFFECT_SCROLL);
  141. if (fMenu && fWindow && fCombo && fSmooth && fList)
  142. return BST_CHECKED;
  143. if ((!fMenu) && (!fWindow) && (!fCombo) && (!fSmooth) && (!fList))
  144. return BST_UNCHECKED;
  145. return BST_INDETERMINATE;
  146. }
  147. //
  148. // SetAnimations
  149. //
  150. // Set animations according (windows / menus / etc.) according to flag.
  151. //
  152. void SetAnimations(WPARAM wVal, DWORD dwEffect, DWORD dwBroadcast)
  153. {
  154. if (!IsTSPerfFlagEnabled(TSPerFlag_NoAnimation))
  155. {
  156. ANIMATIONINFO ai;
  157. // Note, if the checkbox is indeterminate, we treat it like it was checked.
  158. // We should never get this far if the user didn't change something so this should be okay.
  159. BOOL bVal = (wVal == BST_UNCHECKED) ? 0 : 1;
  160. BOOL bEfx = (dwEffect == MENU_EFFECT_FADE) ? 1 : 0;
  161. ai.cbSize = sizeof(ai);
  162. ai.iMinAnimate = bVal;
  163. ClassicSystemParametersInfo(SPI_SETANIMATION, sizeof(ai), (PVOID)&ai, dwBroadcast);
  164. ClassicSystemParametersInfo(SPI_SETCOMBOBOXANIMATION, 0, IntToPtr(bVal), dwBroadcast);
  165. ClassicSystemParametersInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, IntToPtr(bVal), dwBroadcast);
  166. ClassicSystemParametersInfo(SPI_SETMENUANIMATION, 0, IntToPtr(bVal), dwBroadcast);
  167. ClassicSystemParametersInfo(SPI_SETTOOLTIPANIMATION, 0, IntToPtr(bVal), dwBroadcast);
  168. SetRegValueDword(HKEY_CURRENT_USER, SZ_REGKEY_CPDESKTOP, SZ_REGVALUE_SMOOTHSCROLL, bVal);
  169. ClassicSystemParametersInfo(SPI_SETMENUFADE, 0, IntToPtr(bEfx), dwBroadcast);
  170. ClassicSystemParametersInfo(SPI_SETTOOLTIPFADE, 0, IntToPtr(bEfx), dwBroadcast);
  171. ClassicSystemParametersInfo(SPI_SETSELECTIONFADE, 0, bVal ? IntToPtr(bEfx) : 0, dwBroadcast);
  172. }
  173. }
  174. CEffectState::CEffectState() : m_cRef(1)
  175. {
  176. }
  177. HRESULT CEffectState::Load(void)
  178. {
  179. HRESULT hr = S_OK;
  180. // Get the values for the settings from the registry and set the checkboxes
  181. // Large Icons
  182. _nLargeIcon = GetIconState();
  183. // Full Color Icons
  184. if(FALSE == GetRegValueInt(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONCOLORDEPTH, &_nHighIconColor)) // Key not in registry yet
  185. {
  186. _nHighIconColor = 4;
  187. }
  188. // Use animations
  189. _wpMenuAnimation = GetAnimations(&_dwAnimationEffect);
  190. // Smooth edges of screen fonts
  191. _fFontSmoothing = FALSE;
  192. ClassicSystemParametersInfo(SPI_GETFONTSMOOTHING, 0, (PVOID)&_fFontSmoothing, 0);
  193. _dwFontSmoothingType = FONT_SMOOTHING_AA;
  194. if (ClassicSystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, (PVOID)&_dwFontSmoothingType, 0))
  195. {
  196. }
  197. if (FONT_SMOOTHING_MONO == _dwFontSmoothingType)
  198. {
  199. _dwFontSmoothingType = FONT_SMOOTHING_AA;
  200. }
  201. // Show contents while dragging
  202. _fDragWindow = FALSE;
  203. ClassicSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, (PVOID)&_fDragWindow, 0);
  204. _fKeyboardIndicators = FALSE;
  205. ClassicSystemParametersInfo(SPI_GETKEYBOARDINDICATORS, 0, (PVOID)&_fKeyboardIndicators, 0);
  206. _fMenuShadows = TRUE;
  207. ClassicSystemParametersInfo(SPI_GETDROPSHADOW, 0, (PVOID)&_fMenuShadows, 0);
  208. // Set the old values so we know when they changed.
  209. _nOldLargeIcon = _nLargeIcon;
  210. _nOldHighIconColor = _nHighIconColor;
  211. _wpOldMenuAnimation = _wpMenuAnimation;
  212. _fOldFontSmoothing = _fFontSmoothing;
  213. _dwOldFontSmoothingType = _dwFontSmoothingType;
  214. _fOldDragWindow = _fDragWindow;
  215. _fOldKeyboardIndicators = _fKeyboardIndicators;
  216. _dwOldAnimationEffect = _dwAnimationEffect;
  217. _fOldMenuShadows = _fMenuShadows;
  218. return hr;
  219. }
  220. HRESULT CEffectState::Save(void)
  221. {
  222. // ClassicSystemParametersInfo() will hang if a top level window is hung (#162570) and USER will not fix that bug.
  223. // Therefore, we need to make that API call on a background thread because we need to
  224. // be more rebust than to hang.
  225. AddRef();
  226. SPICreateThread(Save_WorkerProc, (void *)this);
  227. return S_OK;
  228. }
  229. DWORD CEffectState::Save_WorkerProc(void * pvThis)
  230. {
  231. CEffectState * pThis = (CEffectState *) pvThis;
  232. if (pThis)
  233. {
  234. pThis->_SaveWorkerProc();
  235. }
  236. return 0;
  237. }
  238. HRESULT CEffectState::_SaveWorkerProc(void)
  239. {
  240. HRESULT hr = S_OK;
  241. // First pass to persist the settings.
  242. hr = _SaveSettings(FALSE);
  243. if (SUCCEEDED(hr))
  244. {
  245. // Second pass to broadcast the change. This may hang if apps are hung.
  246. // This pass may only make it half way thru before it aborts. In some cases
  247. // it's only given 30 seconds to do it's work. If no apps are hung, that should be
  248. // fine. This is cancelled after a period of time because we need this process to go
  249. // away, or the Display CPL will not open again if the user launches it again.
  250. hr = _SaveSettings(TRUE);
  251. }
  252. Release();
  253. return hr;
  254. }
  255. // POSSIBLE FUTURE PERF REFINEMENT:
  256. // We could optimize this by checking if we have more than 5 or so
  257. // broadcasts to make. Then don't send the broadcasts on SystemParametersInfo()
  258. // but instead with WM_WININICHANGE with 0,0. This may reduce flicker.
  259. HRESULT CEffectState::_SaveSettings(BOOL fBroadcast)
  260. {
  261. HRESULT hr = S_OK;
  262. BOOL bDorked = FALSE;
  263. DWORD dwUpdateFlags = (fBroadcast ? (SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE) : SPIF_UPDATEINIFILE);
  264. BOOL bSendSettingsChange = FALSE;
  265. // Full Color Icons
  266. if(_nOldHighIconColor != _nHighIconColor)
  267. {
  268. SetRegValueInt(HKEY_CURRENT_USER, SZ_REGKEY_USERMETRICS, SZ_REGVALUE_ICONCOLORDEPTH, _nHighIconColor);
  269. if ((GetBitsPerPixel() < 16) && (_nHighIconColor == 16)) // Display mode won't support icon high colors
  270. {
  271. }
  272. else
  273. {
  274. _nOldHighIconColor = _nHighIconColor;
  275. bSendSettingsChange = TRUE;
  276. }
  277. }
  278. // Full window drag
  279. if (_fOldDragWindow != _fDragWindow)
  280. {
  281. if (fBroadcast)
  282. {
  283. _fOldDragWindow = _fDragWindow;
  284. }
  285. if (!IsTSPerfFlagEnabled(TSPerFlag_NoWindowDrag))
  286. {
  287. ClassicSystemParametersInfo(SPI_SETDRAGFULLWINDOWS, _fDragWindow, 0, dwUpdateFlags);
  288. }
  289. // we need to send this because the tray's autohide switches off this
  290. bSendSettingsChange = TRUE;
  291. }
  292. // Show Menu Shadows
  293. if (_fOldMenuShadows != _fMenuShadows)
  294. {
  295. if (fBroadcast)
  296. {
  297. _fOldMenuShadows = _fMenuShadows;
  298. }
  299. ClassicSystemParametersInfo(SPI_SETDROPSHADOW, 0, IntToPtr(_fMenuShadows), dwUpdateFlags);
  300. // we need to send this because the tray's autohide switches off this
  301. PostMessageBroadAsync(WM_SETTINGCHANGE, 0, 0);
  302. bSendSettingsChange = TRUE;
  303. }
  304. // Font smoothing
  305. if ((_fOldFontSmoothing != _fFontSmoothing) || (_dwOldFontSmoothingType != _dwFontSmoothingType))
  306. {
  307. if (!_fFontSmoothing)
  308. {
  309. // #168059: If font smoothing is off, we need to set SPI_SETFONTSMOOTHINGTYPE to xxx
  310. // Otherwise, it will still use ClearType.
  311. _dwFontSmoothingType = FONT_SMOOTHING_MONO;
  312. }
  313. ClassicSystemParametersInfo(SPI_SETFONTSMOOTHINGTYPE, 0, (PVOID)UlongToPtr(_dwFontSmoothingType), dwUpdateFlags);
  314. if (fBroadcast)
  315. {
  316. _dwOldFontSmoothingType = _dwFontSmoothingType;
  317. _fOldFontSmoothing = _fFontSmoothing;
  318. }
  319. ClassicSystemParametersInfo(SPI_SETFONTSMOOTHING, _fFontSmoothing, 0, dwUpdateFlags);
  320. if (fBroadcast)
  321. {
  322. // Now have the windows repaint with the change. Whistler #179531
  323. RedrawWindow(NULL, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN);
  324. }
  325. }
  326. // Menu animations
  327. if ((_wpOldMenuAnimation != _wpMenuAnimation) || (_dwOldAnimationEffect != _dwAnimationEffect))
  328. {
  329. if (fBroadcast)
  330. {
  331. _wpOldMenuAnimation = _wpMenuAnimation;
  332. }
  333. SetAnimations(_wpMenuAnimation, _dwAnimationEffect, dwUpdateFlags);
  334. if (fBroadcast)
  335. {
  336. _dwOldAnimationEffect = _dwAnimationEffect;
  337. }
  338. }
  339. // Keyboard indicators
  340. if (_fOldKeyboardIndicators != _fKeyboardIndicators)
  341. {
  342. if (fBroadcast)
  343. {
  344. _fOldKeyboardIndicators = _fKeyboardIndicators;
  345. }
  346. // Are we turning this on? (!_fKeyboardIndicators means "don't show" -> hide)
  347. if (!_fKeyboardIndicators)
  348. {
  349. // Yes, on: hide the key cues, turn on the mechanism
  350. ClassicSystemParametersInfo(SPI_SETKEYBOARDINDICATORS, 0, IntToPtr(_fKeyboardIndicators), dwUpdateFlags);
  351. PostMessageBroadAsync(WM_CHANGEUISTATE, MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
  352. }
  353. else
  354. {
  355. // No, off: means show the keycues, turn off the mechanism
  356. PostMessageBroadAsync(WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
  357. ClassicSystemParametersInfo(SPI_SETKEYBOARDINDICATORS, 0, IntToPtr(_fKeyboardIndicators), dwUpdateFlags);
  358. }
  359. }
  360. // Large Icons
  361. bSendSettingsChange = ChangeIconSizes(_nOldLargeIcon, _nLargeIcon);
  362. if (bSendSettingsChange)
  363. {
  364. if (fBroadcast)
  365. {
  366. _nOldLargeIcon = _nLargeIcon;
  367. }
  368. bDorked = TRUE;
  369. }
  370. // Make the system notice we changed the system icons
  371. if (bDorked)
  372. {
  373. PFNSHUPDATERECYCLEBINICON pfnSHUpdateRecycleBinIcon = NULL;
  374. SHChangeNotify(SHCNE_ASSOCCHANGED, 0, NULL, NULL); // should do the trick!
  375. // Load SHUpdateRecycleBinIcon() if it exists
  376. HINSTANCE hmodShell32 = LoadLibrary(SZ_SHELL32);
  377. if (hmodShell32)
  378. {
  379. pfnSHUpdateRecycleBinIcon = (PFNSHUPDATERECYCLEBINICON)GetProcAddress(hmodShell32, SZ_SHUPDATERECYCLEBINICON);
  380. if (pfnSHUpdateRecycleBinIcon != NULL)
  381. {
  382. pfnSHUpdateRecycleBinIcon();
  383. }
  384. FreeLibrary(hmodShell32);
  385. }
  386. }
  387. if (bSendSettingsChange)
  388. {
  389. // We post this message because if an app is hung or slow, we don't want to hang.
  390. PostMessageBroadAsync(WM_SETTINGCHANGE, 0, 0);
  391. }
  392. return hr;
  393. }
  394. HRESULT CEffectState::Clone(OUT CEffectState ** ppEffectClone)
  395. {
  396. HRESULT hr = E_OUTOFMEMORY;
  397. *ppEffectClone = new CEffectState();
  398. if (*ppEffectClone)
  399. {
  400. hr = S_OK;
  401. (*ppEffectClone)->_nLargeIcon = _nLargeIcon;
  402. (*ppEffectClone)->_nHighIconColor = _nHighIconColor;
  403. (*ppEffectClone)->_wpMenuAnimation = _wpMenuAnimation;
  404. (*ppEffectClone)->_fFontSmoothing = _fFontSmoothing;
  405. (*ppEffectClone)->_dwFontSmoothingType = _dwFontSmoothingType;
  406. (*ppEffectClone)->_fDragWindow = _fDragWindow;
  407. (*ppEffectClone)->_fKeyboardIndicators = _fKeyboardIndicators;
  408. (*ppEffectClone)->_dwAnimationEffect = _dwAnimationEffect;
  409. (*ppEffectClone)->_fMenuShadows = _fMenuShadows;
  410. (*ppEffectClone)->_nOldLargeIcon = _nOldLargeIcon;
  411. (*ppEffectClone)->_nOldHighIconColor = _nOldHighIconColor;
  412. (*ppEffectClone)->_wpOldMenuAnimation = _wpOldMenuAnimation;
  413. (*ppEffectClone)->_fOldFontSmoothing = _fOldFontSmoothing;
  414. (*ppEffectClone)->_dwOldFontSmoothingType = _dwOldFontSmoothingType;
  415. (*ppEffectClone)->_fOldDragWindow = _fOldDragWindow;
  416. (*ppEffectClone)->_fOldKeyboardIndicators = _fOldKeyboardIndicators;
  417. (*ppEffectClone)->_dwOldAnimationEffect = _dwOldAnimationEffect;
  418. (*ppEffectClone)->_fOldMenuShadows = _fOldMenuShadows;
  419. }
  420. return hr;
  421. }
  422. BOOL CEffectState::IsDirty(void)
  423. {
  424. BOOL fDirty = FALSE;
  425. if ((_nLargeIcon != _nOldLargeIcon) ||
  426. (_nHighIconColor != _nOldHighIconColor) ||
  427. (_wpMenuAnimation != _wpOldMenuAnimation) ||
  428. (_fFontSmoothing != _fOldFontSmoothing) ||
  429. (_dwFontSmoothingType != _dwOldFontSmoothingType) ||
  430. (_fDragWindow != _fOldDragWindow) ||
  431. (_fMenuShadows != _fOldMenuShadows) ||
  432. (_fKeyboardIndicators != _fOldKeyboardIndicators) ||
  433. (_dwAnimationEffect != _dwOldAnimationEffect))
  434. {
  435. fDirty = TRUE;
  436. }
  437. return fDirty;
  438. }
  439. ULONG CEffectState::AddRef()
  440. {
  441. return InterlockedIncrement(&m_cRef);
  442. }
  443. ULONG CEffectState::Release()
  444. {
  445. ASSERT( 0 != m_cRef );
  446. ULONG cRef = InterlockedDecrement(&m_cRef);
  447. if ( 0 == cRef )
  448. {
  449. delete this;
  450. }
  451. return cRef;
  452. }