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>
17 static const WCHAR g_CPColors
[] = L
"Control Panel\\Colors";
18 static const WCHAR g_CPANewSchemes
[] = L
"Control Panel\\Appearance\\New Schemes";
19 static const WCHAR g_CPMetrics
[] = L
"Control Panel\\Desktop\\WindowMetrics";
20 static const WCHAR g_SelectedStyle
[] = L
"SelectedStyle";
22 /******************************************************************************/
24 /* This is the list of names for the colors stored in the registry */
25 static const WCHAR
*g_RegColorNames
[NUM_COLORS
] = {
26 L
"Scrollbar", /* 00 = COLOR_SCROLLBAR */
27 L
"Background", /* 01 = COLOR_DESKTOP */
28 L
"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
29 L
"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
30 L
"Menu", /* 04 = COLOR_MENU */
31 L
"Window", /* 05 = COLOR_WINDOW */
32 L
"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
33 L
"MenuText", /* 07 = COLOR_MENUTEXT */
34 L
"WindowText", /* 08 = COLOR_WINDOWTEXT */
35 L
"TitleText", /* 09 = COLOR_CAPTIONTEXT */
36 L
"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
37 L
"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
38 L
"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
39 L
"Hilight", /* 13 = COLOR_HIGHLIGHT */
40 L
"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
41 L
"ButtonFace", /* 15 = COLOR_BTNFACE */
42 L
"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
43 L
"GrayText", /* 17 = COLOR_GRAYTEXT */
44 L
"ButtonText", /* 18 = COLOR_BTNTEXT */
45 L
"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
46 L
"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
47 L
"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
48 L
"ButtonLight", /* 22 = COLOR_3DLIGHT */
49 L
"InfoText", /* 23 = COLOR_INFOTEXT */
50 L
"InfoWindow", /* 24 = COLOR_INFOBK */
51 L
"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
52 L
"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
53 L
"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
54 L
"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
55 L
"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
56 L
"MenuBar", /* 30 = COLOR_MENUBAR */
59 /******************************************************************************/
62 SchemeSetMetric(IN COLOR_SCHEME
*scheme
, int id
, int value
)
66 case SIZE_BORDER_WIDTH
: scheme
->ncMetrics
.iBorderWidth
= value
; break;
67 case SIZE_SCROLL_WIDTH
: scheme
->ncMetrics
.iScrollWidth
= value
; break;
68 case SIZE_SCROLL_HEIGHT
: scheme
->ncMetrics
.iScrollHeight
= value
; break;
69 case SIZE_CAPTION_WIDTH
: scheme
->ncMetrics
.iCaptionWidth
= value
; break;
70 case SIZE_CAPTION_HEIGHT
: scheme
->ncMetrics
.iCaptionHeight
= value
; break;
71 case SIZE_SM_CAPTION_WIDTH
: scheme
->ncMetrics
.iSmCaptionWidth
= value
; break;
72 case SIZE_SM_CAPTION_HEIGHT
: scheme
->ncMetrics
.iSmCaptionHeight
= value
; break;
73 case SIZE_MENU_WIDTH
: scheme
->ncMetrics
.iMenuWidth
= value
; break;
74 case SIZE_MENU_HEIGHT
: scheme
->ncMetrics
.iMenuHeight
= value
; break;
75 case SIZE_ICON
: scheme
->iIconSize
= value
; break;
76 case SIZE_ICON_SPACE_X
: scheme
->icMetrics
.iHorzSpacing
= value
; break;
77 case SIZE_ICON_SPACE_Y
: scheme
->icMetrics
.iVertSpacing
= value
; break;
82 SchemeGetMetric(IN COLOR_SCHEME
*scheme
, int id
)
86 case SIZE_BORDER_WIDTH
: return scheme
->ncMetrics
.iBorderWidth
;
87 case SIZE_SCROLL_WIDTH
: return scheme
->ncMetrics
.iScrollWidth
;
88 case SIZE_SCROLL_HEIGHT
: return scheme
->ncMetrics
.iScrollHeight
;
89 case SIZE_CAPTION_WIDTH
: return scheme
->ncMetrics
.iCaptionWidth
;
90 case SIZE_CAPTION_HEIGHT
: return scheme
->ncMetrics
.iCaptionHeight
;
91 case SIZE_SM_CAPTION_WIDTH
: return scheme
->ncMetrics
.iSmCaptionWidth
;
92 case SIZE_SM_CAPTION_HEIGHT
: return scheme
->ncMetrics
.iSmCaptionHeight
;
93 case SIZE_MENU_WIDTH
: return scheme
->ncMetrics
.iMenuWidth
;
94 case SIZE_MENU_HEIGHT
: return scheme
->ncMetrics
.iMenuHeight
;
95 case SIZE_ICON
: return scheme
->iIconSize
;
96 case SIZE_ICON_SPACE_X
: return scheme
->icMetrics
.iHorzSpacing
;
97 case SIZE_ICON_SPACE_Y
: return scheme
->icMetrics
.iVertSpacing
;
103 SchemeGetFont(IN COLOR_SCHEME
*scheme
, int id
)
107 case FONT_CAPTION
: return &scheme
->ncMetrics
.lfCaptionFont
;
108 case FONT_SMCAPTION
: return &scheme
->ncMetrics
.lfSmCaptionFont
;
109 case FONT_MENU
: return &scheme
->ncMetrics
.lfMenuFont
;
110 case FONT_STATUS
: return &scheme
->ncMetrics
.lfStatusFont
;
111 case FONT_MESSAGE
: return &scheme
->ncMetrics
.lfMessageFont
;
112 case FONT_ICON
: return &scheme
->icMetrics
.lfFont
;
118 * LoadCurrentScheme: Populates the passed scheme based on the current system settings
121 LoadCurrentScheme(OUT COLOR_SCHEME
*scheme
)
128 for (i
= 0; i
< NUM_COLORS
; i
++)
130 scheme
->crColor
[i
] = (COLORREF
)GetSysColor(i
);
133 /* Load non client metrics */
134 scheme
->ncMetrics
.cbSize
= sizeof(NONCLIENTMETRICSW
);
135 ret
= SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
,
136 sizeof(NONCLIENTMETRICSW
),
139 if (!ret
) return FALSE
;
141 /* Load icon metrics */
142 scheme
->icMetrics
.cbSize
= sizeof(ICONMETRICSW
);
143 ret
= SystemParametersInfoW(SPI_GETICONMETRICS
,
144 sizeof(ICONMETRICSW
),
147 if (!ret
) return FALSE
;
149 /* Load flat menu style */
150 ret
= SystemParametersInfoW(SPI_GETFLATMENU
,
154 if (!ret
) return FALSE
;
157 /* "Use the following transition effect for menus and tooltips" */
158 ret
= SystemParametersInfoW(SPI_GETMENUANIMATION
,
160 &scheme
->Effects
.bMenuAnimation
,
162 if (!ret
) return FALSE
;
164 ret
= SystemParametersInfoW(SPI_GETMENUFADE
,
166 &scheme
->Effects
.bMenuFade
,
168 if (!ret
) return FALSE
;
170 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
171 * Just keep them in sync for now:
173 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
174 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
176 /* Show content of windows during dragging */
177 ret
= SystemParametersInfoW(SPI_GETDRAGFULLWINDOWS
,
179 &scheme
->Effects
.bDragFullWindows
,
181 if (!ret
) return FALSE
;
183 /* "Hide underlined letters for keyboard navigation until I press the Alt key" */
184 ret
= SystemParametersInfoW(SPI_GETKEYBOARDCUES
,
186 &scheme
->Effects
.bKeyboardCues
,
188 if (!ret
) return FALSE
;
190 /* Read the icon size from registry */
191 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPMetrics
, &hKey
);
192 if(Result
== ERROR_SUCCESS
)
194 scheme
->iIconSize
= SHRegGetIntW(hKey
, L
"Shell Icon Size", 32);
202 * LoadSchemeFromReg: Populates the passed scheme with values retireved from registry
205 LoadSchemeFromReg(OUT COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
208 WCHAR strValueName
[10], strSchemeKey
[MAX_PATH
];
209 HKEY hkScheme
= NULL
;
210 DWORD dwType
, dwLength
;
215 wsprintf(strSchemeKey
, L
"%s\\%s\\Sizes\\%s",
217 pSelectedTheme
->Color
->StyleName
,
218 pSelectedTheme
->Size
->StyleName
);
220 result
= RegOpenKeyW(HKEY_CURRENT_USER
, strSchemeKey
, &hkScheme
);
221 if (result
!= ERROR_SUCCESS
) return FALSE
;
223 scheme
->bFlatMenus
= SHRegGetIntW(hkScheme
, L
"FlatMenus", 0);
225 for (i
= 0; i
< NUM_COLORS
; i
++)
227 wsprintf(strValueName
, L
"Color #%d", i
);
228 dwLength
= sizeof(COLORREF
);
229 result
= RegQueryValueExW(hkScheme
,
233 (LPBYTE
)&scheme
->crColor
[i
],
235 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_DWORD
)
237 /* Failed to read registry value, initialize with current setting for now */
238 scheme
->crColor
[i
] = GetSysColor(i
);
242 for (i
= 0; i
< NUM_FONTS
; i
++)
244 PLOGFONTW lpfFont
= SchemeGetFont(scheme
, i
);
246 wsprintf(strValueName
, L
"Font #%d", i
);
247 dwLength
= sizeof(LOGFONT
);
248 result
= RegQueryValueExW(hkScheme
,
254 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_BINARY
||
255 dwLength
!= sizeof(LOGFONT
))
257 /* Failed to read registry value */
262 for (i
= 0; i
< NUM_SIZES
; i
++)
264 wsprintf(strValueName
, L
"Size #%d", i
);
265 dwLength
= sizeof(UINT64
);
266 result
= RegQueryValueExW(hkScheme
,
272 if (result
!= ERROR_SUCCESS
|| dwType
!= REG_QWORD
||
273 dwLength
!= sizeof(UINT64
))
275 /* Failed to read registry value, initialize with current setting for now */
279 SchemeSetMetric(scheme
, i
, (int)iSize
);
283 RegCloseKey(hkScheme
);
289 ApplyScheme: Applies the selected scheme and stores its id in the registry if needed
292 ApplyScheme(IN COLOR_SCHEME
*scheme
, IN PTHEME_SELECTION pSelectedTheme
)
296 WCHAR clText
[16], *StyleName
;
297 INT ColorList
[NUM_COLORS
];
299 /* Apply system colors */
300 for (i
= 0; i
< NUM_COLORS
; i
++)
302 SetSysColors(NUM_COLORS
, ColorList
, scheme
->crColor
);
304 /* Save colors to registry */
305 Result
= RegCreateKeyW(HKEY_CURRENT_USER
, g_CPColors
, &hKey
);
306 if (Result
== ERROR_SUCCESS
)
308 for (i
= 0; i
< NUM_COLORS
; i
++)
312 GetRValue(scheme
->crColor
[i
]),
313 GetGValue(scheme
->crColor
[i
]),
314 GetBValue(scheme
->crColor
[i
]));
321 (lstrlen(clText
) + 1) * sizeof(WCHAR
));
326 /* Apply non client metrics */
327 SystemParametersInfoW(SPI_SETNONCLIENTMETRICS
,
328 sizeof(NONCLIENTMETRICS
),
330 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
332 /* Apply icon metrics */
333 SystemParametersInfoW(SPI_SETICONMETRICS
,
336 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
338 /* Effects, save only when needed: */
339 /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
340 * Just keep them in sync for now.
342 scheme
->Effects
.bTooltipAnimation
= scheme
->Effects
.bMenuAnimation
;
343 scheme
->Effects
.bTooltipFade
= scheme
->Effects
.bMenuFade
;
344 SystemParametersInfoW(SPI_SETDRAGFULLWINDOWS
, scheme
->Effects
.bDragFullWindows
, (PVOID
)&scheme
->Effects
.bDragFullWindows
, SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
345 SystemParametersInfoW(SPI_SETKEYBOARDCUES
, 0, IntToPtr(scheme
->Effects
.bKeyboardCues
), SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
346 //SystemParametersInfoW(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)&scheme->Effects.bActiveWindowTracking, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
347 //SystemParametersInfoW(SPI_SETMENUANIMATION, 0, (PVOID)&scheme->Effects.bMenuAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
348 //SystemParametersInfoW(SPI_SETCOMBOBOXANIMATION, 0, (PVOID)&scheme->Effects.bComboBoxAnimation, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
349 //SystemParametersInfoW(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (PVOID)&scheme->Effects.bListBoxSmoothScrolling, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
350 //SystemParametersInfoW(SPI_SETGRADIENTCAPTIONS, 0, (PVOID)&scheme->Effects.bGradientCaptions, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
351 //SystemParametersInfoW(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)&scheme->Effects.bActiveWndTrkZorder, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
352 //SystemParametersInfoW(SPI_SETHOTTRACKING, 0, (PVOID)&scheme->Effects.bHotTracking, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
353 SystemParametersInfoW(SPI_SETMENUFADE
, 0, (PVOID
)&scheme
->Effects
.bMenuFade
, SPIF_UPDATEINIFILE
|SPIF_SENDCHANGE
);
354 //SystemParametersInfoW(SPI_SETSELECTIONFADE, 0, (PVOID)&scheme->Effects.bSelectionFade, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
355 SystemParametersInfoW(SPI_SETTOOLTIPANIMATION
, 0, (PVOID
)&scheme
->Effects
.bTooltipAnimation
, SPIF_UPDATEINIFILE
|SPIF_SENDCHANGE
);
356 SystemParametersInfoW(SPI_SETTOOLTIPFADE
, 0, (PVOID
)&scheme
->Effects
.bTooltipFade
, SPIF_UPDATEINIFILE
|SPIF_SENDCHANGE
);
357 //SystemParametersInfoW(SPI_SETCURSORSHADOW, 0, (PVOID)&scheme->Effects.bCursorShadow, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
358 //SystemParametersInfoW(SPI_SETUIEFFECTS, 0, (PVOID)&scheme->Effects.bUiEffects, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
360 /* Save SchemeId in the registry */
361 if (pSelectedTheme
->Theme
!= NULL
&& pSelectedTheme
->ThemeActive
== FALSE
)
363 StyleName
= pSelectedTheme
->Color
->StyleName
;
364 SHSetValueW(HKEY_CURRENT_USER
,
369 (lstrlenW(StyleName
) + 1) * sizeof(WCHAR
));
374 CreateTheme(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
378 pTheme
= (PTHEME
) malloc(sizeof(THEME
));
379 if (pTheme
== NULL
) return NULL
;
381 pTheme
->DisplayName
= _wcsdup(pszDisplayName
);
382 if (pTheme
->DisplayName
== NULL
)
388 pTheme
->ColoursList
= NULL
;
389 pTheme
->NextTheme
= NULL
;
390 pTheme
->SizesList
= NULL
;
394 pTheme
->ThemeFileName
= NULL
;
398 pTheme
->ThemeFileName
= _wcsdup(pszName
);
399 if (pTheme
->ThemeFileName
== NULL
)
401 free(pTheme
->DisplayName
);
410 CreateStyle(LPCWSTR pszName
, LPCWSTR pszDisplayName
)
414 pStyle
= (PTHEME_STYLE
) malloc(sizeof(THEME_STYLE
));
415 if (pStyle
== NULL
) return NULL
;
417 pStyle
->StyleName
= _wcsdup(pszName
);
418 if (pStyle
->StyleName
== NULL
)
424 pStyle
->DisplayName
= _wcsdup(pszDisplayName
);
425 if (pStyle
->DisplayName
== NULL
)
427 free(pStyle
->StyleName
);
432 pStyle
->ChildStyle
= NULL
;
433 pStyle
->NextStyle
= NULL
;
439 CleanupStyles(IN PTHEME_STYLE pStylesList
)
441 PTHEME_STYLE pStyle
, pStyleOld
;
443 pStyle
= pStylesList
;
446 if (pStyle
->ChildStyle
) CleanupStyles(pStyle
->ChildStyle
);
447 if (pStyle
->DisplayName
) free(pStyle
->DisplayName
);
448 if (pStyle
->StyleName
) free(pStyle
->StyleName
);
451 pStyle
= pStyle
->NextStyle
;
457 CleanupThemes(IN PTHEME pThemeList
)
459 PTHEME pTheme
, pThemeOld
;
464 CleanupStyles(pTheme
->ColoursList
);
465 if (pTheme
->SizesList
) CleanupStyles(pTheme
->SizesList
);
466 if (pTheme
->DisplayName
) free(pTheme
->DisplayName
);
467 if (pTheme
->ThemeFileName
) free(pTheme
->ThemeFileName
);
470 pTheme
= pTheme
->NextTheme
;
476 FindStyle(IN PTHEME_STYLE pStylesList
, IN PCWSTR StyleName
)
480 for (pStyle
= pStylesList
; pStyle
; pStyle
= pStyle
->NextStyle
)
482 if (_wcsicmp(pStyle
->StyleName
, StyleName
) == 0)
488 /* If we can't find the style requested, return the first one */
493 * LoadSchemeSizes: Returns a list of sizes from the registry key of a scheme
496 LoadSchemeSizes(IN HKEY hkScheme
)
498 HKEY hkSizes
, hkSize
;
501 WCHAR wstrSizeName
[5], wstrDisplayName
[50];
502 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
504 Result
= RegOpenKeyW(hkScheme
, L
"Sizes", &hkSizes
);
505 if (Result
!= ERROR_SUCCESS
) return NULL
;
508 while ((RegEnumKeyW(hkSizes
, iStyle
, wstrSizeName
, 5) == ERROR_SUCCESS
))
512 Result
= RegOpenKeyW(hkSizes
, wstrSizeName
, &hkSize
);
513 if (Result
!= ERROR_SUCCESS
) continue;
515 Result
= RegLoadMUIStringW(hkSize
,
518 sizeof(wstrDisplayName
),
522 if (Result
!= ERROR_SUCCESS
)
524 Result
= RegLoadMUIStringW(hkSize
,
527 sizeof(wstrDisplayName
),
533 if (Result
== ERROR_SUCCESS
)
534 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrDisplayName
);
536 pCurrentStyle
= CreateStyle(wstrSizeName
, wstrSizeName
);
538 if (pCurrentStyle
!= NULL
)
540 pCurrentStyle
->NextStyle
= List
;
541 List
= pCurrentStyle
;
547 RegCloseKey(hkSizes
);
552 LoadClassicColorSchemes: Returns a list of classic theme colours from the registry key of a scheme
555 LoadClassicColorSchemes(VOID
)
558 HKEY hkNewSchemes
, hkScheme
;
560 WCHAR wstrStyleName
[5], wstrDisplayName
[50];
561 THEME_STYLE
*List
= NULL
, *pCurrentStyle
;
563 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
564 if (Result
!= ERROR_SUCCESS
) return NULL
;
567 while ((RegEnumKeyW(hkNewSchemes
, iStyle
, wstrStyleName
, 5) == ERROR_SUCCESS
))
571 Result
= RegOpenKeyW(hkNewSchemes
, wstrStyleName
, &hkScheme
);
572 if (Result
!= ERROR_SUCCESS
) continue;
574 Result
= RegLoadMUIStringW(hkScheme
,
577 sizeof(wstrDisplayName
),
581 if (Result
!= ERROR_SUCCESS
)
583 Result
= RegLoadMUIStringW(hkScheme
,
586 sizeof(wstrDisplayName
),
592 if (Result
== ERROR_SUCCESS
)
593 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrDisplayName
);
595 pCurrentStyle
= CreateStyle(wstrStyleName
, wstrStyleName
);
597 if (pCurrentStyle
!= NULL
)
599 pCurrentStyle
->NextStyle
= List
;
600 pCurrentStyle
->ChildStyle
= LoadSchemeSizes(hkScheme
);
601 if(pCurrentStyle
->ChildStyle
== NULL
)
602 CleanupStyles(pCurrentStyle
);
604 List
= pCurrentStyle
;
607 RegCloseKey(hkScheme
);
610 RegCloseKey(hkNewSchemes
);
614 typedef HRESULT (WINAPI
*ENUMTHEMESTYLE
) (LPCWSTR
, LPWSTR
, DWORD
, PTHEMENAMES
);
617 EnumThemeStyles(IN LPCWSTR pszThemeFileName
, IN ENUMTHEMESTYLE pfnEnumTheme
)
621 THEME_STYLE
*List
= NULL
, **ppPrevStyle
, *pCurrentStyle
;
625 while (SUCCEEDED(pfnEnumTheme (pszThemeFileName
, NULL
, index
++, &names
)))
627 pCurrentStyle
= CreateStyle(names
.szName
, names
.szDisplayName
);
628 if(pCurrentStyle
== NULL
) break;
630 *ppPrevStyle
= pCurrentStyle
;
631 ppPrevStyle
= &pCurrentStyle
->NextStyle
;
638 EnumThemeProc(IN LPVOID lpReserved
,
639 IN LPCWSTR pszThemeFileName
,
640 IN LPCWSTR pszThemeName
,
641 IN LPCWSTR pszToolTip
,
642 IN LPVOID lpReserved2
,
643 IN OUT LPVOID lpData
)
645 PTHEME
*List
, pTheme
;
647 List
= (PTHEME
*)lpData
;
649 pTheme
= CreateTheme(pszThemeFileName
, pszThemeName
);
650 if (pTheme
== NULL
) return FALSE
;
652 pTheme
->SizesList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeSizes
);
653 pTheme
->ColoursList
= EnumThemeStyles( pszThemeFileName
, (ENUMTHEMESTYLE
)EnumThemeColors
);
654 if(pTheme
->SizesList
== NULL
|| pTheme
->ColoursList
== NULL
)
656 CleanupThemes(pTheme
);
660 pTheme
->NextTheme
= *List
;
667 LoadThemes: Returns a list that contains tha classic theme and
668 the visual styles of the system
674 PTHEME pClassicTheme
;
675 WCHAR strClassicTheme
[40];
676 WCHAR szThemesPath
[MAX_PATH
], *pszClassicTheme
;
679 /* Insert the classic theme */
680 res
= LoadString(hApplet
, IDS_CLASSIC_THEME
, strClassicTheme
, 40);
681 pszClassicTheme
= (res
> 0 ? strClassicTheme
: L
"Classic Theme");
682 pClassicTheme
= CreateTheme(NULL
, pszClassicTheme
);
683 if (pClassicTheme
== NULL
) return NULL
;
684 pClassicTheme
->ColoursList
= LoadClassicColorSchemes();
686 /* Get path to themes folder */
687 ZeroMemory(szThemesPath
, sizeof(szThemesPath
));
688 hret
= SHGetFolderPathW (NULL
, CSIDL_RESOURCES
, NULL
, SHGFP_TYPE_DEFAULT
, szThemesPath
);
689 if (FAILED(hret
)) return pClassicTheme
;
690 lstrcatW (szThemesPath
, L
"\\Themes");
692 /* Enumerate themes */
693 hret
= EnumThemes( szThemesPath
, EnumThemeProc
, &pClassicTheme
->NextTheme
);
696 pClassicTheme
->NextTheme
= NULL
;
697 if (pClassicTheme
->ColoursList
== NULL
)
699 free(pClassicTheme
->DisplayName
);
705 return pClassicTheme
;
709 * GetActiveTheme: Gets the active theme and populates pSelectedTheme
710 * with entries from the list of loaded themes
713 GetActiveTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
715 WCHAR szThemeFileName
[MAX_PATH
];
716 WCHAR szColorBuff
[MAX_PATH
];
717 WCHAR szSizeBuff
[MAX_PATH
];
721 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
723 /* Retrieve the name of the current theme */
724 hret
= GetCurrentThemeName(szThemeFileName
,
730 if (FAILED(hret
)) return FALSE
;
732 for (pTheme
= pThemeList
; pTheme
; pTheme
= pTheme
->NextTheme
)
734 if(pTheme
->ThemeFileName
&&
735 _wcsicmp(pTheme
->ThemeFileName
, szThemeFileName
) == 0)
741 if (pTheme
== NULL
) return FALSE
;
743 pSelectedTheme
->ThemeActive
= TRUE
;
744 pSelectedTheme
->Theme
= pTheme
;
745 pSelectedTheme
->Color
= FindStyle(pTheme
->ColoursList
, szColorBuff
);
746 pSelectedTheme
->Size
= FindStyle(pTheme
->SizesList
, szSizeBuff
);
752 GetActiveTheme: Gets the active classic theme and populates pSelectedTheme
753 with entries from the list of loaded themes
756 GetActiveClassicTheme(IN PTHEME pThemeList
, OUT PTHEME_SELECTION pSelectedTheme
)
759 WCHAR szSelectedClassicScheme
[5], szSelectedClassicSize
[5];
761 DWORD dwType
, dwDisplayNameLength
;
762 PTHEME_STYLE pCurrentStyle
, pCurrentSize
;
764 ZeroMemory(pSelectedTheme
, sizeof(THEME_SELECTION
));
767 szSelectedClassicScheme
[0] = 0;
768 szSelectedClassicSize
[0] = 0;
770 Result
= RegOpenKeyW(HKEY_CURRENT_USER
, g_CPANewSchemes
, &hkNewSchemes
);
771 if (Result
!= ERROR_SUCCESS
) return FALSE
;
774 dwDisplayNameLength
= sizeof(szSelectedClassicScheme
);
775 Result
= RegQueryValueEx(hkNewSchemes
, L
"SelectedStyle", NULL
, &dwType
,
776 (LPBYTE
)&szSelectedClassicScheme
, &dwDisplayNameLength
);
777 if (Result
== ERROR_SUCCESS
)
780 dwDisplayNameLength
= sizeof(szSelectedClassicSize
);
781 Result
= SHGetValue(hkNewSchemes
, szSelectedClassicScheme
, L
"SelectedSize",
782 &dwType
, szSelectedClassicSize
, &dwDisplayNameLength
);
785 RegCloseKey(hkNewSchemes
);
787 pCurrentStyle
= FindStyle(pThemeList
->ColoursList
, szSelectedClassicScheme
);
788 pCurrentSize
= FindStyle(pCurrentStyle
->ChildStyle
, szSelectedClassicSize
);
790 pSelectedTheme
->Theme
= pThemeList
;
791 pSelectedTheme
->Color
= pCurrentStyle
;
792 pSelectedTheme
->Size
= pCurrentSize
;
798 ActivateTheme(IN PTHEME_SELECTION pSelectedTheme
)
800 HTHEMEFILE hThemeFile
= 0;
803 if (pSelectedTheme
->ThemeActive
)
805 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
806 pSelectedTheme
->Color
->StyleName
,
807 pSelectedTheme
->Size
->StyleName
,
811 if (!SUCCEEDED(hret
)) return FALSE
;
814 hret
= ApplyTheme(hThemeFile
, "", 0);
816 if (pSelectedTheme
->ThemeActive
)
818 CloseThemeFile(hThemeFile
);
821 return SUCCEEDED(hret
);
825 LoadSchemeFromTheme(OUT PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
)
827 HTHEMEFILE hThemeFile
= 0;
832 hret
= OpenThemeFile(pSelectedTheme
->Theme
->ThemeFileName
,
833 pSelectedTheme
->Color
->StyleName
,
834 pSelectedTheme
->Size
->StyleName
,
838 if (!SUCCEEDED(hret
)) return FALSE
;
840 hTheme
= OpenThemeDataFromFile(hThemeFile
, hCPLWindow
, L
"WINDOW", 0);
841 if (hTheme
== NULL
) return FALSE
;
844 for (i
= 0; i
< NUM_COLORS
; i
++)
846 scheme
->crColor
[i
] = GetThemeSysColor(hTheme
,i
);
850 /* I wonder why GetThemeSysInt doesn't work here */
851 scheme
->ncMetrics
.iBorderWidth
= GetThemeSysSize(hTheme
, SM_CXFRAME
);
852 scheme
->ncMetrics
.iScrollWidth
= GetThemeSysSize(hTheme
, SM_CXVSCROLL
);
853 scheme
->ncMetrics
.iScrollHeight
= GetThemeSysSize(hTheme
, SM_CYHSCROLL
);
854 scheme
->ncMetrics
.iCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSIZE
);
855 scheme
->ncMetrics
.iCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSIZE
);
856 scheme
->ncMetrics
.iSmCaptionWidth
= GetThemeSysSize(hTheme
, SM_CXSMSIZE
);
857 scheme
->ncMetrics
.iSmCaptionHeight
= GetThemeSysSize(hTheme
, SM_CYSMSIZE
);
858 scheme
->ncMetrics
.iMenuWidth
= GetThemeSysSize(hTheme
, SM_CXMENUSIZE
);
859 scheme
->ncMetrics
.iMenuHeight
= GetThemeSysSize(hTheme
, SM_CYMENUSIZE
);
862 GetThemeSysFont(hTheme
, TMT_CAPTIONFONT
, &scheme
->ncMetrics
.lfCaptionFont
);
863 GetThemeSysFont(hTheme
, TMT_SMALLCAPTIONFONT
, &scheme
->ncMetrics
.lfSmCaptionFont
);
864 GetThemeSysFont(hTheme
, TMT_MENUFONT
, &scheme
->ncMetrics
.lfMenuFont
);
865 GetThemeSysFont(hTheme
, TMT_STATUSFONT
, &scheme
->ncMetrics
.lfStatusFont
);
866 GetThemeSysFont(hTheme
, TMT_MSGBOXFONT
, &scheme
->ncMetrics
.lfMessageFont
);
867 GetThemeSysFont(hTheme
, TMT_ICONTITLEFONT
, &scheme
->icMetrics
.lfFont
);
869 CloseThemeData(hTheme
);
875 DrawThemePreview(IN HDC hdcMem
, IN PCOLOR_SCHEME scheme
, IN PTHEME_SELECTION pSelectedTheme
, IN PRECT prcWindow
)
880 hbrBack
= CreateSolidBrush(scheme
->crColor
[COLOR_DESKTOP
]);
882 FillRect(hdcMem
, prcWindow
, hbrBack
);
883 DeleteObject(hbrBack
);
885 InflateRect(prcWindow
, -10, -10);
887 hres
= DrawNCPreview(hdcMem
,
890 pSelectedTheme
->Theme
->ThemeFileName
,
891 pSelectedTheme
->Color
->StyleName
,
892 pSelectedTheme
->Size
->StyleName
,
896 return SUCCEEDED(hres
);