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
)
129 for (i
= 0; i
< NUM_COLORS
; i
++)
131 scheme
->crColor
[i
] = (COLORREF
)GetSysColor(i
);
134 /* Load non client metrics */
135 scheme
->ncMetrics
.cbSize
= sizeof(NONCLIENTMETRICSW
);
136 ret
= SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
,
137 sizeof(NONCLIENTMETRICSW
),
140 if (!ret
) return FALSE
;
142 /* Load icon metrics */
143 scheme
->icMetrics
.cbSize
= sizeof(ICONMETRICSW
);
144 ret
= SystemParametersInfoW(SPI_GETICONMETRICS
,
145 sizeof(ICONMETRICSW
),
148 if (!ret
) return FALSE
;
150 /* Load flat menu style */
151 ret
= SystemParametersInfoW(SPI_GETFLATMENU
,
155 if (!ret
) return FALSE
;
158 /* Use the following transition effect for menus and tooltips */
159 ret
= SystemParametersInfoW(SPI_GETMENUANIMATION
,
161 &scheme
->Effects
.bMenuAnimation
,
163 if (!ret
) return FALSE
;
165 ret
= SystemParametersInfoW(SPI_GETMENUFADE
,
167 &scheme
->Effects
.bMenuFade
,
169 if (!ret
) return FALSE
;
171 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
172 * Just keep them in sync for now:
174 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
175 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
177 /* Use the following transition effect for menus and tooltips */
178 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHING
,
180 &scheme
->Effects
.bFontSmoothing
,
182 if (!ret
) return FALSE
;
184 ret
= SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE
,
186 &scheme
->Effects
.uiFontSmoothingType
,
188 if (!ret
) return FALSE
;
190 /* Show shadows under menus */
191 ret
= SystemParametersInfoW(SPI_GETDROPSHADOW
,
193 &scheme
->Effects
.bDropShadow
,
195 if (!ret
) return FALSE
;
197 /* Show content of windows during dragging */
198 ret
= SystemParametersInfoW(SPI_GETDRAGFULLWINDOWS
,
200 &scheme
->Effects
.bDragFullWindows
,
202 if (!ret
) return FALSE
;
204 /* Hide underlined letters for keyboard navigation until the Alt key is pressed */
205 ret
= SystemParametersInfoW(SPI_GETKEYBOARDCUES
,
207 &scheme
->Effects
.bKeyboardCues
,
209 if (!ret
) return FALSE
;
211 /* Read the icon size from registry */
212 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPMetrics
, &hKey
);
213 if(Result
== ERROR_SUCCESS
)
215 scheme
->iIconSize
= SHRegGetIntW(hKey
, L
"Shell Icon Size", 32);
223 * LoadSchemeFromReg: Populates the passed scheme with values retireved from registry
226 LoadSchemeFromReg(OUT COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
229 WCHAR strValueName
[10], strSchemeKey
[MAX_PATH
];
230 HKEY hkScheme
= NULL
;
231 DWORD dwType
, dwLength
;
236 wsprintf(strSchemeKey
, L
"%s\\%s\\Sizes\\%s",
238 pSelectedTheme
->Color
->StyleName
,
239 pSelectedTheme
->Size
->StyleName
);
241 result
= RegOpenKeyW(HKEY_CURRENT_USER
, strSchemeKey
, &hkScheme
);
242 if (result
!= ERROR_SUCCESS
) return FALSE
;
244 scheme
->bFlatMenus
= SHRegGetIntW(hkScheme
, L
"FlatMenus", 0);
246 for (i
= 0; i
< NUM_COLORS
; i
++)
248 wsprintf(strValueName
, L
"Color #%d", i
);
249 dwLength
= sizeof(COLORREF
);
250 result
= RegQueryValueExW(hkScheme
,
254 (LPBYTE
)&scheme
->crColor
[i
],
256 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_DWORD
)
258 /* Failed to read registry value, initialize with current setting for now */
259 scheme
->crColor
[i
] = GetSysColor(i
);
263 for (i
= 0; i
< NUM_FONTS
; i
++)
265 PLOGFONTW lpfFont
= SchemeGetFont(scheme
, i
);
267 wsprintf(strValueName
, L
"Font #%d", i
);
268 dwLength
= sizeof(LOGFONT
);
269 result
= RegQueryValueExW(hkScheme
,
275 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_BINARY
||
276 dwLength
!= sizeof(LOGFONT
))
278 /* Failed to read registry value */
283 for (i
= 0; i
< NUM_SIZES
; i
++)
285 wsprintf(strValueName
, L
"Size #%d", i
);
286 dwLength
= sizeof(UINT64
);
287 result
= RegQueryValueExW(hkScheme
,
293 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_QWORD
||
294 dwLength
!= sizeof(UINT64
))
296 /* Failed to read registry value, initialize with current setting for now */
300 SchemeSetMetric(scheme
, i
, (int)iSize
);
304 RegCloseKey(hkScheme
);
310 * ApplyScheme: Applies the selected scheme and stores its id in the registry if needed
313 ApplyScheme(IN COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
317 WCHAR clText
[16], *StyleName
;
318 INT ColorList
[NUM_COLORS
];
320 /* Apply system colors */
321 for (i
= 0; i
< NUM_COLORS
; i
++)
323 SetSysColors(NUM_COLORS
, ColorList
, scheme
->crColor
);
325 /* Save colors to registry */
326 Result
= RegCreateKeyW(HKEY_CURRENT_USER
, g_CPColors
, &hKey
);
327 if (Result
== ERROR_SUCCESS
)
329 for (i
= 0; i
< NUM_COLORS
; i
++)
333 GetRValue(scheme
->crColor
[i
]),
334 GetGValue(scheme
->crColor
[i
]),
335 GetBValue(scheme
->crColor
[i
]));
342 (lstrlen(clText
) + 1) * sizeof(WCHAR
));
347 /* Apply non client metrics */
348 SystemParametersInfoW(SPI_SETNONCLIENTMETRICS
,
349 sizeof(NONCLIENTMETRICS
),
351 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
353 /* Apply icon metrics */
354 SystemParametersInfoW(SPI_SETICONMETRICS
,
357 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
359 /* Effects, save only when needed: */
360 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
361 * Just keep them in sync for now.
364 #define SYS_CONFIG(__uiAction, __uiParam, __pvParam) \
365 SystemParametersInfoW(__uiAction, __uiParam, __pvParam, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)
367 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
368 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
370 /* Use the following transition effect for menus and tooltips */
371 SYS_CONFIG(SPI_SETMENUANIMATION
, 0, IntToPtr(scheme
->Effects
.bMenuAnimation
));
372 SYS_CONFIG(SPI_SETMENUFADE
, 0, IntToPtr(scheme
->Effects
.bMenuFade
));
374 /* Use the following method to smooth edges of screen fonts */
375 SYS_CONFIG(SPI_SETFONTSMOOTHING
, scheme
->Effects
.bFontSmoothing
, 0);
376 SYS_CONFIG(SPI_SETFONTSMOOTHINGTYPE
, 0, IntToPtr(scheme
->Effects
.uiFontSmoothingType
));
379 * Refresh and redraw all the windows, otherwise the font smoothing changes
380 * only appear after any future partial region invalidation.
381 * Not everyone listens for this WM_SETTINGCHANGE, including the shell and most third party programs.
383 InvalidateRect(NULL
, NULL
, TRUE
);
385 /* Use large icons */
386 //SYS_CONFIG(SPI_GETDRAGFULLWINDOWS, (PVOID) g->SchemeAdv.Effects.bMenuFade);
388 /* Show shadows under menus */
389 SYS_CONFIG(SPI_SETDROPSHADOW
, 0, IntToPtr(scheme
->Effects
.bDropShadow
));
391 /* Show window contents while dragging */
392 SYS_CONFIG(SPI_SETDRAGFULLWINDOWS
, scheme
->Effects
.bDragFullWindows
, 0);
394 /* Hide underlined letters for keyboard navigation until I press the Alt key */
395 SYS_CONFIG(SPI_SETKEYBOARDCUES
, 0, IntToPtr(scheme
->Effects
.bKeyboardCues
));
397 // SYS_CONFIG(SPI_SETACTIVEWINDOWTRACKING, 0, IntToPtr(scheme->Effects.bActiveWindowTracking));
398 // SYS_CONFIG(SPI_SETCOMBOBOXANIMATION, 0, IntToPtr(scheme->Effects.bComboBoxAnimation));
399 // SYS_CONFIG(SPI_SETLISTBOXSMOOTHSCROLLING, 0, IntToPtr(scheme->Effects.bListBoxSmoothScrolling));
400 // SYS_CONFIG(SPI_SETGRADIENTCAPTIONS, 0, IntToPtr(scheme->Effects.bGradientCaptions));
401 // SYS_CONFIG(SPI_SETACTIVEWNDTRKZORDER, 0, IntToPtr(scheme->Effects.bActiveWndTrkZorder));
402 // SYS_CONFIG(SPI_SETHOTTRACKING, 0, IntToPtr(scheme->Effects.bHotTracking));
403 // SYS_CONFIG(SPI_SETSELECTIONFADE, 0, IntToPtr(scheme->Effects.bSelectionFade));
404 SYS_CONFIG(SPI_SETTOOLTIPANIMATION
, 0, IntToPtr(scheme
->Effects
.bTooltipAnimation
));
405 SYS_CONFIG(SPI_SETTOOLTIPFADE
, 0, IntToPtr(scheme
->Effects
.bTooltipFade
));
406 // SYS_CONFIG(SPI_SETCURSORSHADOW, 0, IntToPtr(scheme->Effects.bCursorShadow));
407 // SYS_CONFIG(SPI_SETUIEFFECTS, 0, IntToPtr(scheme->Effects.bUiEffects));
411 /* Save SchemeId in the registry */
412 if (pSelectedTheme
->Theme
!= NULL
&& pSelectedTheme
->ThemeActive
== FALSE
)
414 StyleName
= pSelectedTheme
->Color
->StyleName
;
415 SHSetValueW(HKEY_CURRENT_USER
,
420 (lstrlenW(StyleName
) + 1) * sizeof(WCHAR
));
425 CreateTheme(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
429 pTheme
= (PTHEME
) malloc(sizeof(THEME
));
430 if (pTheme
== NULL
) return NULL
;
432 pTheme
->DisplayName
= _wcsdup(pszDisplayName
);
433 if (pTheme
->DisplayName
== NULL
)
439 pTheme
->ColoursList
= NULL
;
440 pTheme
->NextTheme
= NULL
;
441 pTheme
->SizesList
= NULL
;
445 pTheme
->ThemeFileName
= NULL
;
449 pTheme
->ThemeFileName
= _wcsdup(pszName
);
450 if (pTheme
->ThemeFileName
== NULL
)
452 free(pTheme
->DisplayName
);
461 CreateStyle(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
465 pStyle
= (PTHEME_STYLE
) malloc(sizeof(THEME_STYLE
));
466 if (pStyle
== NULL
) return NULL
;
468 pStyle
->StyleName
= _wcsdup(pszName
);
469 if (pStyle
->StyleName
== NULL
)
475 pStyle
->DisplayName
= _wcsdup(pszDisplayName
);
476 if (pStyle
->DisplayName
== NULL
)
478 free(pStyle
->StyleName
);
483 pStyle
->ChildStyle
= NULL
;
484 pStyle
->NextStyle
= NULL
;
490 CleanupStyles(IN PTHEME_STYLE pStylesList
)
492 PTHEME_STYLE pStyle
, pStyleOld
;
494 pStyle
= pStylesList
;
497 if (pStyle
->ChildStyle
) CleanupStyles(pStyle
->ChildStyle
);
498 if (pStyle
->DisplayName
) free(pStyle
->DisplayName
);
499 if (pStyle
->StyleName
) free(pStyle
->StyleName
);
502 pStyle
= pStyle
->NextStyle
;
508 CleanupThemes(IN PTHEME pThemeList
)
510 PTHEME pTheme
, pThemeOld
;
515 CleanupStyles(pTheme
->ColoursList
);
516 if (pTheme
->SizesList
) CleanupStyles(pTheme
->SizesList
);
517 if (pTheme
->DisplayName
) free(pTheme
->DisplayName
);
518 if (pTheme
->ThemeFileName
) free(pTheme
->ThemeFileName
);
521 pTheme
= pTheme
->NextTheme
;
527 FindStyle(IN PTHEME_STYLE pStylesList
, IN PCWSTR StyleName
)
531 for (pStyle
= pStylesList
; pStyle
; pStyle
= pStyle
->NextStyle
)
533 if (_wcsicmp(pStyle
->StyleName
, StyleName
) == 0)
539 /* If we can't find the style requested, return the first one */
544 * LoadSchemeSizes: Returns a list of sizes from the registry key of a scheme
547 LoadSchemeSizes(IN HKEY hkScheme
)
549 HKEY hkSizes
, hkSize
;
552 WCHAR wstrSizeName
[5], wstrDisplayName
[50];
553 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
555 Result
= RegOpenKeyW(hkScheme
, L
"Sizes", &hkSizes
);
556 if (Result
!= ERROR_SUCCESS
) return NULL
;
559 while ((RegEnumKeyW(hkSizes
, iStyle
, wstrSizeName
, 5) == ERROR_SUCCESS
))
563 Result
= RegOpenKeyW(hkSizes
, wstrSizeName
, &hkSize
);
564 if (Result
!= ERROR_SUCCESS
) continue;
566 Result
= RegLoadMUIStringW(hkSize
,
569 sizeof(wstrDisplayName
),
573 if (Result
!= ERROR_SUCCESS
)
575 Result
= RegLoadMUIStringW(hkSize
,
578 sizeof(wstrDisplayName
),
584 if (Result
== ERROR_SUCCESS
)
585 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrDisplayName
);
587 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrSizeName
);
589 if (pCurrentStyle
!= NULL
)
591 pCurrentStyle
->NextStyle
= List
;
592 List
= pCurrentStyle
;
598 RegCloseKey(hkSizes
);
603 * LoadClassicColorSchemes: Returns a list of classic theme colours from the registry key of a scheme
606 LoadClassicColorSchemes(VOID
)
609 HKEY hkNewSchemes
, hkScheme
;
611 WCHAR wstrStyleName
[5], wstrDisplayName
[50];
612 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
614 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
615 if (Result
!= ERROR_SUCCESS
) return NULL
;
618 while ((RegEnumKeyW(hkNewSchemes
, iStyle
, wstrStyleName
, 5) == ERROR_SUCCESS
))
622 Result
= RegOpenKeyW(hkNewSchemes
, wstrStyleName
, &hkScheme
);
623 if (Result
!= ERROR_SUCCESS
) continue;
625 Result
= RegLoadMUIStringW(hkScheme
,
628 sizeof(wstrDisplayName
),
632 if (Result
!= ERROR_SUCCESS
)
634 Result
= RegLoadMUIStringW(hkScheme
,
637 sizeof(wstrDisplayName
),
643 if (Result
== ERROR_SUCCESS
)
644 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrDisplayName
);
646 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrStyleName
);
648 if (pCurrentStyle
!= NULL
)
650 pCurrentStyle
->NextStyle
= List
;
651 pCurrentStyle
->ChildStyle
= LoadSchemeSizes(hkScheme
);
652 if(pCurrentStyle
->ChildStyle
== NULL
)
653 CleanupStyles(pCurrentStyle
);
655 List
= pCurrentStyle
;
658 RegCloseKey(hkScheme
);
661 RegCloseKey(hkNewSchemes
);
665 typedef HRESULT (WINAPI
*ENUMTHEMESTYLE
) (LPCWSTR
, LPWSTR
, DWORD
, PTHEMENAMES
);
668 EnumThemeStyles(IN LPCWSTR pszThemeFileName
, IN ENUMTHEMESTYLE pfnEnumTheme
)
672 THEME_STYLE
*List
= NULL
, **ppPrevStyle
, *pCurrentStyle
;
676 while (SUCCEEDED(pfnEnumTheme (pszThemeFileName
, NULL
, index
++, &names
)))
678 pCurrentStyle
= CreateStyle(names
.szName
, names
.szDisplayName
);
679 if(pCurrentStyle
== NULL
) break;
681 *ppPrevStyle
= pCurrentStyle
;
682 ppPrevStyle
= &pCurrentStyle
->NextStyle
;
689 EnumThemeProc(IN LPVOID lpReserved
,
690 IN LPCWSTR pszThemeFileName
,
691 IN LPCWSTR pszThemeName
,
692 IN LPCWSTR pszToolTip
,
693 IN LPVOID lpReserved2
,
694 IN OUT LPVOID lpData
)
696 PTHEME
*List
, pTheme
;
698 List
= (PTHEME
*)lpData
;
700 pTheme
= CreateTheme(pszThemeFileName
, pszThemeName
);
701 if (pTheme
== NULL
) return FALSE
;
703 pTheme
->SizesList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeSizes
);
704 pTheme
->ColoursList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeColors
);
705 if(pTheme
->SizesList
== NULL
|| pTheme
->ColoursList
== NULL
)
707 CleanupThemes(pTheme
);
711 pTheme
->NextTheme
= *List
;
718 * LoadThemes: Returns a list that contains tha classic theme and
719 * the visual styles of the system
725 PTHEME pClassicTheme
;
726 WCHAR strClassicTheme
[40];
727 WCHAR szThemesPath
[MAX_PATH
], *pszClassicTheme
;
730 /* Insert the classic theme */
731 res
= LoadString(hApplet
, IDS_CLASSIC_THEME
, strClassicTheme
, 40);
732 pszClassicTheme
= (res
> 0 ? strClassicTheme
: L
"Classic Theme");
733 pClassicTheme
= CreateTheme(NULL
, pszClassicTheme
);
734 if (pClassicTheme
== NULL
) return NULL
;
735 pClassicTheme
->ColoursList
= LoadClassicColorSchemes();
737 /* Get path to themes folder */
738 ZeroMemory(szThemesPath
, sizeof(szThemesPath
));
739 hret
= SHGetFolderPathW (NULL
, CSIDL_RESOURCES
, NULL
, SHGFP_TYPE_DEFAULT
, szThemesPath
);
740 if (FAILED(hret
)) return pClassicTheme
;
741 lstrcatW (szThemesPath
, L
"\\Themes");
743 /* Enumerate themes */
744 hret
= EnumThemes( szThemesPath
, EnumThemeProc
, &pClassicTheme
->NextTheme
);
747 pClassicTheme
->NextTheme
= NULL
;
748 if (pClassicTheme
->ColoursList
== NULL
)
750 free(pClassicTheme
->DisplayName
);
756 return pClassicTheme
;
760 * GetActiveTheme: Gets the active theme and populates pSelectedTheme
761 * with entries from the list of loaded themes
764 GetActiveTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
766 WCHAR szThemeFileName
[MAX_PATH
];
767 WCHAR szColorBuff
[MAX_PATH
];
768 WCHAR szSizeBuff
[MAX_PATH
];
772 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
774 /* Retrieve the name of the current theme */
775 hret
= GetCurrentThemeName(szThemeFileName
,
781 if (FAILED(hret
)) return FALSE
;
783 for (pTheme
= pThemeList
; pTheme
; pTheme
= pTheme
->NextTheme
)
785 if (pTheme
->ThemeFileName
&&
786 _wcsicmp(pTheme
->ThemeFileName
, szThemeFileName
) == 0)
792 if (pTheme
== NULL
) return FALSE
;
794 pSelectedTheme
->ThemeActive
= TRUE
;
795 pSelectedTheme
->Theme
= pTheme
;
796 pSelectedTheme
->Color
= FindStyle(pTheme
->ColoursList
, szColorBuff
);
797 pSelectedTheme
->Size
= FindStyle(pTheme
->SizesList
, szSizeBuff
);
803 * GetActiveTheme: Gets the active classic theme and populates pSelectedTheme
804 * with entries from the list of loaded themes
807 GetActiveClassicTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
810 WCHAR szSelectedClassicScheme
[5], szSelectedClassicSize
[5];
812 DWORD dwType
, dwDisplayNameLength
;
813 PTHEME_STYLE pCurrentStyle
, pCurrentSize
;
815 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
818 szSelectedClassicScheme
[0] = 0;
819 szSelectedClassicSize
[0] = 0;
821 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
822 if (Result
!= ERROR_SUCCESS
) return FALSE
;
825 dwDisplayNameLength
= sizeof(szSelectedClassicScheme
);
826 Result
= RegQueryValueEx(hkNewSchemes
, L
"SelectedStyle", NULL
, &dwType
,
827 (LPBYTE
)&szSelectedClassicScheme
, &dwDisplayNameLength
);
828 if (Result
== ERROR_SUCCESS
)
831 dwDisplayNameLength
= sizeof(szSelectedClassicSize
);
832 Result
= SHGetValue(hkNewSchemes
, szSelectedClassicScheme
, L
"SelectedSize",
833 &dwType
, szSelectedClassicSize
, &dwDisplayNameLength
);
836 RegCloseKey(hkNewSchemes
);
838 pCurrentStyle
= FindStyle(pThemeList
->ColoursList
, szSelectedClassicScheme
);
839 pCurrentSize
= FindStyle(pCurrentStyle
->ChildStyle
, szSelectedClassicSize
);
841 pSelectedTheme
->Theme
= pThemeList
;
842 pSelectedTheme
->Color
= pCurrentStyle
;
843 pSelectedTheme
->Size
= pCurrentSize
;
849 ActivateTheme(IN PTHEME_SELECTION pSelectedTheme
)
851 HTHEMEFILE hThemeFile
= 0;
854 if (pSelectedTheme
->ThemeActive
)
856 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
857 pSelectedTheme
->Color
->StyleName
,
858 pSelectedTheme
->Size
->StyleName
,
862 if (!SUCCEEDED(hret
)) return FALSE
;
865 hret
= ApplyTheme(hThemeFile
, "", 0);
867 if (pSelectedTheme
->ThemeActive
)
869 CloseThemeFile(hThemeFile
);
872 return SUCCEEDED(hret
);
876 LoadSchemeFromTheme(OUT PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
)
878 HTHEMEFILE hThemeFile
= 0;
883 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
884 pSelectedTheme
->Color
->StyleName
,
885 pSelectedTheme
->Size
->StyleName
,
889 if (!SUCCEEDED(hret
)) return FALSE
;
891 hTheme
= OpenThemeDataFromFile(hThemeFile
, hCPLWindow
, L
"WINDOW", 0);
892 if (hTheme
== NULL
) return FALSE
;
895 for (i
= 0; i
< NUM_COLORS
; i
++)
897 scheme
->crColor
[i
] = GetThemeSysColor(hTheme
,i
);
901 /* I wonder why GetThemeSysInt doesn't work here */
902 scheme
->ncMetrics
.iBorderWidth
= GetThemeSysSize(hTheme
, SM_CXFRAME
);
903 scheme
->ncMetrics
.iScrollWidth
= GetThemeSysSize(hTheme
, SM_CXVSCROLL
);
904 scheme
->ncMetrics
.iScrollHeight
= GetThemeSysSize(hTheme
, SM_CYHSCROLL
);
905 scheme
->ncMetrics
.iCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSIZE
);
906 scheme
->ncMetrics
.iCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSIZE
);
907 scheme
->ncMetrics
.iSmCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSMSIZE
);
908 scheme
->ncMetrics
.iSmCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSMSIZE
);
909 scheme
->ncMetrics
.iMenuWidth
= GetThemeSysSize(hTheme
, SM_CXMENUSIZE
);
910 scheme
->ncMetrics
.iMenuHeight
= GetThemeSysSize(hTheme
, SM_CYMENUSIZE
);
913 GetThemeSysFont(hTheme
, TMT_CAPTIONFONT
, &scheme
->ncMetrics
.lfCaptionFont
);
914 GetThemeSysFont(hTheme
, TMT_SMALLCAPTIONFONT
, &scheme
->ncMetrics
.lfSmCaptionFont
);
915 GetThemeSysFont(hTheme
, TMT_MENUFONT
, &scheme
->ncMetrics
.lfMenuFont
);
916 GetThemeSysFont(hTheme
, TMT_STATUSFONT
, &scheme
->ncMetrics
.lfStatusFont
);
917 GetThemeSysFont(hTheme
, TMT_MSGBOXFONT
, &scheme
->ncMetrics
.lfMessageFont
);
918 GetThemeSysFont(hTheme
, TMT_ICONTITLEFONT
, &scheme
->icMetrics
.lfFont
);
920 CloseThemeData(hTheme
);
926 DrawThemePreview(IN HDC hdcMem
, IN PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
, IN PRECT prcWindow
)
931 hbrBack
= CreateSolidBrush(scheme
->crColor
[COLOR_DESKTOP
]);
933 FillRect(hdcMem
, prcWindow
, hbrBack
);
934 DeleteObject(hbrBack
);
936 InflateRect(prcWindow
, -10, -10);
938 hres
= DrawNCPreview(hdcMem
,
941 pSelectedTheme
->Theme
->ThemeFileName
,
942 pSelectedTheme
->Color
->StyleName
,
943 pSelectedTheme
->Size
->StyleName
,
947 return SUCCEEDED(hres
);