xref: /reactos/dll/cpl/desk/appearance.c (revision cd5c660b)
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS Display Control Panel
5  * FILE:            lib/cpl/desk/appearance.c
6  * PURPOSE:         Appearance property page
7  *
8  * PROGRAMMERS:     Trevor McCort (lycan359@gmail.com)
9  *                  Timo Kreuzer (timo[dot]kreuzer[at]web[dot]de
10  */
11 
12 #include "desk.h"
13 #include "appearance.h"
14 
15 /******************************************************************************/
16 
17 /* This const assigns the color and metric numbers to the elements from the elements list */
18 
19 /* Size 1 (width)	Size 2 (height)	Color 1					Color 2							Font			Fontcolor */
20 const ASSIGNMENT g_Assignment[NUM_ELEMENTS] =
21 { {-1,				-1,				COLOR_DESKTOP,			-1,								-1,				-1},				/* -Desktop */
22   {SIZE_CAPTION_Y,	-1,				COLOR_INACTIVECAPTION,	COLOR_GRADIENTINACTIVECAPTION,	FONT_CAPTION,	-1},				/* inactive window caption */
23   {SIZE_BORDER_X,	SIZE_BORDER_Y,	COLOR_INACTIVEBORDER,	-1,								-1,				-1},  				/* inactive window border */
24   {SIZE_CAPTION_Y,	-1,				COLOR_ACTIVECAPTION,	COLOR_GRADIENTACTIVECAPTION,	FONT_CAPTION,	COLOR_CAPTIONTEXT},	/* -active window caption */
25   {SIZE_BORDER_X,	SIZE_BORDER_Y,	COLOR_ACTIVEBORDER,		-1,								-1,				-1},				/* active window border */
26   {SIZE_MENU_X,		SIZE_MENU_Y,	COLOR_MENU,				-1, 							FONT_MENU,		COLOR_MENUTEXT},	/* menu */
27   {SIZE_MENU_X,		SIZE_MENU_Y,	COLOR_HIGHLIGHT,		-1,								FONT_HILIGHT,	COLOR_HIGHLIGHTTEXT},/* marked element */
28   {-1,				-1,				COLOR_WINDOW,			-1 /*COLOR_WINDOWFRAME*/,				-1,				COLOR_WINDOWTEXT},	/* window */
29   {SIZE_SCROLL_X,	SIZE_SCROLL_Y,	COLOR_SCROLLBAR,		-1,								-1,				-1},				/* scroll bar */
30   {-1,				-1,				COLOR_3DFACE,			-1,								-1,				COLOR_BTNTEXT},		/* 3d objects */
31   {SIZE_SMCAPTION_Y,-1,				-1,						-1,								FONT_SMCAPTION,	-1},				/* palette window caption */
32   {-1,				-1,				-1,						-1,								-1,				-1},				/* symbol caption FIXME: Access? */
33   {SIZE_CAPTION_Y,	-1,				-1,						-1,								-1,				-1},				/* caption bar */
34   {-1,				-1,				-1,						-1,								-1,				COLOR_GRAYTEXT},	/* inactive menu item FIXME: Access? */
35   {-1,				-1,				-1,						-1,								FONT_DIALOG,	COLOR_WINDOWTEXT},	/* dialog */
36   {-1,				-1,				-1,						-1,								-1,				-1},				/* scrollbar controls FIXME: Access? */
37   {-1,				-1,				COLOR_APPWORKSPACE,		-1,								-1,				-1},				/* application background */
38   {-1,				-1,				-1,						-1,								-1,				-1},				/* small caption bar FIXME: Access? */
39   {SIZE_ICON_SPC_X,	-1,				-1,						-1,								-1,				-1},				/* symbol distance horiz. */
40   {SIZE_ICON_SPC_Y,	-1,				-1,						-1,								-1,				-1},				/* symbol distance vert. */
41   {-1,				-1,				COLOR_INFOBK,			-1,								FONT_INFO,		COLOR_INFOTEXT},	/* quickinfo */
42   {SIZE_ICON_X,		SIZE_ICON_Y,	-1,						-1,								FONT_ICON,		-1}};				/* symbol */
43 
44 /* This is the list of names for the colors stored in the registry */
45 const TCHAR g_RegColorNames[NUM_COLORS][MAX_COLORNAMELENGTH] =
46 	{TEXT("Scrollbar"),				/* 00 = COLOR_SCROLLBAR */
47 	TEXT("Background"),				/* 01 = COLOR_DESKTOP */
48 	TEXT("ActiveTitle"),			/* 02 = COLOR_ACTIVECAPTION  */
49 	TEXT("InactiveTitle"),			/* 03 = COLOR_INACTIVECAPTION */
50 	TEXT("Menu"),					/* 04 = COLOR_MENU */
51 	TEXT("Window"),					/* 05 = COLOR_WINDOW */
52 	TEXT("WindowFrame"),			/* 06 = COLOR_WINDOWFRAME */
53 	TEXT("MenuText"), 				/* 07 = COLOR_MENUTEXT */
54 	TEXT("WindowText"), 			/* 08 = COLOR_WINDOWTEXT */
55 	TEXT("TitleText"), 				/* 09 = COLOR_CAPTIONTEXT */
56 	TEXT("ActiveBorder"), 			/* 10 = COLOR_ACTIVEBORDER */
57 	TEXT("InactiveBorder"), 		/* 11 = COLOR_INACTIVEBORDER */
58 	TEXT("AppWorkSpace"), 			/* 12 = COLOR_APPWORKSPACE */
59 	TEXT("Hilight"), 				/* 13 = COLOR_HIGHLIGHT */
60 	TEXT("HilightText"), 			/* 14 = COLOR_HIGHLIGHTTEXT */
61 	TEXT("ButtonFace"), 			/* 15 = COLOR_BTNFACE */
62 	TEXT("ButtonShadow"), 			/* 16 = COLOR_BTNSHADOW */
63 	TEXT("GrayText"), 				/* 17 = COLOR_GRAYTEXT */
64 	TEXT("ButtonText"), 			/* 18 = COLOR_BTNTEXT */
65 	TEXT("InactiveTitleText"), 		/* 19 = COLOR_INACTIVECAPTIONTEXT */
66 	TEXT("ButtonHilight"), 			/* 20 = COLOR_BTNHIGHLIGHT */
67 	TEXT("ButtonDkShadow"), 		/* 21 = COLOR_3DDKSHADOW */
68 	TEXT("ButtonLight"), 			/* 22 = COLOR_3DLIGHT */
69 	TEXT("InfoText"), 				/* 23 = COLOR_INFOTEXT */
70 	TEXT("InfoWindow"), 			/* 24 = COLOR_INFOBK */
71 	TEXT("ButtonAlternateFace"),	/* 25 = COLOR_ALTERNATEBTNFACE */
72 	TEXT("HotTrackingColor"), 		/* 26 = COLOR_HOTLIGHT */
73 	TEXT("GradientActiveTitle"),	/* 27 = COLOR_GRADIENTACTIVECAPTION */
74 	TEXT("GradientInactiveTitle"),	/* 28 = COLOR_GRADIENTINACTIVECAPTION */
75 	TEXT("MenuHilight"), 			/* 29 = COLOR_MENUHILIGHT */
76 	TEXT("MenuBar"), 				/* 30 = COLOR_MENUBAR */
77 };
78 
79 /* This is the list of used metrics and their numbers */
80 const int g_SizeMetric[NUM_SIZES] =
81 {
82 	SM_CXBORDER,
83 	SM_CYBORDER,
84 	SM_CYCAPTION,
85 	SM_CXICON,
86 	SM_CYICON,
87 	SM_CXICONSPACING,
88 	SM_CYICONSPACING,
89 	SM_CXMENUSIZE,
90 	SM_CYMENU,
91 	SM_CXVSCROLL,
92 	SM_CYHSCROLL,
93 	SM_CYSMCAPTION
94 };
95 
96 /******************************************************************************/
97 
98 static VOID
99 LoadCurrentTheme(GLOBALS* g)
100 {
101 	INT i;
102 	NONCLIENTMETRICS NonClientMetrics;
103 
104 	g->Theme.bHasChanged = FALSE;
105 	/* FIXME: it may be custom! */
106 	g->Theme.bIsCustom = FALSE;
107 
108 	/* Load colors */
109 	for (i = 0; i <= 30; i++)
110 	{
111 		g->ColorList[i] = i;
112 		g->Theme.crColor[i] = (COLORREF)GetSysColor(i);
113 	}
114 
115 	/* Load sizes */
116 	for (i = 0; i <= 11; i++)
117 	{
118 		g->Theme.Size[i] = GetSystemMetrics(g_SizeMetric[i]);
119 	}
120 
121 	/* Load fonts */
122 	NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS);
123 	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
124 	g->Theme.lfFont[FONT_CAPTION] = NonClientMetrics.lfCaptionFont;
125 	g->Theme.lfFont[FONT_SMCAPTION] = NonClientMetrics.lfSmCaptionFont;
126 	g->Theme.lfFont[FONT_MENU] = NonClientMetrics.lfMenuFont;
127 	g->Theme.lfFont[FONT_INFO] = NonClientMetrics.lfStatusFont;
128 	g->Theme.lfFont[FONT_DIALOG] = NonClientMetrics.lfMessageFont;
129 	SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &g->Theme.lfFont[FONT_ICON], 0);
130 
131     /* Effects */
132    /* "Use the following transition effect for menus and tooltips" */
133     SystemParametersInfo(SPI_GETMENUANIMATION, sizeof(BOOL), &g->Theme.Effects.bMenuAnimation, 0);
134     SystemParametersInfo(SPI_GETMENUFADE, sizeof(BOOL), &g->Theme.Effects.bMenuFade, 0);
135     /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
136      * Just keep them in sync for now:
137      */
138     g->Theme.Effects.bTooltipAnimation  = g->Theme.Effects.bMenuAnimation;
139     g->Theme.Effects.bTooltipFade       = g->Theme.Effects.bMenuFade;
140 
141     /* show content of windows during dragging */
142     //SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, g->Theme.Effects.bDragFullWindows, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
143     SystemParametersInfoW(SPI_GETDRAGFULLWINDOWS, 0, &g->Theme.Effects.bDragFullWindows, 0);
144 
145     /* "Hide underlined letters for keyboard navigation until I press the Alt key" */
146     SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &g->Theme.Effects.bKeyboardCues, 0);
147 }
148 
149 
150 static BOOL
151 LoadThemeFromReg(GLOBALS* g)
152 {
153 	INT i;
154 	TCHAR strSizeName[20] = {TEXT("Sizes\\0")};
155 	TCHAR strValueName[10];
156 	HKEY hkNewSchemes, hkScheme, hkSize;
157 	DWORD dwType, dwLength;
158 	BOOL Ret = FALSE;
159 	INT iPreset = g->Theme.Id;
160 
161 	if(RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance\\New Schemes"),
162 		0, KEY_READ, &hkNewSchemes) == ERROR_SUCCESS)
163 	{
164 		if(RegOpenKeyEx(hkNewSchemes, g->ThemeTemplates[iPreset].strKeyName, 0, KEY_READ, &hkScheme) == ERROR_SUCCESS)
165 		{
166 			lstrcpyn(&strSizeName[6],g->ThemeTemplates[iPreset].strSizeName, 3);
167 			if(RegOpenKeyEx(hkScheme, strSizeName, 0, KEY_READ, &hkSize) == ERROR_SUCCESS)
168 			{
169 				Ret = TRUE;
170 
171 				dwLength = sizeof(DWORD);
172 				if (RegQueryValueEx(hkSize, TEXT("FlatMenus"), NULL, &dwType, (LPBYTE)&g->Theme.bFlatMenus, &dwLength) != ERROR_SUCCESS ||
173 				    dwType != REG_DWORD || dwLength != sizeof(DWORD))
174 				{
175 					/* Failed to read registry value */
176 					g->Theme.bFlatMenus = FALSE;
177 					Ret = FALSE;
178 				}
179 
180 				for (i = 0; i <= 30; i++)
181 				{
182 					wsprintf(strValueName, TEXT("Color #%d"), i);
183 					dwLength = sizeof(COLORREF);
184 					if (RegQueryValueEx(hkSize, strValueName, NULL, &dwType, (LPBYTE)&g->Theme.crColor[i], &dwLength) != ERROR_SUCCESS ||
185 					    dwType != REG_DWORD || dwLength != sizeof(COLORREF))
186 					{
187 						/* Failed to read registry value, initialize with current setting for now */
188 						g->Theme.crColor[i] = GetSysColor(i);
189 						Ret = FALSE;
190 					}
191 				}
192 				for (i = 0; i <= 5; i++)
193 				{
194 					wsprintf(strValueName, TEXT("Font #%d"), i);
195 					dwLength = sizeof(LOGFONT);
196 					g->Theme.lfFont[i].lfFaceName[0] = 'x';
197 					if (RegQueryValueEx(hkSize, strValueName, NULL, &dwType, (LPBYTE)&g->Theme.lfFont[i], &dwLength) != ERROR_SUCCESS ||
198 					    dwType != REG_BINARY || dwLength != sizeof(LOGFONT))
199 					{
200 						/* Failed to read registry value */
201 						Ret = FALSE;
202 					}
203 				}
204 				for (i = 0; i <= 8; i++)
205 				{
206 					wsprintf(strValueName, TEXT("Size #%d"), i);
207 					dwLength = sizeof(UINT64);
208 					if (RegQueryValueEx(hkSize, strValueName, NULL, &dwType, (LPBYTE)&g->Theme.Size[i], &dwLength) != ERROR_SUCCESS ||
209 					    dwType != REG_QWORD || dwLength != sizeof(UINT64))
210 					{
211 						/* Failed to read registry value, initialize with current setting for now */
212 						g->Theme.Size[i] = GetSystemMetrics(g_SizeMetric[i]);
213 						Ret = FALSE;
214 					}
215 				}
216 				RegCloseKey(hkScheme);
217 			}
218 			RegCloseKey(hkScheme);
219 		}
220 		RegCloseKey(hkNewSchemes);
221 	}
222 
223 	return Ret;
224 }
225 
226 static VOID
227 _UpdateUserPref(UINT SpiGet,UINT SpiSet,BOOL *pbFlag)
228 {
229     SystemParametersInfo(SpiSet, 0, (PVOID)pbFlag, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
230 }
231 #define UPDATE_USERPREF(NAME,pbFlag) _UpdateUserPref(SPI_GET ## NAME, SPI_SET ## NAME, pbFlag)
232 
233 static VOID
234 ApplyTheme(GLOBALS* g)
235 {
236 	INT i, Result;
237 	HKEY hKey;
238 	DWORD dwDisposition = 0;
239 	TCHAR clText[16] = {0};
240 	NONCLIENTMETRICS NonClientMetrics;
241 	HFONT hMyFont;
242 	LOGFONT lfButtonFont;
243 
244 	if (!g->Theme.bHasChanged)
245 		return;
246 
247 	/* Update some globals */
248 	g->crCOLOR_BTNFACE = g->Theme.crColor[COLOR_BTNFACE];
249 	g->crCOLOR_BTNTEXT = g->Theme.crColor[COLOR_BTNTEXT];
250 	g->crCOLOR_BTNSHADOW = g->Theme.crColor[COLOR_BTNSHADOW];
251 	g->crCOLOR_BTNHIGHLIGHT = g->Theme.crColor[COLOR_BTNHIGHLIGHT];
252 	lfButtonFont = g->Theme.lfFont[FONT_DIALOG];
253 
254 	/* Create new font for bold button */
255 	lfButtonFont.lfWeight = FW_BOLD;
256 	lfButtonFont.lfItalic = FALSE;
257 	hMyFont = CreateFontIndirect(&lfButtonFont);
258 	if (hMyFont)
259 	{
260 		if (g->hBoldFont)
261 			DeleteObject(g->hBoldFont);
262 		g->hBoldFont = hMyFont;
263 	}
264 
265 	/* Create new font for italic button */
266 	lfButtonFont.lfWeight = FW_REGULAR;
267 	lfButtonFont.lfItalic = TRUE;
268 	hMyFont = CreateFontIndirect(&lfButtonFont);
269 	if (hMyFont)
270 	{
271 		if (g->hItalicFont)
272 			DeleteObject(g->hItalicFont);
273 		g->hItalicFont = hMyFont;
274 	}
275 
276 	/* Apply Colors from global variable */
277 	SetSysColors(30, &g->ColorList[0], &g->Theme.crColor[0]);
278 
279 	/* Save colors to registry */
280 	Result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Colors"), 0, KEY_ALL_ACCESS, &hKey);
281 	if (Result != ERROR_SUCCESS)
282 	{
283 		/* Could not open the key, try to create it */
284 		Result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Colors"), 0, NULL, 0, KEY_ALL_ACCESS, NULL,&hKey, &dwDisposition);
285 	}
286 
287 	if (Result == ERROR_SUCCESS)
288 	{
289 		for (i = 0; i <= 30; i++)
290 		{
291 			DWORD red   = GetRValue(g->Theme.crColor[i]);
292 			DWORD green = GetGValue(g->Theme.crColor[i]);
293 			DWORD blue  = GetBValue(g->Theme.crColor[i]);
294 			wsprintf(clText, TEXT("%d %d %d"), red, green, blue);
295 			RegSetValueEx(hKey, g_RegColorNames[i], 0, REG_SZ, (BYTE *)clText, lstrlen( clText )*sizeof(TCHAR) + sizeof(TCHAR));
296 		}
297 
298 		RegCloseKey(hKey);
299 	}
300 
301 	/* Apply the fonts */
302 	NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS);
303 	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
304 	NonClientMetrics.lfCaptionFont = g->Theme.lfFont[FONT_CAPTION];
305 	NonClientMetrics.lfSmCaptionFont = g->Theme.lfFont[FONT_SMCAPTION];
306 	NonClientMetrics.lfMenuFont = g->Theme.lfFont[FONT_MENU];
307 	NonClientMetrics.lfStatusFont = g->Theme.lfFont[FONT_INFO];
308 	NonClientMetrics.lfMessageFont = g->Theme.lfFont[FONT_DIALOG];
309 	SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
310 	SystemParametersInfo(SPI_SETICONTITLELOGFONT, sizeof(LOGFONT), &g->Theme.lfFont[FONT_ICON], 0);
311 
312 	/* FIXME: Apply size metrics */
313 
314 	/* Save fonts and size metrics to registry */
315 	Result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop\\WindowMetrics"), 0, KEY_ALL_ACCESS, &hKey);
316 	if (Result != ERROR_SUCCESS)
317 	{
318 		/* Could not open the key, try to create it */
319 		Result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop\\WindowMetrics"), 0, NULL, 0, KEY_ALL_ACCESS, NULL,&hKey, &dwDisposition);
320 	}
321 
322 	if (Result == ERROR_SUCCESS)
323 	{
324 		RegSetValueEx(hKey, TEXT("CaptionFont"), 0, REG_BINARY, (BYTE *)&g->Theme.lfFont[FONT_CAPTION], sizeof(LOGFONT));
325 		RegSetValueEx(hKey, TEXT("SmCaptionFont"), 0, REG_BINARY, (BYTE *)&g->Theme.lfFont[FONT_SMCAPTION], sizeof(LOGFONT));
326 		RegSetValueEx(hKey, TEXT("IconFont"), 0, REG_BINARY, (BYTE *)&g->Theme.lfFont[FONT_ICON], sizeof(LOGFONT));
327 		RegSetValueEx(hKey, TEXT("MenuFont"), 0, REG_BINARY, (BYTE *)&g->Theme.lfFont[FONT_MENU], sizeof(LOGFONT));
328 		RegSetValueEx(hKey, TEXT("StatusFont"), 0, REG_BINARY, (BYTE *)&g->Theme.lfFont[FONT_INFO], sizeof(LOGFONT));
329 		RegSetValueEx(hKey, TEXT("MessageFont"), 0, REG_BINARY, (BYTE *)&g->Theme.lfFont[FONT_DIALOG], sizeof(LOGFONT));
330 
331 		/* Save size metrics to registry */
332 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_BORDER_X]);
333 		RegSetValueEx(hKey, TEXT("BorderWidth"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
334 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_CAPTION_Y]);
335 		RegSetValueEx(hKey, TEXT("CaptionWidth"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
336 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_CAPTION_Y]);
337 		RegSetValueEx(hKey, TEXT("CaptionHeight"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
338 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_SMCAPTION_Y]);
339 		RegSetValueEx(hKey, TEXT("SmCaptionWidth"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
340 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_SMCAPTION_Y]);
341 		RegSetValueEx(hKey, TEXT("SmCaptionHeight"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
342 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_ICON_SPC_X]);
343 		RegSetValueEx(hKey, TEXT("IconSpacing"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
344 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_ICON_SPC_Y]);
345 		RegSetValueEx(hKey, TEXT("IconVerticalSpacing"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
346 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_MENU_X]);
347 		RegSetValueEx(hKey, TEXT("MenuWidth"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
348 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_MENU_Y]);
349 		RegSetValueEx(hKey, TEXT("MenuHeight"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
350 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_SCROLL_X]);
351 		RegSetValueEx(hKey, TEXT("ScrollWidth"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
352 		wsprintf(clText, TEXT("%d"), -15 * g->Theme.Size[SIZE_SCROLL_Y]);
353 		RegSetValueEx(hKey, TEXT("ScrollHeight"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
354 		wsprintf(clText, TEXT("%d"), g->Theme.Size[SIZE_ICON_X]);
355 		RegSetValueEx(hKey, TEXT("Shell Icon Sizet"), 0, REG_SZ, (BYTE *)clText, sizeof(clText));
356 
357 		RegCloseKey(hKey);
358 	}
359 
360     /* Effects, save only when needed: */
361     /* FIXME: XP seems to use grayed checkboxes to reflect differences between menu and tooltips settings
362      * Just keep them in sync for now.
363      */
364     g->Theme.Effects.bTooltipAnimation  = g->Theme.Effects.bMenuAnimation;
365     g->Theme.Effects.bTooltipFade       = g->Theme.Effects.bMenuFade;
366     SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, g->Theme.Effects.bDragFullWindows, NULL, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE);
367     //UPDATE_USERPREF(KEYBOARDCUES, &g->Theme.Effects.bKeyboardCues);
368     //UPDATE_USERPREF(ACTIVEWINDOWTRACKING, &g->Theme.Effects.bActiveWindowTracking);
369     //UPDATE_USERPREF(MENUANIMATION, &g->Theme.Effects.bMenuAnimation);
370     //UPDATE_USERPREF(COMBOBOXANIMATION, &g->Theme.Effects.bComboBoxAnimation);
371     //UPDATE_USERPREF(LISTBOXSMOOTHSCROLLING, &g->Theme.Effects.bListBoxSmoothScrolling);
372     //UPDATE_USERPREF(GRADIENTCAPTIONS, &g->Theme.Effects.bGradientCaptions);
373     //UPDATE_USERPREF(ACTIVEWNDTRKZORDER, &g->Theme.Effects.bActiveWndTrkZorder);
374     //UPDATE_USERPREF(HOTTRACKING, &g->Theme.Effects.bHotTracking);
375     UPDATE_USERPREF(MENUFADE, &g->Theme.Effects.bMenuFade);
376     //UPDATE_USERPREF(SELECTIONFADE, &g->Theme.Effects.bSelectionFade);
377     UPDATE_USERPREF(TOOLTIPANIMATION, &g->Theme.Effects.bTooltipAnimation);
378     UPDATE_USERPREF(TOOLTIPFADE, &g->Theme.Effects.bTooltipFade);
379     //UPDATE_USERPREF(CURSORSHADOW, &g->Theme.Effects.bCursorShadow);
380     //UPDATE_USERPREF(UIEFFECTS, &g->Theme.Effects.bUiEffects);
381 	/* Save ThemeId */
382 	Result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance\\New Schemes"), 0, KEY_ALL_ACCESS, &hKey);
383 	if (Result == ERROR_SUCCESS)
384 	{
385 		lstrcpy(clText, g->ThemeTemplates[g->Theme.Id].strKeyName);
386 		RegSetValueEx(hKey, TEXT("SelectedStyle"), 0, REG_SZ, (BYTE *)clText, (lstrlen(clText)+1) * sizeof (TCHAR));
387 		RegCloseKey(hKey);
388 	}
389 }
390 
391 
392 static INT_PTR
393 AppearancePage_OnInit(HWND hwndDlg, GLOBALS *g)
394 {
395 	HKEY hkNewSchemes, hkScheme, hkSizes, hkSize;
396 	FILETIME ftLastWriteTime;
397 	TCHAR strSelectedStyle[4];
398 	DWORD dwLength, dwType;
399 	DWORD dwDisposition = 0;
400 	INT iStyle, iSize, iTemplateIndex, iListIndex = 0;
401 	INT Result;
402 
403 	g = (GLOBALS*)malloc(sizeof(GLOBALS));
404 	if (g == NULL)
405 	{
406 		return FALSE;
407 	}
408 
409 	SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)g);
410 
411 	LoadCurrentTheme(g);
412 
413 	/* Fill color schemes combo */
414 	Result = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance\\New Schemes"),
415 		0, KEY_READ, &hkNewSchemes);
416 	if (Result != ERROR_SUCCESS)
417 	{
418 		/* Could not open the key, try to create it */
419 		Result = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Appearance\\New Schemes"), 0, NULL, 0, KEY_ALL_ACCESS, NULL,&hkNewSchemes, &dwDisposition);
420 		if (Result == ERROR_SUCCESS)
421 		{
422 			/* FIXME: We have created it new, so let's put somethig there */
423 		}
424 	}
425 	if (Result == ERROR_SUCCESS)
426 	{
427 		/* First find out the currently selected template */
428 		dwLength = 8;
429 		RegQueryValueEx(hkNewSchemes, TEXT("SelectedStyle"), NULL, &dwType, (LPBYTE)&strSelectedStyle, &dwLength);
430 		iTemplateIndex = 0;
431 		iStyle = 0;
432 		dwLength = MAX_TEMPLATENAMELENTGH;
433 		while((RegEnumKeyEx(hkNewSchemes, iStyle, g->ThemeTemplates[iTemplateIndex].strKeyName, &dwLength,
434 			NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) && (iTemplateIndex < MAX_TEMPLATES))
435 		{
436 			/* is it really a template or one of the other entries */
437 			if (dwLength < 5)
438 			{
439 				if (RegOpenKeyEx(hkNewSchemes, g->ThemeTemplates[iTemplateIndex].strKeyName, 0, KEY_READ, &hkScheme) == ERROR_SUCCESS)
440 				{
441 					if(RegOpenKeyEx(hkScheme, TEXT("Sizes"), 0, KEY_READ, &hkSizes) == ERROR_SUCCESS)
442 					{
443 						iSize = 0;
444 						dwLength = 3;
445 						while((RegEnumKeyEx(hkSizes, iSize, g->ThemeTemplates[iTemplateIndex].strSizeName, &dwLength,
446 							NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) && (iSize <= 4))
447 						{
448 							if(RegOpenKeyEx(hkSizes, g->ThemeTemplates[iTemplateIndex].strSizeName, 0, KEY_READ, &hkSize) == ERROR_SUCCESS)
449 							{
450 								dwLength = MAX_TEMPLATENAMELENTGH;
451 								RegQueryValueEx(hkSize, TEXT("DisplayName"), NULL, &dwType, (LPBYTE)&g->ThemeTemplates[iTemplateIndex].strDisplayName, &dwLength);
452 								dwLength = MAX_TEMPLATENAMELENTGH;
453 								RegQueryValueEx(hkSize, TEXT("LegacyName"), NULL, &dwType, (LPBYTE)&g->ThemeTemplates[iTemplateIndex].strLegacyName, &dwLength);
454 								RegCloseKey(hkSize);
455 							}
456 							iListIndex = SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_ADDSTRING, 0, (LPARAM)g->ThemeTemplates[iTemplateIndex].strLegacyName);
457 							SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_SETITEMDATA, iListIndex, iTemplateIndex);
458 							if (lstrcmp(g->ThemeTemplates[iTemplateIndex].strKeyName, strSelectedStyle) == 0)
459 							{
460 								SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_SETCURSEL, (WPARAM)iListIndex, 0);
461 							}
462 							iSize++;
463 							iTemplateIndex++;
464 							dwLength = 3;
465 						}
466 						RegCloseKey(hkSizes);
467 					}
468 					RegCloseKey(hkScheme);
469 				}
470 			}
471 			iStyle++;
472 			dwLength = MAX_TEMPLATENAMELENTGH;
473 		}
474 		RegCloseKey(hkNewSchemes);
475 	}
476 	SendMessage(GetDlgItem(hwndDlg, IDC_APPEARANCE_COLORSCHEME), LB_SETCURSEL, 0, 0);
477 
478 	return FALSE;
479 }
480 
481 
482 static INT_PTR
483 AppearancePage_OnDestroy(HWND hwndDlg, GLOBALS *g)
484 {
485 	free(g);
486 	return TRUE;
487 }
488 
489 
490 INT_PTR CALLBACK
491 AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
492 {
493 	INT i;
494 	GLOBALS *g;
495 	LPNMHDR lpnm;
496 
497 	g = (GLOBALS*)GetWindowLongPtr(hwndDlg, DWLP_USER);
498 
499 	switch (uMsg)
500 	{
501 		case WM_INITDIALOG:
502 			return AppearancePage_OnInit(hwndDlg, g);
503 
504 		case WM_DESTROY:
505 			return AppearancePage_OnDestroy(hwndDlg, g);
506 
507 		case WM_COMMAND:
508 			switch (LOWORD(wParam))
509 			{
510 				case IDC_APPEARANCE_EFFECTS:
511 					DialogBoxParam(hApplet, (LPCTSTR)IDD_EFFAPPEARANCE,
512 						hwndDlg, EffAppearanceDlgProc, (LPARAM)g);
513 
514 					/* Was anything changed in the effects appearance dialog? */
515 					if (memcmp(&g->Theme, &g->ThemeAdv, sizeof(THEME)) != 0)
516 					{
517 						PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
518 						g->Theme = g->ThemeAdv;
519 						g->Theme.bHasChanged = TRUE;
520 					}
521 					break;
522 
523 				case IDC_APPEARANCE_ADVANCED:
524 					DialogBoxParam(hApplet, (LPCTSTR)IDD_ADVAPPEARANCE,
525 						hwndDlg, AdvAppearanceDlgProc, (LPARAM)g);
526 
527 					/* Was anything changed in the advanced appearance dialog? */
528 					if (memcmp(&g->Theme, &g->ThemeAdv, sizeof(THEME)) != 0)
529 					{
530 						PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
531 						g->Theme = g->ThemeAdv;
532 						g->Theme.bHasChanged = TRUE;
533 					}
534 					break;
535 
536 				case IDC_APPEARANCE_COLORSCHEME:
537 					if(HIWORD(wParam) == CBN_SELCHANGE)
538 					{
539 						PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
540 						g->Theme.bHasChanged = TRUE;
541 						i = SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_GETCURSEL, 0, 0);
542 						g->Theme.Id = SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_GETITEMDATA, (WPARAM)i, 0);
543 						LoadThemeFromReg(g);
544 						//SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_PREVIEW, WM_PAINT, 0, 0);
545 					}
546 					break;
547 
548 				default:
549 					return FALSE;
550 			}
551 			return TRUE;
552 
553 		case WM_NOTIFY:
554 			lpnm = (LPNMHDR)lParam;
555 			switch (lpnm->code)
556 			{
557 				case PSN_APPLY:
558 					if (g->Theme.bHasChanged)
559 					{
560 						ApplyTheme(g);
561 					}
562 					return TRUE;
563 
564 				default:
565 					return FALSE;
566 			}
567 			return TRUE;
568 
569 		default:
570 			return FALSE;
571 	}
572 
573 	return TRUE;
574 }
575