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
7 * PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
12 static const WCHAR g_CPColors
[] = L
"Control Panel\\Colors";
13 static const WCHAR g_CPANewSchemes
[] = L
"Control Panel\\Appearance\\New Schemes";
14 static const WCHAR g_CPMetrics
[] = L
"Control Panel\\Desktop\\WindowMetrics";
15 static const WCHAR g_SelectedStyle
[] = L
"SelectedStyle";
17 /******************************************************************************/
19 /* This is the list of names for the colors stored in the registry */
20 static const WCHAR
*g_RegColorNames
[NUM_COLORS
] = {
21 L
"Scrollbar", /* 00 = COLOR_SCROLLBAR */
22 L
"Background", /* 01 = COLOR_DESKTOP */
23 L
"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
24 L
"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
25 L
"Menu", /* 04 = COLOR_MENU */
26 L
"Window", /* 05 = COLOR_WINDOW */
27 L
"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
28 L
"MenuText", /* 07 = COLOR_MENUTEXT */
29 L
"WindowText", /* 08 = COLOR_WINDOWTEXT */
30 L
"TitleText", /* 09 = COLOR_CAPTIONTEXT */
31 L
"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
32 L
"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
33 L
"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
34 L
"Hilight", /* 13 = COLOR_HIGHLIGHT */
35 L
"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
36 L
"ButtonFace", /* 15 = COLOR_BTNFACE */
37 L
"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
38 L
"GrayText", /* 17 = COLOR_GRAYTEXT */
39 L
"ButtonText", /* 18 = COLOR_BTNTEXT */
40 L
"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
41 L
"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
42 L
"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
43 L
"ButtonLight", /* 22 = COLOR_3DLIGHT */
44 L
"InfoText", /* 23 = COLOR_INFOTEXT */
45 L
"InfoWindow", /* 24 = COLOR_INFOBK */
46 L
"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
47 L
"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
48 L
"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
49 L
"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
50 L
"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
51 L
"MenuBar", /* 30 = COLOR_MENUBAR */
54 /******************************************************************************/
57 SchemeSetMetric(IN COLOR_SCHEME
*scheme
, int id
, int value
)
61 case SIZE_BORDER_WIDTH
: scheme
->ncMetrics
.iBorderWidth
= value
; break;
62 case SIZE_SCROLL_WIDTH
: scheme
->ncMetrics
.iScrollWidth
= value
; break;
63 case SIZE_SCROLL_HEIGHT
: scheme
->ncMetrics
.iScrollHeight
= value
; break;
64 case SIZE_CAPTION_WIDTH
: scheme
->ncMetrics
.iCaptionWidth
= value
; break;
65 case SIZE_CAPTION_HEIGHT
: scheme
->ncMetrics
.iCaptionHeight
= value
; break;
66 case SIZE_SM_CAPTION_WIDTH
: scheme
->ncMetrics
.iSmCaptionWidth
= value
; break;
67 case SIZE_SM_CAPTION_HEIGHT
: scheme
->ncMetrics
.iSmCaptionHeight
= value
; break;
68 case SIZE_MENU_WIDTH
: scheme
->ncMetrics
.iMenuWidth
= value
; break;
69 case SIZE_MENU_HEIGHT
: scheme
->ncMetrics
.iMenuHeight
= value
; break;
70 case SIZE_ICON
: scheme
->iIconSize
= value
; break;
71 case SIZE_ICON_SPACE_X
: scheme
->icMetrics
.iHorzSpacing
= value
; break;
72 case SIZE_ICON_SPACE_Y
: scheme
->icMetrics
.iVertSpacing
= value
; break;
77 SchemeGetMetric(IN COLOR_SCHEME
*scheme
, int id
)
81 case SIZE_BORDER_WIDTH
: return scheme
->ncMetrics
.iBorderWidth
;
82 case SIZE_SCROLL_WIDTH
: return scheme
->ncMetrics
.iScrollWidth
;
83 case SIZE_SCROLL_HEIGHT
: return scheme
->ncMetrics
.iScrollHeight
;
84 case SIZE_CAPTION_WIDTH
: return scheme
->ncMetrics
.iCaptionWidth
;
85 case SIZE_CAPTION_HEIGHT
: return scheme
->ncMetrics
.iCaptionHeight
;
86 case SIZE_SM_CAPTION_WIDTH
: return scheme
->ncMetrics
.iSmCaptionWidth
;
87 case SIZE_SM_CAPTION_HEIGHT
: return scheme
->ncMetrics
.iSmCaptionHeight
;
88 case SIZE_MENU_WIDTH
: return scheme
->ncMetrics
.iMenuWidth
;
89 case SIZE_MENU_HEIGHT
: return scheme
->ncMetrics
.iMenuHeight
;
90 case SIZE_ICON
: return scheme
->iIconSize
;
91 case SIZE_ICON_SPACE_X
: return scheme
->icMetrics
.iHorzSpacing
;
92 case SIZE_ICON_SPACE_Y
: return scheme
->icMetrics
.iVertSpacing
;
98 SchemeGetFont(IN COLOR_SCHEME
*scheme
, int id
)
102 case FONT_CAPTION
: return &scheme
->ncMetrics
.lfCaptionFont
;
103 case FONT_SMCAPTION
: return &scheme
->ncMetrics
.lfSmCaptionFont
;
104 case FONT_MENU
: return &scheme
->ncMetrics
.lfMenuFont
;
105 case FONT_STATUS
: return &scheme
->ncMetrics
.lfStatusFont
;
106 case FONT_MESSAGE
: return &scheme
->ncMetrics
.lfMessageFont
;
107 case FONT_ICON
: return &scheme
->icMetrics
.lfFont
;
113 * LoadCurrentScheme: Populates the passed scheme based on the current system settings
116 LoadCurrentScheme(OUT COLOR_SCHEME
*scheme
)
123 for (i
= 0; i
< NUM_COLORS
; i
++)
125 scheme
->crColor
[i
] = (COLORREF
)GetSysColor(i
);
128 /* Load non client metrics */
129 scheme
->ncMetrics
.cbSize
= sizeof(NONCLIENTMETRICSW
);
130 ret
= SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
,
131 sizeof(NONCLIENTMETRICSW
),
134 if (!ret
) return FALSE
;
136 /* Load icon metrics */
137 scheme
->icMetrics
.cbSize
= sizeof(ICONMETRICSW
);
138 ret
= SystemParametersInfoW(SPI_GETICONMETRICS
,
139 sizeof(ICONMETRICSW
),
142 if (!ret
) return FALSE
;
144 /* Load flat menu style */
145 ret
= SystemParametersInfoW(SPI_GETFLATMENU
,
149 if (!ret
) return FALSE
;
152 /* "Use the following transition effect for menus and tooltips" */
153 ret
= SystemParametersInfoW(SPI_GETMENUANIMATION
,
155 &scheme
->Effects
.bMenuAnimation
,
157 if (!ret
) return FALSE
;
159 ret
= SystemParametersInfoW(SPI_GETMENUFADE
,
161 &scheme
->Effects
.bMenuFade
,
163 if (!ret
) return FALSE
;
165 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
166 * Just keep them in sync for now:
168 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
169 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
171 /* Show content of windows during dragging */
172 ret
= SystemParametersInfoW(SPI_GETDRAGFULLWINDOWS
,
174 &scheme
->Effects
.bDragFullWindows
,
176 if (!ret
) return FALSE
;
178 /* "Hide underlined letters for keyboard navigation until I press the Alt key" */
179 ret
= SystemParametersInfoW(SPI_GETKEYBOARDCUES
,
181 &scheme
->Effects
.bKeyboardCues
,
183 if (!ret
) return FALSE
;
185 /* Read the icon size from registry */
186 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPMetrics
, &hKey
);
187 if(Result
== ERROR_SUCCESS
)
189 scheme
->iIconSize
= SHRegGetIntW(hKey
, L
"Shell Icon Size", 32);
197 * LoadSchemeFromReg: Populates the passed scheme with values retireved from registry
200 LoadSchemeFromReg(OUT COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
203 WCHAR strValueName
[10], strSchemeKey
[MAX_PATH
];
204 HKEY hkScheme
= NULL
;
205 DWORD dwType
, dwLength
;
210 wsprintf(strSchemeKey
, L
"%s\\%s\\Sizes\\%s",
212 pSelectedTheme
->Color
->StyleName
,
213 pSelectedTheme
->Size
->StyleName
);
215 result
= RegOpenKeyW(HKEY_CURRENT_USER
, strSchemeKey
, &hkScheme
);
216 if (result
!= ERROR_SUCCESS
) return FALSE
;
218 scheme
->bFlatMenus
= SHRegGetIntW(hkScheme
, L
"FlatMenus", 0);
220 for (i
= 0; i
< NUM_COLORS
; i
++)
222 wsprintf(strValueName
, L
"Color #%d", i
);
223 dwLength
= sizeof(COLORREF
);
224 result
= RegQueryValueExW(hkScheme
,
228 (LPBYTE
)&scheme
->crColor
[i
],
230 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_DWORD
)
232 /* Failed to read registry value, initialize with current setting for now */
233 scheme
->crColor
[i
] = GetSysColor(i
);
237 for (i
= 0; i
< NUM_FONTS
; i
++)
239 PLOGFONTW lpfFont
= SchemeGetFont(scheme
, i
);
241 wsprintf(strValueName
, L
"Font #%d", i
);
242 dwLength
= sizeof(LOGFONT
);
243 result
= RegQueryValueExW(hkScheme
,
249 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_BINARY
||
250 dwLength
!= sizeof(LOGFONT
))
252 /* Failed to read registry value */
257 for (i
= 0; i
< NUM_SIZES
; i
++)
259 wsprintf(strValueName
, L
"Size #%d", i
);
260 dwLength
= sizeof(UINT64
);
261 result
= RegQueryValueExW(hkScheme
,
267 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_QWORD
||
268 dwLength
!= sizeof(UINT64
))
270 /* Failed to read registry value, initialize with current setting for now */
274 SchemeSetMetric(scheme
, i
, (int)iSize
);
278 RegCloseKey(hkScheme
);
284 ApplyScheme: Applies the selected scheme and stores its id in the registry if needed
287 ApplyScheme(IN COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
291 WCHAR clText
[16], *StyleName
;
292 INT ColorList
[NUM_COLORS
];
294 /* Apply system colors */
295 for (i
= 0; i
< NUM_COLORS
; i
++)
297 SetSysColors(NUM_COLORS
, ColorList
, scheme
->crColor
);
299 /* Save colors to registry */
300 Result
= RegCreateKeyW(HKEY_CURRENT_USER
, g_CPColors
, &hKey
);
301 if (Result
== ERROR_SUCCESS
)
303 for (i
= 0; i
< NUM_COLORS
; i
++)
307 GetRValue(scheme
->crColor
[i
]),
308 GetGValue(scheme
->crColor
[i
]),
309 GetBValue(scheme
->crColor
[i
]));
316 (lstrlen(clText
) + 1) * sizeof(WCHAR
));
321 /* Apply non client metrics */
322 SystemParametersInfoW(SPI_SETNONCLIENTMETRICS
,
323 sizeof(NONCLIENTMETRICS
),
325 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
327 /* Apply icon metrics */
328 SystemParametersInfoW(SPI_SETICONMETRICS
,
331 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
333 /* Effects, save only when needed: */
334 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
335 * Just keep them in sync for now.
337 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
338 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
339 SystemParametersInfoW(SPI_SETDRAGFULLWINDOWS
, scheme
->Effects
.bDragFullWindows
, (PVOID
)&scheme
->Effects
.bDragFullWindows
, SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
340 SystemParametersInfoW(SPI_SETKEYBOARDCUES
, 0, IntToPtr(scheme
->Effects
.bKeyboardCues
), SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
341 //SystemParametersInfoW(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)&scheme->Effects.bActiveWindowTracking, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
342 //SystemParametersInfoW(SPI_SETMENUANIMATION, 0, (PVOID)&scheme->Effects.bMenuAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
343 //SystemParametersInfoW(SPI_SETCOMBOBOXANIMATION, 0, (PVOID)&scheme->Effects.bComboBoxAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
344 //SystemParametersInfoW(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (PVOID)&scheme->Effects.bListBoxSmoothScrolling, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
345 //SystemParametersInfoW(SPI_SETGRADIENTCAPTIONS, 0, (PVOID)&scheme->Effects.bGradientCaptions, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
346 //SystemParametersInfoW(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)&scheme->Effects.bActiveWndTrkZorder, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
347 //SystemParametersInfoW(SPI_SETHOTTRACKING, 0, (PVOID)&scheme->Effects.bHotTracking, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
348 SystemParametersInfoW(SPI_SETMENUFADE
, 0, (PVOID
)&scheme
->Effects
.bMenuFade
, SPIF_UPDATEINIFILE
|SPIF_SENDCHANGE
);
349 //SystemParametersInfoW(SPI_SETSELECTIONFADE, 0, (PVOID)&scheme->Effects.bSelectionFade, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
350 SystemParametersInfoW(SPI_SETTOOLTIPANIMATION
, 0, (PVOID
)&scheme
->Effects
.bTooltipAnimation
, SPIF_UPDATEINIFILE
|SPIF_SENDCHANGE
);
351 SystemParametersInfoW(SPI_SETTOOLTIPFADE
, 0, (PVOID
)&scheme
->Effects
.bTooltipFade
, SPIF_UPDATEINIFILE
|SPIF_SENDCHANGE
);
352 //SystemParametersInfoW(SPI_SETCURSORSHADOW, 0, (PVOID)&scheme->Effects.bCursorShadow, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
353 //SystemParametersInfoW(SPI_SETUIEFFECTS, 0, (PVOID)&scheme->Effects.bUiEffects, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
355 /* Save SchemeId in the registry */
356 if (pSelectedTheme
->Theme
!= NULL
&& pSelectedTheme
->ThemeActive
== FALSE
)
358 StyleName
= pSelectedTheme
->Color
->StyleName
;
359 SHSetValueW(HKEY_CURRENT_USER
,
364 (lstrlenW(StyleName
) + 1) * sizeof(WCHAR
));
369 CreateTheme(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
373 pTheme
= (PTHEME
) malloc(sizeof(THEME
));
374 if (pTheme
== NULL
) return NULL
;
376 pTheme
->DisplayName
= _wcsdup(pszDisplayName
);
377 if (pTheme
->DisplayName
== NULL
)
383 pTheme
->ColoursList
= NULL
;
384 pTheme
->NextTheme
= NULL
;
385 pTheme
->SizesList
= NULL
;
389 pTheme
->ThemeFileName
= NULL
;
393 pTheme
->ThemeFileName
= _wcsdup(pszName
);
394 if (pTheme
->ThemeFileName
== NULL
)
396 free(pTheme
->DisplayName
);
405 CreateStyle(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
409 pStyle
= (PTHEME_STYLE
) malloc(sizeof(THEME_STYLE
));
410 if (pStyle
== NULL
) return NULL
;
412 pStyle
->StyleName
= _wcsdup(pszName
);
413 if (pStyle
->StyleName
== NULL
)
419 pStyle
->DisplayName
= _wcsdup(pszDisplayName
);
420 if (pStyle
->DisplayName
== NULL
)
422 free(pStyle
->StyleName
);
427 pStyle
->ChildStyle
= NULL
;
428 pStyle
->NextStyle
= NULL
;
434 CleanupStyles(IN PTHEME_STYLE pStylesList
)
436 PTHEME_STYLE pStyle
, pStyleOld
;
438 pStyle
= pStylesList
;
441 if (pStyle
->ChildStyle
) CleanupStyles(pStyle
->ChildStyle
);
442 if (pStyle
->DisplayName
) free(pStyle
->DisplayName
);
443 if (pStyle
->StyleName
) free(pStyle
->StyleName
);
446 pStyle
= pStyle
->NextStyle
;
452 CleanupThemes(IN PTHEME pThemeList
)
454 PTHEME pTheme
, pThemeOld
;
459 CleanupStyles(pTheme
->ColoursList
);
460 if (pTheme
->SizesList
) CleanupStyles(pTheme
->SizesList
);
461 if (pTheme
->DisplayName
) free(pTheme
->DisplayName
);
462 if (pTheme
->ThemeFileName
) free(pTheme
->ThemeFileName
);
465 pTheme
= pTheme
->NextTheme
;
471 FindStyle(IN PTHEME_STYLE pStylesList
, IN PCWSTR StyleName
)
475 for (pStyle
= pStylesList
; pStyle
; pStyle
= pStyle
->NextStyle
)
477 if (_wcsicmp(pStyle
->StyleName
, StyleName
) == 0)
483 /* If we can't find the style requested, return the first one */
488 * LoadSchemeSizes: Returns a list of sizes from the registry key of a scheme
491 LoadSchemeSizes(IN HKEY hkScheme
)
493 HKEY hkSizes
, hkSize
;
496 WCHAR wstrSizeName
[5], wstrDisplayName
[50];
497 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
499 Result
= RegOpenKeyW(hkScheme
, L
"Sizes", &hkSizes
);
500 if (Result
!= ERROR_SUCCESS
) return NULL
;
503 while ((RegEnumKeyW(hkSizes
, iStyle
, wstrSizeName
, 5) == ERROR_SUCCESS
))
507 Result
= RegOpenKeyW(hkSizes
, wstrSizeName
, &hkSize
);
508 if (Result
!= ERROR_SUCCESS
) continue;
510 Result
= RegLoadMUIStringW(hkSize
,
513 sizeof(wstrDisplayName
),
517 if (Result
!= ERROR_SUCCESS
)
519 Result
= RegLoadMUIStringW(hkSize
,
522 sizeof(wstrDisplayName
),
528 if (Result
== ERROR_SUCCESS
)
529 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrDisplayName
);
531 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrSizeName
);
533 if (pCurrentStyle
!= NULL
)
535 pCurrentStyle
->NextStyle
= List
;
536 List
= pCurrentStyle
;
542 RegCloseKey(hkSizes
);
547 LoadClassicColorSchemes: Returns a list of classic theme colours from the registry key of a scheme
550 LoadClassicColorSchemes(VOID
)
553 HKEY hkNewSchemes
, hkScheme
;
555 WCHAR wstrStyleName
[5], wstrDisplayName
[50];
556 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
558 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
559 if (Result
!= ERROR_SUCCESS
) return NULL
;
562 while ((RegEnumKeyW(hkNewSchemes
, iStyle
, wstrStyleName
, 5) == ERROR_SUCCESS
))
566 Result
= RegOpenKeyW(hkNewSchemes
, wstrStyleName
, &hkScheme
);
567 if (Result
!= ERROR_SUCCESS
) continue;
569 Result
= RegLoadMUIStringW(hkScheme
,
572 sizeof(wstrDisplayName
),
577 if (Result
== ERROR_SUCCESS
)
578 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrDisplayName
);
580 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrStyleName
);
582 if (pCurrentStyle
!= NULL
)
584 pCurrentStyle
->NextStyle
= List
;
585 pCurrentStyle
->ChildStyle
= LoadSchemeSizes(hkScheme
);
586 if(pCurrentStyle
->ChildStyle
== NULL
)
587 CleanupStyles(pCurrentStyle
);
589 List
= pCurrentStyle
;
592 RegCloseKey(hkScheme
);
595 RegCloseKey(hkNewSchemes
);
599 typedef HRESULT (WINAPI
*ENUMTHEMESTYLE
) (LPCWSTR
, LPWSTR
, DWORD
, PTHEMENAMES
);
602 EnumThemeStyles(IN LPCWSTR pszThemeFileName
, IN ENUMTHEMESTYLE pfnEnumTheme
)
606 THEME_STYLE
*List
= NULL
, **ppPrevStyle
, *pCurrentStyle
;
610 while (SUCCEEDED(pfnEnumTheme (pszThemeFileName
, NULL
, index
++, &names
)))
612 pCurrentStyle
= CreateStyle(names
.szName
, names
.szDisplayName
);
613 if(pCurrentStyle
== NULL
) break;
615 *ppPrevStyle
= pCurrentStyle
;
616 ppPrevStyle
= &pCurrentStyle
->NextStyle
;
623 EnumThemeProc(IN LPVOID lpReserved
,
624 IN LPCWSTR pszThemeFileName
,
625 IN LPCWSTR pszThemeName
,
626 IN LPCWSTR pszToolTip
,
627 IN LPVOID lpReserved2
,
628 IN OUT LPVOID lpData
)
630 PTHEME
*List
, pTheme
;
632 List
= (PTHEME
*)lpData
;
634 pTheme
= CreateTheme(pszThemeFileName
, pszThemeName
);
635 if (pTheme
== NULL
) return FALSE
;
637 pTheme
->SizesList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeSizes
);
638 pTheme
->ColoursList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeColors
);
639 if(pTheme
->SizesList
== NULL
|| pTheme
->ColoursList
== NULL
)
641 CleanupThemes(pTheme
);
645 pTheme
->NextTheme
= *List
;
652 LoadThemes: Returns a list that contains tha classic theme and
653 the visual styles of the system
659 PTHEME pClassicTheme
;
660 WCHAR strClassicTheme
[40];
661 WCHAR szThemesPath
[MAX_PATH
], *pszClassicTheme
;
664 /* Insert the classic theme */
665 res
= LoadString(hApplet
, IDS_CLASSIC_THEME
, strClassicTheme
, 40);
666 pszClassicTheme
= (res
> 0 ? strClassicTheme
: L
"Classic Theme");
667 pClassicTheme
= CreateTheme(NULL
, pszClassicTheme
);
668 if (pClassicTheme
== NULL
) return NULL
;
669 pClassicTheme
->ColoursList
= LoadClassicColorSchemes();
671 /* Get path to themes folder */
672 ZeroMemory(szThemesPath
, sizeof(szThemesPath
));
673 hret
= SHGetFolderPathW (NULL
, CSIDL_RESOURCES
, NULL
, SHGFP_TYPE_DEFAULT
, szThemesPath
);
674 if (FAILED(hret
)) return pClassicTheme
;
675 lstrcatW (szThemesPath
, L
"\\Themes");
677 /* Enumerate themes */
678 hret
= EnumThemes( szThemesPath
, EnumThemeProc
, &pClassicTheme
->NextTheme
);
681 pClassicTheme
->NextTheme
= NULL
;
682 if (pClassicTheme
->ColoursList
== NULL
)
684 free(pClassicTheme
->DisplayName
);
690 return pClassicTheme
;
694 * GetActiveTheme: Gets the active theme and populates pSelectedTheme
695 * with entries from the list of loaded themes
698 GetActiveTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
700 WCHAR szThemeFileName
[MAX_PATH
];
701 WCHAR szColorBuff
[MAX_PATH
];
702 WCHAR szSizeBuff
[MAX_PATH
];
706 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
708 /* Retrieve the name of the current theme */
709 hret
= GetCurrentThemeName(szThemeFileName
,
715 if (FAILED(hret
)) return FALSE
;
717 for (pTheme
= pThemeList
; pTheme
; pTheme
= pTheme
->NextTheme
)
719 if(pTheme
->ThemeFileName
&&
720 _wcsicmp(pTheme
->ThemeFileName
, szThemeFileName
) == 0)
726 if (pTheme
== NULL
) return FALSE
;
728 pSelectedTheme
->ThemeActive
= TRUE
;
729 pSelectedTheme
->Theme
= pTheme
;
730 pSelectedTheme
->Color
= FindStyle(pTheme
->ColoursList
, szColorBuff
);
731 pSelectedTheme
->Size
= FindStyle(pTheme
->SizesList
, szSizeBuff
);
737 GetActiveTheme: Gets the active classic theme and populates pSelectedTheme
738 with entries from the list of loaded themes
741 GetActiveClassicTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
744 WCHAR szSelectedClassicScheme
[5], szSelectedClassicSize
[5];
746 DWORD dwType
, dwDisplayNameLength
;
747 PTHEME_STYLE pCurrentStyle
, pCurrentSize
;
749 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
752 szSelectedClassicScheme
[0] = 0;
753 szSelectedClassicSize
[0] = 0;
755 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
756 if (Result
!= ERROR_SUCCESS
) return FALSE
;
759 dwDisplayNameLength
= sizeof(szSelectedClassicScheme
);
760 Result
= RegQueryValueEx(hkNewSchemes
, L
"SelectedStyle", NULL
, &dwType
,
761 (LPBYTE
)&szSelectedClassicScheme
, &dwDisplayNameLength
);
762 if (Result
== ERROR_SUCCESS
)
765 dwDisplayNameLength
= sizeof(szSelectedClassicSize
);
766 Result
= SHGetValue(hkNewSchemes
, szSelectedClassicScheme
, L
"SelectedSize",
767 &dwType
, szSelectedClassicSize
, &dwDisplayNameLength
);
770 RegCloseKey(hkNewSchemes
);
772 pCurrentStyle
= FindStyle(pThemeList
->ColoursList
, szSelectedClassicScheme
);
773 pCurrentSize
= FindStyle(pCurrentStyle
->ChildStyle
, szSelectedClassicSize
);
775 pSelectedTheme
->Theme
= pThemeList
;
776 pSelectedTheme
->Color
= pCurrentStyle
;
777 pSelectedTheme
->Size
= pCurrentSize
;
783 ActivateTheme(IN PTHEME_SELECTION pSelectedTheme
)
785 HTHEMEFILE hThemeFile
= 0;
788 if (pSelectedTheme
->ThemeActive
)
790 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
791 pSelectedTheme
->Color
->StyleName
,
792 pSelectedTheme
->Size
->StyleName
,
796 if (!SUCCEEDED(hret
)) return FALSE
;
799 hret
= ApplyTheme(hThemeFile
, "", 0);
801 if (pSelectedTheme
->ThemeActive
)
803 CloseThemeFile(hThemeFile
);
806 return SUCCEEDED(hret
);
810 LoadSchemeFromTheme(OUT PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
)
812 HTHEMEFILE hThemeFile
= 0;
817 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
818 pSelectedTheme
->Color
->StyleName
,
819 pSelectedTheme
->Size
->StyleName
,
823 if (!SUCCEEDED(hret
)) return FALSE
;
825 hTheme
= OpenThemeDataFromFile(hThemeFile
, hCPLWindow
, L
"WINDOW", 0);
826 if (hTheme
== NULL
) return FALSE
;
829 for (i
= 0; i
< NUM_COLORS
; i
++)
831 scheme
->crColor
[i
] = GetThemeSysColor(hTheme
,i
);
835 /* I wonder why GetThemeSysInt doesn't work here */
836 scheme
->ncMetrics
.iBorderWidth
= GetThemeSysSize(hTheme
, SM_CXFRAME
);
837 scheme
->ncMetrics
.iScrollWidth
= GetThemeSysSize(hTheme
, SM_CXVSCROLL
);
838 scheme
->ncMetrics
.iScrollHeight
= GetThemeSysSize(hTheme
, SM_CYHSCROLL
);
839 scheme
->ncMetrics
.iCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSIZE
);
840 scheme
->ncMetrics
.iCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSIZE
);
841 scheme
->ncMetrics
.iSmCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSMSIZE
);
842 scheme
->ncMetrics
.iSmCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSMSIZE
);
843 scheme
->ncMetrics
.iMenuWidth
= GetThemeSysSize(hTheme
, SM_CXMENUSIZE
);
844 scheme
->ncMetrics
.iMenuHeight
= GetThemeSysSize(hTheme
, SM_CYMENUSIZE
);
847 GetThemeSysFont(hTheme
, TMT_CAPTIONFONT
, &scheme
->ncMetrics
.lfCaptionFont
);
848 GetThemeSysFont(hTheme
, TMT_SMALLCAPTIONFONT
, &scheme
->ncMetrics
.lfSmCaptionFont
);
849 GetThemeSysFont(hTheme
, TMT_MENUFONT
, &scheme
->ncMetrics
.lfMenuFont
);
850 GetThemeSysFont(hTheme
, TMT_STATUSFONT
, &scheme
->ncMetrics
.lfStatusFont
);
851 GetThemeSysFont(hTheme
, TMT_MSGBOXFONT
, &scheme
->ncMetrics
.lfMessageFont
);
852 GetThemeSysFont(hTheme
, TMT_ICONTITLEFONT
, &scheme
->icMetrics
.lfFont
);
854 CloseThemeData(hTheme
);
860 DrawThemePreview(IN HDC hdcMem
, IN PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
, IN PRECT prcWindow
)
865 hbrBack
= CreateSolidBrush(scheme
->crColor
[COLOR_DESKTOP
]);
867 FillRect(hdcMem
, prcWindow
, hbrBack
);
868 DeleteObject(hbrBack
);
870 InflateRect(prcWindow
, -10, -10);
872 hres
= DrawNCPreview(hdcMem
,
875 pSelectedTheme
->Theme
->ThemeFileName
,
876 pSelectedTheme
->Color
->StyleName
,
877 pSelectedTheme
->Size
->StyleName
,
881 return SUCCEEDED(hres
);