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