2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/theme.c
5 * PURPOSE: Handling themes and visual effects
7 * PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
8 * Ismael Ferreras Morezuelas (swyterzone+reactos@gmail.com)
18 static const WCHAR g_CPColors
[] = L
"Control Panel\\Colors";
19 static const WCHAR g_CPANewSchemes
[] = L
"Control Panel\\Appearance\\New Schemes";
20 static const WCHAR g_CPMetrics
[] = L
"Control Panel\\Desktop\\WindowMetrics";
21 static const WCHAR g_SelectedStyle
[] = L
"SelectedStyle";
23 /******************************************************************************/
25 /* This is the list of names for the colors stored in the registry */
26 static const WCHAR
*g_RegColorNames
[NUM_COLORS
] = {
27 L
"Scrollbar", /* 00 = COLOR_SCROLLBAR */
28 L
"Background", /* 01 = COLOR_DESKTOP */
29 L
"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
30 L
"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
31 L
"Menu", /* 04 = COLOR_MENU */
32 L
"Window", /* 05 = COLOR_WINDOW */
33 L
"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
34 L
"MenuText", /* 07 = COLOR_MENUTEXT */
35 L
"WindowText", /* 08 = COLOR_WINDOWTEXT */
36 L
"TitleText", /* 09 = COLOR_CAPTIONTEXT */
37 L
"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
38 L
"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
39 L
"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
40 L
"Hilight", /* 13 = COLOR_HIGHLIGHT */
41 L
"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
42 L
"ButtonFace", /* 15 = COLOR_BTNFACE */
43 L
"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
44 L
"GrayText", /* 17 = COLOR_GRAYTEXT */
45 L
"ButtonText", /* 18 = COLOR_BTNTEXT */
46 L
"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
47 L
"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
48 L
"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
49 L
"ButtonLight", /* 22 = COLOR_3DLIGHT */
50 L
"InfoText", /* 23 = COLOR_INFOTEXT */
51 L
"InfoWindow", /* 24 = COLOR_INFOBK */
52 L
"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
53 L
"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
54 L
"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
55 L
"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
56 L
"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
57 L
"MenuBar", /* 30 = COLOR_MENUBAR */
60 /******************************************************************************/
63 SchemeSetMetric(IN COLOR_SCHEME
*scheme
, int id
, int value
)
67 case SIZE_BORDER_WIDTH
: scheme
->ncMetrics
.iBorderWidth
= value
; break;
68 case SIZE_SCROLL_WIDTH
: scheme
->ncMetrics
.iScrollWidth
= value
; break;
69 case SIZE_SCROLL_HEIGHT
: scheme
->ncMetrics
.iScrollHeight
= value
; break;
70 case SIZE_CAPTION_WIDTH
: scheme
->ncMetrics
.iCaptionWidth
= value
; break;
71 case SIZE_CAPTION_HEIGHT
: scheme
->ncMetrics
.iCaptionHeight
= value
; break;
72 case SIZE_SM_CAPTION_WIDTH
: scheme
->ncMetrics
.iSmCaptionWidth
= value
; break;
73 case SIZE_SM_CAPTION_HEIGHT
: scheme
->ncMetrics
.iSmCaptionHeight
= value
; break;
74 case SIZE_MENU_WIDTH
: scheme
->ncMetrics
.iMenuWidth
= value
; break;
75 case SIZE_MENU_HEIGHT
: scheme
->ncMetrics
.iMenuHeight
= value
; break;
76 case SIZE_ICON
: scheme
->iIconSize
= value
; break;
77 case SIZE_ICON_SPACE_X
: scheme
->icMetrics
.iHorzSpacing
= value
; break;
78 case SIZE_ICON_SPACE_Y
: scheme
->icMetrics
.iVertSpacing
= value
; break;
83 SchemeGetMetric(IN COLOR_SCHEME
*scheme
, int id
)
87 case SIZE_BORDER_WIDTH
: return scheme
->ncMetrics
.iBorderWidth
;
88 case SIZE_SCROLL_WIDTH
: return scheme
->ncMetrics
.iScrollWidth
;
89 case SIZE_SCROLL_HEIGHT
: return scheme
->ncMetrics
.iScrollHeight
;
90 case SIZE_CAPTION_WIDTH
: return scheme
->ncMetrics
.iCaptionWidth
;
91 case SIZE_CAPTION_HEIGHT
: return scheme
->ncMetrics
.iCaptionHeight
;
92 case SIZE_SM_CAPTION_WIDTH
: return scheme
->ncMetrics
.iSmCaptionWidth
;
93 case SIZE_SM_CAPTION_HEIGHT
: return scheme
->ncMetrics
.iSmCaptionHeight
;
94 case SIZE_MENU_WIDTH
: return scheme
->ncMetrics
.iMenuWidth
;
95 case SIZE_MENU_HEIGHT
: return scheme
->ncMetrics
.iMenuHeight
;
96 case SIZE_ICON
: return scheme
->iIconSize
;
97 case SIZE_ICON_SPACE_X
: return scheme
->icMetrics
.iHorzSpacing
;
98 case SIZE_ICON_SPACE_Y
: return scheme
->icMetrics
.iVertSpacing
;
104 SchemeGetFont(IN COLOR_SCHEME
*scheme
, int id
)
108 case FONT_CAPTION
: return &scheme
->ncMetrics
.lfCaptionFont
;
109 case FONT_SMCAPTION
: return &scheme
->ncMetrics
.lfSmCaptionFont
;
110 case FONT_MENU
: return &scheme
->ncMetrics
.lfMenuFont
;
111 case FONT_STATUS
: return &scheme
->ncMetrics
.lfStatusFont
;
112 case FONT_MESSAGE
: return &scheme
->ncMetrics
.lfMessageFont
;
113 case FONT_ICON
: return &scheme
->icMetrics
.lfFont
;
119 * LoadCurrentScheme: Populates the passed scheme based on the current system settings
122 LoadCurrentScheme(OUT COLOR_SCHEME
*scheme
)
127 #if (WINVER >= 0x0600)
132 for (i
= 0; i
< NUM_COLORS
; i
++)
134 scheme
->crColor
[i
] = (COLORREF
)GetSysColor(i
);
137 /* Load non client metrics */
138 scheme
->ncMetrics
.cbSize
= sizeof(NONCLIENTMETRICSW
);
140 #if (WINVER >= 0x0600)
141 /* Size of NONCLIENTMETRICSA/W depends on current version of the OS.
143 * https://msdn.microsoft.com/en-us/library/windows/desktop/ff729175%28v=vs.85%29.aspx
145 if (GetVersionEx(&osvi
))
147 /* Windows XP and earlier */
148 if (osvi
.dwMajorVersion
<= 5)
149 scheme
->ncMetrics
.cbSize
-= sizeof(scheme
->ncMetrics
.iPaddedBorderWidth
);
153 ret
= SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
,
154 sizeof(NONCLIENTMETRICSW
),
157 if (!ret
) return FALSE
;
159 /* Load icon metrics */
160 scheme
->icMetrics
.cbSize
= sizeof(ICONMETRICSW
);
161 ret
= SystemParametersInfoW(SPI_GETICONMETRICS
,
162 sizeof(ICONMETRICSW
),
165 if (!ret
) return FALSE
;
167 /* Load flat menu style */
168 ret
= SystemParametersInfoW(SPI_GETFLATMENU
,
172 if (!ret
) return FALSE
;
175 /* Use the following transition effect for menus and tooltips */
176 ret
= SystemParametersInfoW(SPI_GETMENUANIMATION
,
178 &scheme
->Effects
.bMenuAnimation
,
180 if (!ret
) return FALSE
;
182 ret
= SystemParametersInfoW(SPI_GETMENUFADE
,
184 &scheme
->Effects
.bMenuFade
,
186 if (!ret
) return FALSE
;
188 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
189 * Just keep them in sync for now:
191 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
192 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
194 /* Use the following transition effect for menus and tooltips */
195 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHING
,
197 &scheme
->Effects
.bFontSmoothing
,
199 if (!ret
) return FALSE
;
201 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE
,
203 &scheme
->Effects
.uiFontSmoothingType
,
205 if (!ret
) return FALSE
;
207 /* Show shadows under menus */
208 ret
= SystemParametersInfoW(SPI_GETDROPSHADOW
,
210 &scheme
->Effects
.bDropShadow
,
212 if (!ret
) return FALSE
;
214 /* Show content of windows during dragging */
215 ret
= SystemParametersInfoW(SPI_GETDRAGFULLWINDOWS
,
217 &scheme
->Effects
.bDragFullWindows
,
219 if (!ret
) return FALSE
;
221 /* Hide underlined letters for keyboard navigation until the Alt key is pressed */
222 ret
= SystemParametersInfoW(SPI_GETKEYBOARDCUES
,
224 &scheme
->Effects
.bKeyboardCues
,
226 if (!ret
) return FALSE
;
228 /* Read the icon size from registry */
229 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPMetrics
, &hKey
);
230 if(Result
== ERROR_SUCCESS
)
232 scheme
->iIconSize
= SHRegGetIntW(hKey
, L
"Shell Icon Size", 32);
240 * LoadSchemeFromReg: Populates the passed scheme with values retrieved from registry
243 LoadSchemeFromReg(OUT COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
246 WCHAR strValueName
[10], strSchemeKey
[MAX_PATH
];
247 HKEY hkScheme
= NULL
;
248 DWORD dwType
, dwLength
;
253 wsprintf(strSchemeKey
, L
"%s\\%s\\Sizes\\%s",
255 pSelectedTheme
->Color
->StyleName
,
256 pSelectedTheme
->Size
->StyleName
);
258 result
= RegOpenKeyW(HKEY_CURRENT_USER
, strSchemeKey
, &hkScheme
);
259 if (result
!= ERROR_SUCCESS
) return FALSE
;
261 scheme
->bFlatMenus
= SHRegGetIntW(hkScheme
, L
"FlatMenus", 0);
263 for (i
= 0; i
< NUM_COLORS
; i
++)
265 wsprintf(strValueName
, L
"Color #%d", i
);
266 dwLength
= sizeof(COLORREF
);
267 result
= RegQueryValueExW(hkScheme
,
271 (LPBYTE
)&scheme
->crColor
[i
],
273 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_DWORD
)
275 /* Failed to read registry value, initialize with current setting for now */
276 scheme
->crColor
[i
] = GetSysColor(i
);
280 for (i
= 0; i
< NUM_FONTS
; i
++)
282 PLOGFONTW lpfFont
= SchemeGetFont(scheme
, i
);
284 wsprintf(strValueName
, L
"Font #%d", i
);
285 dwLength
= sizeof(LOGFONT
);
286 result
= RegQueryValueExW(hkScheme
,
292 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_BINARY
||
293 dwLength
!= sizeof(LOGFONT
))
295 /* Failed to read registry value */
300 for (i
= 0; i
< NUM_SIZES
; i
++)
302 wsprintf(strValueName
, L
"Size #%d", i
);
303 dwLength
= sizeof(UINT64
);
304 result
= RegQueryValueExW(hkScheme
,
310 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_QWORD
||
311 dwLength
!= sizeof(UINT64
))
313 /* Failed to read registry value, initialize with current setting for now */
317 SchemeSetMetric(scheme
, i
, (int)iSize
);
321 RegCloseKey(hkScheme
);
327 * ApplyScheme: Applies the selected scheme and stores its id in the registry if needed
330 ApplyScheme(IN COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
334 WCHAR clText
[16], *StyleName
;
335 INT ColorList
[NUM_COLORS
];
337 /* Apply system colors */
338 for (i
= 0; i
< NUM_COLORS
; i
++)
340 SetSysColors(NUM_COLORS
, ColorList
, scheme
->crColor
);
342 /* Save colors to registry */
343 Result
= RegCreateKeyW(HKEY_CURRENT_USER
, g_CPColors
, &hKey
);
344 if (Result
== ERROR_SUCCESS
)
346 for (i
= 0; i
< NUM_COLORS
; i
++)
350 GetRValue(scheme
->crColor
[i
]),
351 GetGValue(scheme
->crColor
[i
]),
352 GetBValue(scheme
->crColor
[i
]));
359 (lstrlen(clText
) + 1) * sizeof(WCHAR
));
364 /* Apply non client metrics */
365 SystemParametersInfoW(SPI_SETNONCLIENTMETRICS
,
366 sizeof(NONCLIENTMETRICS
),
368 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
370 /* Apply icon metrics */
371 SystemParametersInfoW(SPI_SETICONMETRICS
,
374 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
376 /* Effects, save only when needed: */
377 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
378 * Just keep them in sync for now.
381 #define SYS_CONFIG(__uiAction, __uiParam, __pvParam) \
382 SystemParametersInfoW(__uiAction, __uiParam, __pvParam, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)
384 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
385 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
387 /* Use the following transition effect for menus and tooltips */
388 SYS_CONFIG(SPI_SETMENUANIMATION
, 0, IntToPtr(scheme
->Effects
.bMenuAnimation
));
389 SYS_CONFIG(SPI_SETMENUFADE
, 0, IntToPtr(scheme
->Effects
.bMenuFade
));
391 /* Use the following method to smooth edges of screen fonts */
392 SYS_CONFIG(SPI_SETFONTSMOOTHING
, scheme
->Effects
.bFontSmoothing
, 0);
393 SYS_CONFIG(SPI_SETFONTSMOOTHINGTYPE
, 0, IntToPtr(scheme
->Effects
.uiFontSmoothingType
));
396 * Refresh and redraw all the windows, otherwise the font smoothing changes
397 * only appear after any future partial region invalidation.
398 * Not everyone listens for this WM_SETTINGCHANGE, including the shell and most third party programs.
400 InvalidateRect(NULL
, NULL
, TRUE
);
402 /* Use large icons */
403 //SYS_CONFIG(SPI_GETDRAGFULLWINDOWS, (PVOID) g->SchemeAdv.Effects.bMenuFade);
405 /* Show shadows under menus */
406 SYS_CONFIG(SPI_SETDROPSHADOW
, 0, IntToPtr(scheme
->Effects
.bDropShadow
));
408 /* Show window contents while dragging */
409 SYS_CONFIG(SPI_SETDRAGFULLWINDOWS
, scheme
->Effects
.bDragFullWindows
, 0);
411 /* Hide underlined letters for keyboard navigation until I press the Alt key */
412 SYS_CONFIG(SPI_SETKEYBOARDCUES
, 0, IntToPtr(scheme
->Effects
.bKeyboardCues
));
414 // SYS_CONFIG(SPI_SETACTIVEWINDOWTRACKING, 0, IntToPtr(scheme->Effects.bActiveWindowTracking));
415 // SYS_CONFIG(SPI_SETCOMBOBOXANIMATION, 0, IntToPtr(scheme->Effects.bComboBoxAnimation));
416 // SYS_CONFIG(SPI_SETLISTBOXSMOOTHSCROLLING, 0, IntToPtr(scheme->Effects.bListBoxSmoothScrolling));
417 // SYS_CONFIG(SPI_SETGRADIENTCAPTIONS, 0, IntToPtr(scheme->Effects.bGradientCaptions));
418 // SYS_CONFIG(SPI_SETACTIVEWNDTRKZORDER, 0, IntToPtr(scheme->Effects.bActiveWndTrkZorder));
419 // SYS_CONFIG(SPI_SETHOTTRACKING, 0, IntToPtr(scheme->Effects.bHotTracking));
420 // SYS_CONFIG(SPI_SETSELECTIONFADE, 0, IntToPtr(scheme->Effects.bSelectionFade));
421 SYS_CONFIG(SPI_SETTOOLTIPANIMATION
, 0, IntToPtr(scheme
->Effects
.bTooltipAnimation
));
422 SYS_CONFIG(SPI_SETTOOLTIPFADE
, 0, IntToPtr(scheme
->Effects
.bTooltipFade
));
423 // SYS_CONFIG(SPI_SETCURSORSHADOW, 0, IntToPtr(scheme->Effects.bCursorShadow));
424 // SYS_CONFIG(SPI_SETUIEFFECTS, 0, IntToPtr(scheme->Effects.bUiEffects));
428 /* Save SchemeId in the registry */
429 if (pSelectedTheme
->Theme
!= NULL
&& pSelectedTheme
->ThemeActive
== FALSE
)
431 StyleName
= pSelectedTheme
->Color
->StyleName
;
432 SHSetValueW(HKEY_CURRENT_USER
,
437 (lstrlenW(StyleName
) + 1) * sizeof(WCHAR
));
442 CreateTheme(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
446 pTheme
= (PTHEME
) malloc(sizeof(THEME
));
447 if (pTheme
== NULL
) return NULL
;
449 pTheme
->DisplayName
= _wcsdup(pszDisplayName
);
450 if (pTheme
->DisplayName
== NULL
)
456 pTheme
->ColoursList
= NULL
;
457 pTheme
->NextTheme
= NULL
;
458 pTheme
->SizesList
= NULL
;
462 pTheme
->ThemeFileName
= NULL
;
466 pTheme
->ThemeFileName
= _wcsdup(pszName
);
467 if (pTheme
->ThemeFileName
== NULL
)
469 free(pTheme
->DisplayName
);
478 CreateStyle(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
482 pStyle
= (PTHEME_STYLE
) malloc(sizeof(THEME_STYLE
));
483 if (pStyle
== NULL
) return NULL
;
485 pStyle
->StyleName
= _wcsdup(pszName
);
486 if (pStyle
->StyleName
== NULL
)
492 pStyle
->DisplayName
= _wcsdup(pszDisplayName
);
493 if (pStyle
->DisplayName
== NULL
)
495 free(pStyle
->StyleName
);
500 pStyle
->ChildStyle
= NULL
;
501 pStyle
->NextStyle
= NULL
;
507 CleanupStyles(IN PTHEME_STYLE pStylesList
)
509 PTHEME_STYLE pStyle
, pStyleOld
;
511 pStyle
= pStylesList
;
514 if (pStyle
->ChildStyle
) CleanupStyles(pStyle
->ChildStyle
);
515 if (pStyle
->DisplayName
) free(pStyle
->DisplayName
);
516 if (pStyle
->StyleName
) free(pStyle
->StyleName
);
519 pStyle
= pStyle
->NextStyle
;
525 CleanupThemes(IN PTHEME pThemeList
)
527 PTHEME pTheme
, pThemeOld
;
532 CleanupStyles(pTheme
->ColoursList
);
533 if (pTheme
->SizesList
) CleanupStyles(pTheme
->SizesList
);
534 if (pTheme
->DisplayName
) free(pTheme
->DisplayName
);
535 if (pTheme
->ThemeFileName
) free(pTheme
->ThemeFileName
);
538 pTheme
= pTheme
->NextTheme
;
544 FindStyle(IN PTHEME_STYLE pStylesList
, IN PCWSTR StyleName
)
548 for (pStyle
= pStylesList
; pStyle
; pStyle
= pStyle
->NextStyle
)
550 if (_wcsicmp(pStyle
->StyleName
, StyleName
) == 0)
556 /* If we can't find the style requested, return the first one */
561 * LoadSchemeSizes: Returns a list of sizes from the registry key of a scheme
564 LoadSchemeSizes(IN HKEY hkScheme
)
566 HKEY hkSizes
, hkSize
;
569 WCHAR wstrSizeName
[5], wstrDisplayName
[50];
570 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
572 Result
= RegOpenKeyW(hkScheme
, L
"Sizes", &hkSizes
);
573 if (Result
!= ERROR_SUCCESS
) return NULL
;
576 while ((RegEnumKeyW(hkSizes
, iStyle
, wstrSizeName
, 5) == ERROR_SUCCESS
))
580 Result
= RegOpenKeyW(hkSizes
, wstrSizeName
, &hkSize
);
581 if (Result
!= ERROR_SUCCESS
) continue;
583 Result
= RegLoadMUIStringW(hkSize
,
586 sizeof(wstrDisplayName
),
590 if (Result
!= ERROR_SUCCESS
)
592 Result
= RegLoadMUIStringW(hkSize
,
595 sizeof(wstrDisplayName
),
601 if (Result
== ERROR_SUCCESS
)
602 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrDisplayName
);
604 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrSizeName
);
606 if (pCurrentStyle
!= NULL
)
608 pCurrentStyle
->NextStyle
= List
;
609 List
= pCurrentStyle
;
615 RegCloseKey(hkSizes
);
620 * LoadClassicColorSchemes: Returns a list of classic theme colours from the registry key of a scheme
623 LoadClassicColorSchemes(VOID
)
626 HKEY hkNewSchemes
, hkScheme
;
628 WCHAR wstrStyleName
[5], wstrDisplayName
[50];
629 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
631 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
632 if (Result
!= ERROR_SUCCESS
) return NULL
;
635 while ((RegEnumKeyW(hkNewSchemes
, iStyle
, wstrStyleName
, 5) == ERROR_SUCCESS
))
639 Result
= RegOpenKeyW(hkNewSchemes
, wstrStyleName
, &hkScheme
);
640 if (Result
!= ERROR_SUCCESS
) continue;
642 Result
= RegLoadMUIStringW(hkScheme
,
645 sizeof(wstrDisplayName
),
649 if (Result
!= ERROR_SUCCESS
)
651 Result
= RegLoadMUIStringW(hkScheme
,
654 sizeof(wstrDisplayName
),
660 if (Result
== ERROR_SUCCESS
)
661 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrDisplayName
);
663 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrStyleName
);
665 if (pCurrentStyle
!= NULL
)
667 pCurrentStyle
->NextStyle
= List
;
668 pCurrentStyle
->ChildStyle
= LoadSchemeSizes(hkScheme
);
669 if(pCurrentStyle
->ChildStyle
== NULL
)
670 CleanupStyles(pCurrentStyle
);
672 List
= pCurrentStyle
;
675 RegCloseKey(hkScheme
);
678 RegCloseKey(hkNewSchemes
);
682 typedef HRESULT (WINAPI
*ENUMTHEMESTYLE
) (LPCWSTR
, LPWSTR
, DWORD
, PTHEMENAMES
);
685 EnumThemeStyles(IN LPCWSTR pszThemeFileName
, IN ENUMTHEMESTYLE pfnEnumTheme
)
689 THEME_STYLE
*List
= NULL
, **ppPrevStyle
, *pCurrentStyle
;
693 while (SUCCEEDED(pfnEnumTheme (pszThemeFileName
, NULL
, index
++, &names
)))
695 pCurrentStyle
= CreateStyle(names
.szName
, names
.szDisplayName
);
696 if(pCurrentStyle
== NULL
) break;
698 *ppPrevStyle
= pCurrentStyle
;
699 ppPrevStyle
= &pCurrentStyle
->NextStyle
;
706 EnumThemeProc(IN LPVOID lpReserved
,
707 IN LPCWSTR pszThemeFileName
,
708 IN LPCWSTR pszThemeName
,
709 IN LPCWSTR pszToolTip
,
710 IN LPVOID lpReserved2
,
711 IN OUT LPVOID lpData
)
713 PTHEME
*List
, pTheme
;
715 List
= (PTHEME
*)lpData
;
717 pTheme
= CreateTheme(pszThemeFileName
, pszThemeName
);
718 if (pTheme
== NULL
) return FALSE
;
720 pTheme
->SizesList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeSizes
);
721 pTheme
->ColoursList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeColors
);
722 if(pTheme
->SizesList
== NULL
|| pTheme
->ColoursList
== NULL
)
724 CleanupThemes(pTheme
);
728 pTheme
->NextTheme
= *List
;
735 * LoadThemes: Returns a list that contains tha classic theme and
736 * the visual styles of the system
742 PTHEME pClassicTheme
;
743 WCHAR strClassicTheme
[40];
744 WCHAR szThemesPath
[MAX_PATH
], *pszClassicTheme
;
747 /* Insert the classic theme */
748 res
= LoadString(hApplet
, IDS_CLASSIC_THEME
, strClassicTheme
, 40);
749 pszClassicTheme
= (res
> 0 ? strClassicTheme
: L
"Classic Theme");
750 pClassicTheme
= CreateTheme(NULL
, pszClassicTheme
);
751 if (pClassicTheme
== NULL
) return NULL
;
752 pClassicTheme
->ColoursList
= LoadClassicColorSchemes();
754 /* Get path to themes folder */
755 ZeroMemory(szThemesPath
, sizeof(szThemesPath
));
756 hret
= SHGetFolderPathW (NULL
, CSIDL_RESOURCES
, NULL
, SHGFP_TYPE_DEFAULT
, szThemesPath
);
757 if (FAILED(hret
)) return pClassicTheme
;
758 lstrcatW (szThemesPath
, L
"\\Themes");
760 /* Enumerate themes */
761 hret
= EnumThemes( szThemesPath
, EnumThemeProc
, &pClassicTheme
->NextTheme
);
764 pClassicTheme
->NextTheme
= NULL
;
765 if (pClassicTheme
->ColoursList
== NULL
)
767 free(pClassicTheme
->DisplayName
);
773 return pClassicTheme
;
777 * GetActiveTheme: Gets the active theme and populates pSelectedTheme
778 * with entries from the list of loaded themes
781 GetActiveTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
783 WCHAR szThemeFileName
[MAX_PATH
];
784 WCHAR szColorBuff
[MAX_PATH
];
785 WCHAR szSizeBuff
[MAX_PATH
];
789 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
791 /* Retrieve the name of the current theme */
792 hret
= GetCurrentThemeName(szThemeFileName
,
798 if (FAILED(hret
)) return FALSE
;
800 for (pTheme
= pThemeList
; pTheme
; pTheme
= pTheme
->NextTheme
)
802 if (pTheme
->ThemeFileName
&&
803 _wcsicmp(pTheme
->ThemeFileName
, szThemeFileName
) == 0)
809 if (pTheme
== NULL
) return FALSE
;
811 pSelectedTheme
->ThemeActive
= TRUE
;
812 pSelectedTheme
->Theme
= pTheme
;
813 pSelectedTheme
->Color
= FindStyle(pTheme
->ColoursList
, szColorBuff
);
814 pSelectedTheme
->Size
= FindStyle(pTheme
->SizesList
, szSizeBuff
);
820 * GetActiveTheme: Gets the active classic theme and populates pSelectedTheme
821 * with entries from the list of loaded themes
824 GetActiveClassicTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
827 WCHAR szSelectedClassicScheme
[5], szSelectedClassicSize
[5];
829 DWORD dwType
, dwDisplayNameLength
;
830 PTHEME_STYLE pCurrentStyle
, pCurrentSize
;
832 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
835 szSelectedClassicScheme
[0] = 0;
836 szSelectedClassicSize
[0] = 0;
838 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
839 if (Result
!= ERROR_SUCCESS
) return FALSE
;
842 dwDisplayNameLength
= sizeof(szSelectedClassicScheme
);
843 Result
= RegQueryValueEx(hkNewSchemes
, L
"SelectedStyle", NULL
, &dwType
,
844 (LPBYTE
)&szSelectedClassicScheme
, &dwDisplayNameLength
);
845 if (Result
== ERROR_SUCCESS
)
848 dwDisplayNameLength
= sizeof(szSelectedClassicSize
);
849 Result
= SHGetValue(hkNewSchemes
, szSelectedClassicScheme
, L
"SelectedSize",
850 &dwType
, szSelectedClassicSize
, &dwDisplayNameLength
);
853 RegCloseKey(hkNewSchemes
);
855 pCurrentStyle
= FindStyle(pThemeList
->ColoursList
, szSelectedClassicScheme
);
856 pCurrentSize
= FindStyle(pCurrentStyle
->ChildStyle
, szSelectedClassicSize
);
858 pSelectedTheme
->Theme
= pThemeList
;
859 pSelectedTheme
->Color
= pCurrentStyle
;
860 pSelectedTheme
->Size
= pCurrentSize
;
866 ActivateTheme(IN PTHEME_SELECTION pSelectedTheme
)
868 HTHEMEFILE hThemeFile
= 0;
871 if (pSelectedTheme
->ThemeActive
)
873 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
874 pSelectedTheme
->Color
->StyleName
,
875 pSelectedTheme
->Size
->StyleName
,
879 if (!SUCCEEDED(hret
)) return FALSE
;
882 hret
= ApplyTheme(hThemeFile
, "", 0);
884 if (pSelectedTheme
->ThemeActive
)
886 CloseThemeFile(hThemeFile
);
889 return SUCCEEDED(hret
);
893 LoadSchemeFromTheme(OUT PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
)
895 HTHEMEFILE hThemeFile
= 0;
900 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
901 pSelectedTheme
->Color
->StyleName
,
902 pSelectedTheme
->Size
->StyleName
,
906 if (!SUCCEEDED(hret
)) return FALSE
;
908 hTheme
= OpenThemeDataFromFile(hThemeFile
, hCPLWindow
, L
"WINDOW", 0);
909 if (hTheme
== NULL
) return FALSE
;
912 for (i
= 0; i
< NUM_COLORS
; i
++)
914 scheme
->crColor
[i
] = GetThemeSysColor(hTheme
,i
);
918 /* I wonder why GetThemeSysInt doesn't work here */
919 scheme
->ncMetrics
.iBorderWidth
= GetThemeSysSize(hTheme
, SM_CXFRAME
);
920 scheme
->ncMetrics
.iScrollWidth
= GetThemeSysSize(hTheme
, SM_CXVSCROLL
);
921 scheme
->ncMetrics
.iScrollHeight
= GetThemeSysSize(hTheme
, SM_CYHSCROLL
);
922 scheme
->ncMetrics
.iCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSIZE
);
923 scheme
->ncMetrics
.iCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSIZE
);
924 scheme
->ncMetrics
.iSmCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSMSIZE
);
925 scheme
->ncMetrics
.iSmCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSMSIZE
);
926 scheme
->ncMetrics
.iMenuWidth
= GetThemeSysSize(hTheme
, SM_CXMENUSIZE
);
927 scheme
->ncMetrics
.iMenuHeight
= GetThemeSysSize(hTheme
, SM_CYMENUSIZE
);
930 GetThemeSysFont(hTheme
, TMT_CAPTIONFONT
, &scheme
->ncMetrics
.lfCaptionFont
);
931 GetThemeSysFont(hTheme
, TMT_SMALLCAPTIONFONT
, &scheme
->ncMetrics
.lfSmCaptionFont
);
932 GetThemeSysFont(hTheme
, TMT_MENUFONT
, &scheme
->ncMetrics
.lfMenuFont
);
933 GetThemeSysFont(hTheme
, TMT_STATUSFONT
, &scheme
->ncMetrics
.lfStatusFont
);
934 GetThemeSysFont(hTheme
, TMT_MSGBOXFONT
, &scheme
->ncMetrics
.lfMessageFont
);
935 GetThemeSysFont(hTheme
, TMT_ICONTITLEFONT
, &scheme
->icMetrics
.lfFont
);
937 CloseThemeData(hTheme
);
943 DrawThemePreview(IN HDC hdcMem
, IN PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
, IN PRECT prcWindow
)
948 hbrBack
= CreateSolidBrush(scheme
->crColor
[COLOR_DESKTOP
]);
950 FillRect(hdcMem
, prcWindow
, hbrBack
);
951 DeleteObject(hbrBack
);
953 InflateRect(prcWindow
, -10, -10);
955 hres
= DrawNCPreview(hdcMem
,
958 pSelectedTheme
->Theme
->ThemeFileName
,
959 pSelectedTheme
->Color
->StyleName
,
960 pSelectedTheme
->Size
->StyleName
,
964 return SUCCEEDED(hres
);