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
),
576 if (Result
!= ERROR_SUCCESS
)
578 Result
= RegLoadMUIStringW(hkScheme
,
581 sizeof(wstrDisplayName
),
587 if (Result
== ERROR_SUCCESS
)
588 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrDisplayName
);
590 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrStyleName
);
592 if (pCurrentStyle
!= NULL
)
594 pCurrentStyle
->NextStyle
= List
;
595 pCurrentStyle
->ChildStyle
= LoadSchemeSizes(hkScheme
);
596 if(pCurrentStyle
->ChildStyle
== NULL
)
597 CleanupStyles(pCurrentStyle
);
599 List
= pCurrentStyle
;
602 RegCloseKey(hkScheme
);
605 RegCloseKey(hkNewSchemes
);
609 typedef HRESULT (WINAPI
*ENUMTHEMESTYLE
) (LPCWSTR
, LPWSTR
, DWORD
, PTHEMENAMES
);
612 EnumThemeStyles(IN LPCWSTR pszThemeFileName
, IN ENUMTHEMESTYLE pfnEnumTheme
)
616 THEME_STYLE
*List
= NULL
, **ppPrevStyle
, *pCurrentStyle
;
620 while (SUCCEEDED(pfnEnumTheme (pszThemeFileName
, NULL
, index
++, &names
)))
622 pCurrentStyle
= CreateStyle(names
.szName
, names
.szDisplayName
);
623 if(pCurrentStyle
== NULL
) break;
625 *ppPrevStyle
= pCurrentStyle
;
626 ppPrevStyle
= &pCurrentStyle
->NextStyle
;
633 EnumThemeProc(IN LPVOID lpReserved
,
634 IN LPCWSTR pszThemeFileName
,
635 IN LPCWSTR pszThemeName
,
636 IN LPCWSTR pszToolTip
,
637 IN LPVOID lpReserved2
,
638 IN OUT LPVOID lpData
)
640 PTHEME
*List
, pTheme
;
642 List
= (PTHEME
*)lpData
;
644 pTheme
= CreateTheme(pszThemeFileName
, pszThemeName
);
645 if (pTheme
== NULL
) return FALSE
;
647 pTheme
->SizesList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeSizes
);
648 pTheme
->ColoursList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeColors
);
649 if(pTheme
->SizesList
== NULL
|| pTheme
->ColoursList
== NULL
)
651 CleanupThemes(pTheme
);
655 pTheme
->NextTheme
= *List
;
662 LoadThemes: Returns a list that contains tha classic theme and
663 the visual styles of the system
669 PTHEME pClassicTheme
;
670 WCHAR strClassicTheme
[40];
671 WCHAR szThemesPath
[MAX_PATH
], *pszClassicTheme
;
674 /* Insert the classic theme */
675 res
= LoadString(hApplet
, IDS_CLASSIC_THEME
, strClassicTheme
, 40);
676 pszClassicTheme
= (res
> 0 ? strClassicTheme
: L
"Classic Theme");
677 pClassicTheme
= CreateTheme(NULL
, pszClassicTheme
);
678 if (pClassicTheme
== NULL
) return NULL
;
679 pClassicTheme
->ColoursList
= LoadClassicColorSchemes();
681 /* Get path to themes folder */
682 ZeroMemory(szThemesPath
, sizeof(szThemesPath
));
683 hret
= SHGetFolderPathW (NULL
, CSIDL_RESOURCES
, NULL
, SHGFP_TYPE_DEFAULT
, szThemesPath
);
684 if (FAILED(hret
)) return pClassicTheme
;
685 lstrcatW (szThemesPath
, L
"\\Themes");
687 /* Enumerate themes */
688 hret
= EnumThemes( szThemesPath
, EnumThemeProc
, &pClassicTheme
->NextTheme
);
691 pClassicTheme
->NextTheme
= NULL
;
692 if (pClassicTheme
->ColoursList
== NULL
)
694 free(pClassicTheme
->DisplayName
);
700 return pClassicTheme
;
704 * GetActiveTheme: Gets the active theme and populates pSelectedTheme
705 * with entries from the list of loaded themes
708 GetActiveTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
710 WCHAR szThemeFileName
[MAX_PATH
];
711 WCHAR szColorBuff
[MAX_PATH
];
712 WCHAR szSizeBuff
[MAX_PATH
];
716 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
718 /* Retrieve the name of the current theme */
719 hret
= GetCurrentThemeName(szThemeFileName
,
725 if (FAILED(hret
)) return FALSE
;
727 for (pTheme
= pThemeList
; pTheme
; pTheme
= pTheme
->NextTheme
)
729 if(pTheme
->ThemeFileName
&&
730 _wcsicmp(pTheme
->ThemeFileName
, szThemeFileName
) == 0)
736 if (pTheme
== NULL
) return FALSE
;
738 pSelectedTheme
->ThemeActive
= TRUE
;
739 pSelectedTheme
->Theme
= pTheme
;
740 pSelectedTheme
->Color
= FindStyle(pTheme
->ColoursList
, szColorBuff
);
741 pSelectedTheme
->Size
= FindStyle(pTheme
->SizesList
, szSizeBuff
);
747 GetActiveTheme: Gets the active classic theme and populates pSelectedTheme
748 with entries from the list of loaded themes
751 GetActiveClassicTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
754 WCHAR szSelectedClassicScheme
[5], szSelectedClassicSize
[5];
756 DWORD dwType
, dwDisplayNameLength
;
757 PTHEME_STYLE pCurrentStyle
, pCurrentSize
;
759 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
762 szSelectedClassicScheme
[0] = 0;
763 szSelectedClassicSize
[0] = 0;
765 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
766 if (Result
!= ERROR_SUCCESS
) return FALSE
;
769 dwDisplayNameLength
= sizeof(szSelectedClassicScheme
);
770 Result
= RegQueryValueEx(hkNewSchemes
, L
"SelectedStyle", NULL
, &dwType
,
771 (LPBYTE
)&szSelectedClassicScheme
, &dwDisplayNameLength
);
772 if (Result
== ERROR_SUCCESS
)
775 dwDisplayNameLength
= sizeof(szSelectedClassicSize
);
776 Result
= SHGetValue(hkNewSchemes
, szSelectedClassicScheme
, L
"SelectedSize",
777 &dwType
, szSelectedClassicSize
, &dwDisplayNameLength
);
780 RegCloseKey(hkNewSchemes
);
782 pCurrentStyle
= FindStyle(pThemeList
->ColoursList
, szSelectedClassicScheme
);
783 pCurrentSize
= FindStyle(pCurrentStyle
->ChildStyle
, szSelectedClassicSize
);
785 pSelectedTheme
->Theme
= pThemeList
;
786 pSelectedTheme
->Color
= pCurrentStyle
;
787 pSelectedTheme
->Size
= pCurrentSize
;
793 ActivateTheme(IN PTHEME_SELECTION pSelectedTheme
)
795 HTHEMEFILE hThemeFile
= 0;
798 if (pSelectedTheme
->ThemeActive
)
800 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
801 pSelectedTheme
->Color
->StyleName
,
802 pSelectedTheme
->Size
->StyleName
,
806 if (!SUCCEEDED(hret
)) return FALSE
;
809 hret
= ApplyTheme(hThemeFile
, "", 0);
811 if (pSelectedTheme
->ThemeActive
)
813 CloseThemeFile(hThemeFile
);
816 return SUCCEEDED(hret
);
820 LoadSchemeFromTheme(OUT PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
)
822 HTHEMEFILE hThemeFile
= 0;
827 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
828 pSelectedTheme
->Color
->StyleName
,
829 pSelectedTheme
->Size
->StyleName
,
833 if (!SUCCEEDED(hret
)) return FALSE
;
835 hTheme
= OpenThemeDataFromFile(hThemeFile
, hCPLWindow
, L
"WINDOW", 0);
836 if (hTheme
== NULL
) return FALSE
;
839 for (i
= 0; i
< NUM_COLORS
; i
++)
841 scheme
->crColor
[i
] = GetThemeSysColor(hTheme
,i
);
845 /* I wonder why GetThemeSysInt doesn't work here */
846 scheme
->ncMetrics
.iBorderWidth
= GetThemeSysSize(hTheme
, SM_CXFRAME
);
847 scheme
->ncMetrics
.iScrollWidth
= GetThemeSysSize(hTheme
, SM_CXVSCROLL
);
848 scheme
->ncMetrics
.iScrollHeight
= GetThemeSysSize(hTheme
, SM_CYHSCROLL
);
849 scheme
->ncMetrics
.iCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSIZE
);
850 scheme
->ncMetrics
.iCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSIZE
);
851 scheme
->ncMetrics
.iSmCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSMSIZE
);
852 scheme
->ncMetrics
.iSmCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSMSIZE
);
853 scheme
->ncMetrics
.iMenuWidth
= GetThemeSysSize(hTheme
, SM_CXMENUSIZE
);
854 scheme
->ncMetrics
.iMenuHeight
= GetThemeSysSize(hTheme
, SM_CYMENUSIZE
);
857 GetThemeSysFont(hTheme
, TMT_CAPTIONFONT
, &scheme
->ncMetrics
.lfCaptionFont
);
858 GetThemeSysFont(hTheme
, TMT_SMALLCAPTIONFONT
, &scheme
->ncMetrics
.lfSmCaptionFont
);
859 GetThemeSysFont(hTheme
, TMT_MENUFONT
, &scheme
->ncMetrics
.lfMenuFont
);
860 GetThemeSysFont(hTheme
, TMT_STATUSFONT
, &scheme
->ncMetrics
.lfStatusFont
);
861 GetThemeSysFont(hTheme
, TMT_MSGBOXFONT
, &scheme
->ncMetrics
.lfMessageFont
);
862 GetThemeSysFont(hTheme
, TMT_ICONTITLEFONT
, &scheme
->icMetrics
.lfFont
);
864 CloseThemeData(hTheme
);
870 DrawThemePreview(IN HDC hdcMem
, IN PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
, IN PRECT prcWindow
)
875 hbrBack
= CreateSolidBrush(scheme
->crColor
[COLOR_DESKTOP
]);
877 FillRect(hdcMem
, prcWindow
, hbrBack
);
878 DeleteObject(hbrBack
);
880 InflateRect(prcWindow
, -10, -10);
882 hres
= DrawNCPreview(hdcMem
,
885 pSelectedTheme
->Theme
->ThemeFileName
,
886 pSelectedTheme
->Color
->StyleName
,
887 pSelectedTheme
->Size
->StyleName
,
891 return SUCCEEDED(hres
);