3 * - Theme configuration code
4 * - User Shell Folder mapping
6 * Copyright (c) 2005 by Frank Richter
7 * Copyright (c) 2006 by Michael Jung
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
39 #include <wine/debug.h>
44 WINE_DEFAULT_DEBUG_CHANNEL(winecfg
);
46 /* UXTHEME functions not in the headers */
48 typedef struct tagTHEMENAMES
50 WCHAR szName
[MAX_PATH
+1];
51 WCHAR szDisplayName
[MAX_PATH
+1];
52 WCHAR szTooltip
[MAX_PATH
+1];
53 } THEMENAMES
, *PTHEMENAMES
;
55 typedef void* HTHEMEFILE
;
56 typedef BOOL (CALLBACK
*EnumThemeProc
)(LPVOID lpReserved
,
57 LPCWSTR pszThemeFileName
,
59 LPCWSTR pszToolTip
, LPVOID lpReserved2
,
62 HRESULT WINAPI
EnumThemeColors (LPCWSTR pszThemeFileName
, LPWSTR pszSizeName
,
63 DWORD dwColorNum
, PTHEMENAMES pszColorNames
);
64 HRESULT WINAPI
EnumThemeSizes (LPCWSTR pszThemeFileName
, LPWSTR pszColorName
,
65 DWORD dwSizeNum
, PTHEMENAMES pszSizeNames
);
66 HRESULT WINAPI
ApplyTheme (HTHEMEFILE hThemeFile
, char* unknown
, HWND hWnd
);
67 HRESULT WINAPI
OpenThemeFile (LPCWSTR pszThemeFileName
, LPCWSTR pszColorName
,
68 LPCWSTR pszSizeName
, HTHEMEFILE
* hThemeFile
,
70 HRESULT WINAPI
CloseThemeFile (HTHEMEFILE hThemeFile
);
71 HRESULT WINAPI
EnumThemes (LPCWSTR pszThemePath
, EnumThemeProc callback
,
74 static void refresh_sysparams(HWND hDlg
);
75 static void on_sysparam_change(HWND hDlg
);
77 /* A struct to keep both the internal and "fancy" name of a color or size */
84 /* wrapper around DSA that also keeps an item count */
91 /* Some helper functions to deal with ThemeColorOrSize structs in WrappedDSAs */
93 static void color_or_size_dsa_add (WrappedDsa
* wdsa
, const WCHAR
* name
,
94 const WCHAR
* fancyName
)
96 ThemeColorOrSize item
;
98 item
.name
= HeapAlloc (GetProcessHeap(), 0,
99 (lstrlenW (name
) + 1) * sizeof(WCHAR
));
100 lstrcpyW (item
.name
, name
);
102 item
.fancyName
= HeapAlloc (GetProcessHeap(), 0,
103 (lstrlenW (fancyName
) + 1) * sizeof(WCHAR
));
104 lstrcpyW (item
.fancyName
, fancyName
);
106 DSA_InsertItem (wdsa
->dsa
, wdsa
->count
, &item
);
110 static int CALLBACK
dsa_destroy_callback (LPVOID p
, LPVOID pData
)
112 ThemeColorOrSize
* item
= p
;
113 HeapFree (GetProcessHeap(), 0, item
->name
);
114 HeapFree (GetProcessHeap(), 0, item
->fancyName
);
118 static void free_color_or_size_dsa (WrappedDsa
* wdsa
)
120 DSA_DestroyCallback (wdsa
->dsa
, dsa_destroy_callback
, NULL
);
123 static void create_color_or_size_dsa (WrappedDsa
* wdsa
)
125 wdsa
->dsa
= DSA_Create (sizeof (ThemeColorOrSize
), 1);
129 static ThemeColorOrSize
* color_or_size_dsa_get (WrappedDsa
* wdsa
, int index
)
131 return DSA_GetItemPtr (wdsa
->dsa
, index
);
134 static int color_or_size_dsa_find (WrappedDsa
* wdsa
, const WCHAR
* name
)
137 for (; i
< wdsa
->count
; i
++)
139 ThemeColorOrSize
* item
= color_or_size_dsa_get (wdsa
, i
);
140 if (lstrcmpiW (item
->name
, name
) == 0) break;
145 /* A theme file, contains file name, display name, color and size scheme names */
148 WCHAR
* themeFileName
;
154 static HDSA themeFiles
= NULL
;
155 static int themeFilesCount
= 0;
157 static int CALLBACK
theme_dsa_destroy_callback (LPVOID p
, LPVOID pData
)
160 HeapFree (GetProcessHeap(), 0, item
->themeFileName
);
161 HeapFree (GetProcessHeap(), 0, item
->fancyName
);
162 free_color_or_size_dsa (&item
->colors
);
163 free_color_or_size_dsa (&item
->sizes
);
167 /* Free memory occupied by the theme list */
168 static void free_theme_files(void)
170 if (themeFiles
== NULL
) return;
172 DSA_DestroyCallback (themeFiles
, theme_dsa_destroy_callback
, NULL
);
177 typedef HRESULT (WINAPI
* EnumTheme
) (LPCWSTR
, LPWSTR
, DWORD
, PTHEMENAMES
);
179 /* fill a string list with either colors or sizes of a theme */
180 static void fill_theme_string_array (const WCHAR
* filename
,
187 WINE_TRACE ("%s %p %p\n", wine_dbgstr_w (filename
), wdsa
, enumTheme
);
189 while (SUCCEEDED (enumTheme (filename
, NULL
, index
++, &names
)))
191 WINE_TRACE ("%s: %s\n", wine_dbgstr_w (names
.szName
),
192 wine_dbgstr_w (names
.szDisplayName
));
193 color_or_size_dsa_add (wdsa
, names
.szName
, names
.szDisplayName
);
197 /* Theme enumeration callback, adds theme to theme list */
198 static BOOL CALLBACK
myEnumThemeProc (LPVOID lpReserved
,
199 LPCWSTR pszThemeFileName
,
200 LPCWSTR pszThemeName
,
202 LPVOID lpReserved2
, LPVOID lpData
)
206 /* fill size/color lists */
207 create_color_or_size_dsa (&newEntry
.colors
);
208 fill_theme_string_array (pszThemeFileName
, &newEntry
.colors
, EnumThemeColors
);
209 create_color_or_size_dsa (&newEntry
.sizes
);
210 fill_theme_string_array (pszThemeFileName
, &newEntry
.sizes
, EnumThemeSizes
);
212 newEntry
.themeFileName
= HeapAlloc (GetProcessHeap(), 0,
213 (lstrlenW (pszThemeFileName
) + 1) * sizeof(WCHAR
));
214 lstrcpyW (newEntry
.themeFileName
, pszThemeFileName
);
216 newEntry
.fancyName
= HeapAlloc (GetProcessHeap(), 0,
217 (lstrlenW (pszThemeName
) + 1) * sizeof(WCHAR
));
218 lstrcpyW (newEntry
.fancyName
, pszThemeName
);
220 /*list_add_tail (&themeFiles, &newEntry->entry);*/
221 DSA_InsertItem (themeFiles
, themeFilesCount
, &newEntry
);
227 /* Scan for themes */
228 static void scan_theme_files(void)
230 WCHAR themesPath
[MAX_PATH
];
234 if (FAILED (SHGetFolderPathW (NULL
, CSIDL_RESOURCES
, NULL
,
235 SHGFP_TYPE_CURRENT
, themesPath
))) return;
237 themeFiles
= DSA_Create (sizeof (ThemeFile
), 1);
238 lstrcatW (themesPath
, L
"\\Themes");
240 EnumThemes (themesPath
, myEnumThemeProc
, 0);
243 /* fill the color & size combo boxes for a given theme */
244 static void fill_color_size_combos (ThemeFile
* theme
, HWND comboColor
,
249 SendMessageW (comboColor
, CB_RESETCONTENT
, 0, 0);
250 for (i
= 0; i
< theme
->colors
.count
; i
++)
252 ThemeColorOrSize
* item
= color_or_size_dsa_get (&theme
->colors
, i
);
253 SendMessageW (comboColor
, CB_ADDSTRING
, 0, (LPARAM
)item
->fancyName
);
256 SendMessageW (comboSize
, CB_RESETCONTENT
, 0, 0);
257 for (i
= 0; i
< theme
->sizes
.count
; i
++)
259 ThemeColorOrSize
* item
= color_or_size_dsa_get (&theme
->sizes
, i
);
260 SendMessageW (comboSize
, CB_ADDSTRING
, 0, (LPARAM
)item
->fancyName
);
264 /* Select the item of a combo box that matches a theme's color and size
266 static void select_color_and_size (ThemeFile
* theme
,
267 const WCHAR
* colorName
, HWND comboColor
,
268 const WCHAR
* sizeName
, HWND comboSize
)
270 SendMessageW (comboColor
, CB_SETCURSEL
,
271 color_or_size_dsa_find (&theme
->colors
, colorName
), 0);
272 SendMessageW (comboSize
, CB_SETCURSEL
,
273 color_or_size_dsa_find (&theme
->sizes
, sizeName
), 0);
276 /* Fill theme, color and sizes combo boxes with the know themes and select
277 * the entries matching the currently active theme. */
278 static BOOL
fill_theme_list (HWND comboTheme
, HWND comboColor
, HWND comboSize
)
280 WCHAR textNoTheme
[256];
284 WCHAR currentTheme
[MAX_PATH
];
285 WCHAR currentColor
[MAX_PATH
];
286 WCHAR currentSize
[MAX_PATH
];
287 ThemeFile
* theme
= NULL
;
289 LoadStringW(GetModuleHandleW(NULL
), IDS_NOTHEME
, textNoTheme
, ARRAY_SIZE(textNoTheme
));
291 SendMessageW (comboTheme
, CB_RESETCONTENT
, 0, 0);
292 SendMessageW (comboTheme
, CB_ADDSTRING
, 0, (LPARAM
)textNoTheme
);
294 for (i
= 0; i
< themeFilesCount
; i
++)
296 ThemeFile
* item
= DSA_GetItemPtr (themeFiles
, i
);
297 SendMessageW (comboTheme
, CB_ADDSTRING
, 0,
298 (LPARAM
)item
->fancyName
);
301 if (IsThemeActive() && SUCCEEDED(GetCurrentThemeName(currentTheme
, ARRAY_SIZE(currentTheme
),
302 currentColor
, ARRAY_SIZE(currentColor
), currentSize
, ARRAY_SIZE(currentSize
))))
304 /* Determine the index of the currently active theme. */
306 for (i
= 0; i
< themeFilesCount
; i
++)
308 theme
= DSA_GetItemPtr (themeFiles
, i
);
309 if (lstrcmpiW (theme
->themeFileName
, currentTheme
) == 0)
318 /* Current theme not found?... add to the list, then... */
319 WINE_TRACE("Theme %s not in list of enumerated themes\n",
320 wine_dbgstr_w (currentTheme
));
321 myEnumThemeProc (NULL
, currentTheme
, currentTheme
,
322 currentTheme
, NULL
, NULL
);
323 themeIndex
= themeFilesCount
;
324 theme
= DSA_GetItemPtr (themeFiles
, themeFilesCount
-1);
326 fill_color_size_combos (theme
, comboColor
, comboSize
);
327 select_color_and_size (theme
, currentColor
, comboColor
,
328 currentSize
, comboSize
);
332 /* No theme selected */
336 SendMessageW (comboTheme
, CB_SETCURSEL
, themeIndex
, 0);
340 /* Update the color & size combo boxes when the selection of the theme
341 * combo changed. Selects the current color and size scheme if the theme
342 * is currently active, otherwise the first color and size. */
343 static BOOL
update_color_and_size (int themeIndex
, HWND comboColor
,
352 WCHAR currentTheme
[MAX_PATH
];
353 WCHAR currentColor
[MAX_PATH
];
354 WCHAR currentSize
[MAX_PATH
];
355 ThemeFile
* theme
= DSA_GetItemPtr (themeFiles
, themeIndex
- 1);
357 fill_color_size_combos (theme
, comboColor
, comboSize
);
359 if ((SUCCEEDED(GetCurrentThemeName (currentTheme
, ARRAY_SIZE(currentTheme
),
360 currentColor
, ARRAY_SIZE(currentColor
), currentSize
, ARRAY_SIZE(currentSize
))))
361 && (lstrcmpiW (currentTheme
, theme
->themeFileName
) == 0))
363 select_color_and_size (theme
, currentColor
, comboColor
,
364 currentSize
, comboSize
);
368 SendMessageW (comboColor
, CB_SETCURSEL
, 0, 0);
369 SendMessageW (comboSize
, CB_SETCURSEL
, 0, 0);
375 /* Apply a theme from a given theme, color and size combo box item index. */
376 static void do_apply_theme (HWND dialog
, int themeIndex
, int colorIndex
, int sizeIndex
)
378 static char b
[] = "\0";
383 ApplyTheme (NULL
, b
, NULL
);
387 ThemeFile
* theme
= DSA_GetItemPtr (themeFiles
, themeIndex
-1);
388 const WCHAR
* themeFileName
= theme
->themeFileName
;
389 const WCHAR
* colorName
= NULL
;
390 const WCHAR
* sizeName
= NULL
;
392 ThemeColorOrSize
* item
;
394 item
= color_or_size_dsa_get (&theme
->colors
, colorIndex
);
395 colorName
= item
->name
;
397 item
= color_or_size_dsa_get (&theme
->sizes
, sizeIndex
);
398 sizeName
= item
->name
;
400 if (SUCCEEDED (OpenThemeFile (themeFileName
, colorName
, sizeName
,
403 ApplyTheme (hTheme
, b
, NULL
);
404 CloseThemeFile (hTheme
);
408 ApplyTheme (NULL
, b
, NULL
);
412 refresh_sysparams(dialog
);
415 static BOOL updating_ui
;
416 static BOOL theme_dirty
;
418 static void enable_size_and_color_controls (HWND dialog
, BOOL enable
)
420 EnableWindow (GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
), enable
);
421 EnableWindow (GetDlgItem (dialog
, IDC_THEME_COLORTEXT
), enable
);
422 EnableWindow (GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
), enable
);
423 EnableWindow (GetDlgItem (dialog
, IDC_THEME_SIZETEXT
), enable
);
426 static void init_dialog (HWND dialog
)
428 SendDlgItemMessageW(dialog
, IDC_SYSPARAM_SIZE_UD
, UDM_SETBUDDY
,
429 (WPARAM
)GetDlgItem(dialog
, IDC_SYSPARAM_SIZE
), 0);
432 static void update_dialog (HWND dialog
)
437 if (!fill_theme_list (GetDlgItem (dialog
, IDC_THEME_THEMECOMBO
),
438 GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
),
439 GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
)))
441 SendMessageW (GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
), CB_SETCURSEL
, (WPARAM
)-1, 0);
442 SendMessageW (GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
), CB_SETCURSEL
, (WPARAM
)-1, 0);
443 enable_size_and_color_controls (dialog
, FALSE
);
447 enable_size_and_color_controls (dialog
, TRUE
);
451 SendDlgItemMessageW(dialog
, IDC_SYSPARAM_SIZE_UD
, UDM_SETRANGE
, 0, MAKELONG(100, 8));
456 static void on_theme_changed(HWND dialog
) {
457 int index
= SendMessageW (GetDlgItem (dialog
, IDC_THEME_THEMECOMBO
),
459 if (!update_color_and_size (index
, GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
),
460 GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
)))
462 SendMessageW (GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
), CB_SETCURSEL
, -1, 0);
463 SendMessageW (GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
), CB_SETCURSEL
, -1, 0);
464 enable_size_and_color_controls (dialog
, FALSE
);
468 enable_size_and_color_controls (dialog
, TRUE
);
473 static void apply_theme(HWND dialog
)
475 int themeIndex
, colorIndex
, sizeIndex
;
477 if (!theme_dirty
) return;
479 themeIndex
= SendMessageW (GetDlgItem (dialog
, IDC_THEME_THEMECOMBO
),
481 colorIndex
= SendMessageW (GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
),
483 sizeIndex
= SendMessageW (GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
),
486 do_apply_theme (dialog
, themeIndex
, colorIndex
, sizeIndex
);
492 int sm_idx
, color_idx
;
493 const WCHAR
*color_reg
;
499 {-1, COLOR_BTNFACE
, L
"ButtonFace" }, /* IDC_SYSPARAMS_BUTTON */
500 {-1, COLOR_BTNTEXT
, L
"ButtonText" }, /* IDC_SYSPARAMS_BUTTON_TEXT */
501 {-1, COLOR_BACKGROUND
, L
"Background" }, /* IDC_SYSPARAMS_DESKTOP */
502 {SM_CXMENUSIZE
, COLOR_MENU
, L
"Menu" }, /* IDC_SYSPARAMS_MENU */
503 {-1, COLOR_MENUTEXT
, L
"MenuText" }, /* IDC_SYSPARAMS_MENU_TEXT */
504 {SM_CXVSCROLL
, COLOR_SCROLLBAR
, L
"Scrollbar" }, /* IDC_SYSPARAMS_SCROLLBAR */
505 {-1, COLOR_HIGHLIGHT
, L
"Hilight" }, /* IDC_SYSPARAMS_SELECTION */
506 {-1, COLOR_HIGHLIGHTTEXT
, L
"HilightText" }, /* IDC_SYSPARAMS_SELECTION_TEXT */
507 {-1, COLOR_INFOBK
, L
"InfoWindow" }, /* IDC_SYSPARAMS_TOOLTIP */
508 {-1, COLOR_INFOTEXT
, L
"InfoText" }, /* IDC_SYSPARAMS_TOOLTIP_TEXT */
509 {-1, COLOR_WINDOW
, L
"Window" }, /* IDC_SYSPARAMS_WINDOW */
510 {-1, COLOR_WINDOWTEXT
, L
"WindowText" }, /* IDC_SYSPARAMS_WINDOW_TEXT */
511 {SM_CYSIZE
, COLOR_ACTIVECAPTION
, L
"ActiveTitle" }, /* IDC_SYSPARAMS_ACTIVE_TITLE */
512 {-1, COLOR_CAPTIONTEXT
, L
"TitleText" }, /* IDC_SYSPARAMS_ACTIVE_TITLE_TEXT */
513 {-1, COLOR_INACTIVECAPTION
, L
"InactiveTitle" }, /* IDC_SYSPARAMS_INACTIVE_TITLE */
514 {-1, COLOR_INACTIVECAPTIONTEXT
,L
"InactiveTitleText" }, /* IDC_SYSPARAMS_INACTIVE_TITLE_TEXT */
515 {-1, -1, L
"MsgBoxText" }, /* IDC_SYSPARAMS_MSGBOX_TEXT */
516 {-1, COLOR_APPWORKSPACE
, L
"AppWorkSpace" }, /* IDC_SYSPARAMS_APPWORKSPACE */
517 {-1, COLOR_WINDOWFRAME
, L
"WindowFrame" }, /* IDC_SYSPARAMS_WINDOW_FRAME */
518 {-1, COLOR_ACTIVEBORDER
, L
"ActiveBorder" }, /* IDC_SYSPARAMS_ACTIVE_BORDER */
519 {-1, COLOR_INACTIVEBORDER
, L
"InactiveBorder" }, /* IDC_SYSPARAMS_INACTIVE_BORDER */
520 {-1, COLOR_BTNSHADOW
, L
"ButtonShadow" }, /* IDC_SYSPARAMS_BUTTON_SHADOW */
521 {-1, COLOR_GRAYTEXT
, L
"GrayText" }, /* IDC_SYSPARAMS_GRAY_TEXT */
522 {-1, COLOR_BTNHIGHLIGHT
, L
"ButtonHilight" }, /* IDC_SYSPARAMS_BUTTON_HIGHLIGHT */
523 {-1, COLOR_3DDKSHADOW
, L
"ButtonDkShadow" }, /* IDC_SYSPARAMS_BUTTON_DARK_SHADOW */
524 {-1, COLOR_3DLIGHT
, L
"ButtonLight" }, /* IDC_SYSPARAMS_BUTTON_LIGHT */
525 {-1, COLOR_ALTERNATEBTNFACE
, L
"ButtonAlternateFace" }, /* IDC_SYSPARAMS_BUTTON_ALTERNATE */
526 {-1, COLOR_HOTLIGHT
, L
"HotTrackingColor" }, /* IDC_SYSPARAMS_HOT_TRACKING */
527 {-1, COLOR_GRADIENTACTIVECAPTION
, L
"GradientActiveTitle" }, /* IDC_SYSPARAMS_ACTIVE_TITLE_GRADIENT */
528 {-1, COLOR_GRADIENTINACTIVECAPTION
, L
"GradientInactiveTitle" }, /* IDC_SYSPARAMS_INACTIVE_TITLE_GRADIENT */
529 {-1, COLOR_MENUHILIGHT
, L
"MenuHilight" }, /* IDC_SYSPARAMS_MENU_HIGHLIGHT */
530 {-1, COLOR_MENUBAR
, L
"MenuBar" }, /* IDC_SYSPARAMS_MENUBAR */
533 static void save_sys_color(int idx
, COLORREF clr
)
537 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%d %d %d", GetRValue (clr
), GetGValue (clr
), GetBValue (clr
));
538 set_reg_key(HKEY_CURRENT_USER
, L
"Control Panel\\Colors", metrics
[idx
].color_reg
, buffer
);
541 static void set_color_from_theme(const WCHAR
*keyName
, COLORREF color
)
545 for (i
=0; i
< ARRAY_SIZE(metrics
); i
++)
547 if (wcsicmp(metrics
[i
].color_reg
, keyName
)==0)
549 metrics
[i
].color
= color
;
550 save_sys_color(i
, color
);
556 static void do_parse_theme(WCHAR
*file
)
558 WCHAR
*keyName
, keyNameValue
[MAX_PATH
];
559 DWORD len
, allocLen
= 512;
560 WCHAR
*keyNamePtr
= NULL
;
561 int red
= 0, green
= 0, blue
= 0;
564 WINE_TRACE("%s\n", wine_dbgstr_w(file
));
565 keyName
= malloc(sizeof(*keyName
) * allocLen
);
569 len
= GetPrivateProfileStringW(L
"Control Panel\\Colors", NULL
, NULL
, keyName
,
571 if (len
< allocLen
- 2)
575 keyName
= realloc(keyName
, sizeof(*keyName
) * allocLen
);
578 keyNamePtr
= keyName
;
579 while (*keyNamePtr
!=0) {
580 GetPrivateProfileStringW(L
"Control Panel\\Colors", keyNamePtr
, NULL
, keyNameValue
,
583 WINE_TRACE("parsing key: %s with value: %s\n",
584 wine_dbgstr_w(keyNamePtr
), wine_dbgstr_w(keyNameValue
));
586 swscanf(keyNameValue
, L
"%d %d %d", &red
, &green
, &blue
);
588 color
= RGB((BYTE
)red
, (BYTE
)green
, (BYTE
)blue
);
589 set_color_from_theme(keyNamePtr
, color
);
591 keyNamePtr
+=lstrlenW(keyNamePtr
);
597 static void on_theme_install(HWND dialog
)
599 static const WCHAR filterMask
[] = L
"\0*.msstyles;*.theme\0";
601 WCHAR filetitle
[MAX_PATH
];
602 WCHAR file
[MAX_PATH
];
606 LoadStringW(GetModuleHandleW(NULL
), IDS_THEMEFILE
, filter
, ARRAY_SIZE(filter
) - ARRAY_SIZE(filterMask
));
607 memcpy(filter
+ lstrlenW (filter
), filterMask
, sizeof(filterMask
));
608 LoadStringW(GetModuleHandleW(NULL
), IDS_THEMEFILE_SELECT
, title
, ARRAY_SIZE(title
));
610 ofn
.lStructSize
= sizeof(OPENFILENAMEW
);
611 ofn
.hwndOwner
= dialog
;
613 ofn
.lpstrFilter
= filter
;
614 ofn
.lpstrCustomFilter
= NULL
;
615 ofn
.nMaxCustFilter
= 0;
616 ofn
.nFilterIndex
= 0;
617 ofn
.lpstrFile
= file
;
618 ofn
.lpstrFile
[0] = '\0';
619 ofn
.nMaxFile
= ARRAY_SIZE(file
);
620 ofn
.lpstrFileTitle
= filetitle
;
621 ofn
.lpstrFileTitle
[0] = '\0';
622 ofn
.nMaxFileTitle
= ARRAY_SIZE(filetitle
);
623 ofn
.lpstrInitialDir
= NULL
;
624 ofn
.lpstrTitle
= title
;
625 ofn
.Flags
= OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_ENABLESIZING
;
627 ofn
.nFileExtension
= 0;
628 ofn
.lpstrDefExt
= NULL
;
631 ofn
.lpTemplateName
= NULL
;
633 if (GetOpenFileNameW(&ofn
))
635 WCHAR themeFilePath
[MAX_PATH
];
636 SHFILEOPSTRUCTW shfop
;
638 if (FAILED (SHGetFolderPathW (NULL
, CSIDL_RESOURCES
|CSIDL_FLAG_CREATE
, NULL
,
639 SHGFP_TYPE_CURRENT
, themeFilePath
))) return;
641 if (lstrcmpiW(PathFindExtensionW(filetitle
), L
".theme")==0)
643 do_parse_theme(file
);
644 SendMessageW(GetParent(dialog
), PSM_CHANGED
, 0, 0);
648 PathRemoveExtensionW (filetitle
);
650 /* Construct path into which the theme file goes */
651 lstrcatW (themeFilePath
, L
"\\themes\\");
652 lstrcatW (themeFilePath
, filetitle
);
654 /* Create the directory */
655 SHCreateDirectoryExW (dialog
, themeFilePath
, NULL
);
657 /* Append theme file name itself */
658 lstrcatW (themeFilePath
, L
"\\");
659 lstrcatW (themeFilePath
, PathFindFileNameW (file
));
660 /* SHFileOperation() takes lists as input, so double-nullterminate */
661 themeFilePath
[lstrlenW (themeFilePath
)+1] = 0;
662 file
[lstrlenW (file
)+1] = 0;
665 WINE_TRACE("copying: %s -> %s\n", wine_dbgstr_w (file
),
666 wine_dbgstr_w (themeFilePath
));
668 shfop
.wFunc
= FO_COPY
;
670 shfop
.pTo
= themeFilePath
;
671 shfop
.fFlags
= FOF_NOCONFIRMMKDIR
;
672 if (SHFileOperationW (&shfop
) == 0)
675 if (!fill_theme_list (GetDlgItem (dialog
, IDC_THEME_THEMECOMBO
),
676 GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
),
677 GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
)))
679 SendMessageW (GetDlgItem (dialog
, IDC_THEME_COLORCOMBO
), CB_SETCURSEL
, -1, 0);
680 SendMessageW (GetDlgItem (dialog
, IDC_THEME_SIZECOMBO
), CB_SETCURSEL
, -1, 0);
681 enable_size_and_color_controls (dialog
, FALSE
);
685 enable_size_and_color_controls (dialog
, TRUE
);
689 WINE_TRACE("copy operation failed\n");
691 else WINE_TRACE("user cancelled\n");
694 /* Information about symbolic link targets of certain User Shell Folders. */
695 struct ShellFolderInfo
{
697 char szLinkTarget
[FILENAME_MAX
]; /* in unix locale */
700 #define CSIDL_DOWNLOADS 0x0047
702 static struct ShellFolderInfo asfiInfo
[] = {
703 { CSIDL_DESKTOP
, "" },
704 { CSIDL_PERSONAL
, "" },
705 { CSIDL_MYPICTURES
, "" },
706 { CSIDL_MYMUSIC
, "" },
707 { CSIDL_MYVIDEO
, "" },
708 { CSIDL_DOWNLOADS
, "" },
709 { CSIDL_TEMPLATES
, "" }
712 static struct ShellFolderInfo
*psfiSelected
= NULL
;
714 static void init_shell_folder_listview_headers(HWND dialog
) {
715 LVCOLUMNW listColumn
;
717 WCHAR szShellFolder
[64] = L
"Shell Folder";
718 WCHAR szLinksTo
[64] = L
"Links to";
721 LoadStringW(GetModuleHandleW(NULL
), IDS_SHELL_FOLDER
, szShellFolder
, ARRAY_SIZE(szShellFolder
));
722 LoadStringW(GetModuleHandleW(NULL
), IDS_LINKS_TO
, szLinksTo
, ARRAY_SIZE(szLinksTo
));
724 GetClientRect(GetDlgItem(dialog
, IDC_LIST_SFPATHS
), &viewRect
);
725 width
= (viewRect
.right
- viewRect
.left
) / 3;
727 listColumn
.mask
= LVCF_TEXT
| LVCF_WIDTH
| LVCF_SUBITEM
;
728 listColumn
.pszText
= szShellFolder
;
729 listColumn
.cchTextMax
= lstrlenW(listColumn
.pszText
);
730 listColumn
.cx
= width
;
732 SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_INSERTCOLUMNW
, 0, (LPARAM
) &listColumn
);
734 listColumn
.pszText
= szLinksTo
;
735 listColumn
.cchTextMax
= lstrlenW(listColumn
.pszText
);
736 listColumn
.cx
= viewRect
.right
- viewRect
.left
- width
- 1;
738 SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_INSERTCOLUMNW
, 1, (LPARAM
) &listColumn
);
741 /* Reads the currently set shell folder symbol link targets into asfiInfo. */
742 static void read_shell_folder_link_targets(void) {
743 WCHAR wszPath
[MAX_PATH
];
746 for (i
=0; i
<ARRAY_SIZE(asfiInfo
); i
++) {
747 asfiInfo
[i
].szLinkTarget
[0] = '\0';
748 if (SUCCEEDED( SHGetFolderPathW( NULL
, asfiInfo
[i
].nFolder
| CSIDL_FLAG_DONT_VERIFY
, NULL
,
749 SHGFP_TYPE_CURRENT
, wszPath
)))
750 query_shell_folder( wszPath
, asfiInfo
[i
].szLinkTarget
, FILENAME_MAX
);
754 static void update_shell_folder_listview(HWND dialog
) {
757 LONG lSelected
= SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_GETNEXTITEM
, -1,
758 MAKELPARAM(LVNI_SELECTED
,0));
760 SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_DELETEALLITEMS
, 0, 0);
762 for (i
=0; i
<ARRAY_SIZE(asfiInfo
); i
++) {
763 WCHAR buffer
[MAX_PATH
];
765 LPITEMIDLIST pidlCurrent
;
767 /* Some acrobatic to get the localized name of the shell folder */
768 hr
= SHGetFolderLocation(dialog
, asfiInfo
[i
].nFolder
, NULL
, 0, &pidlCurrent
);
770 LPSHELLFOLDER psfParent
;
771 LPCITEMIDLIST pidlLast
;
772 hr
= SHBindToParent(pidlCurrent
, &IID_IShellFolder
, (LPVOID
*)&psfParent
, &pidlLast
);
775 hr
= IShellFolder_GetDisplayNameOf(psfParent
, pidlLast
, SHGDN_FORADDRESSBAR
, &strRet
);
777 hr
= StrRetToBufW(&strRet
, pidlLast
, buffer
, MAX_PATH
);
779 IShellFolder_Release(psfParent
);
784 /* If there's a dangling symlink for the current shell folder, SHGetFolderLocation
785 * will fail above. We fall back to the (non-verified) path of the shell folder. */
787 hr
= SHGetFolderPathW(dialog
, asfiInfo
[i
].nFolder
|CSIDL_FLAG_DONT_VERIFY
, NULL
,
788 SHGFP_TYPE_CURRENT
, buffer
);
791 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
794 item
.pszText
= buffer
;
795 item
.lParam
= (LPARAM
)&asfiInfo
[i
];
796 SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
798 item
.mask
= LVIF_TEXT
;
801 item
.pszText
= strdupU2W(asfiInfo
[i
].szLinkTarget
);
802 SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_SETITEMW
, 0, (LPARAM
)&item
);
803 HeapFree(GetProcessHeap(), 0, item
.pszText
);
806 /* Ensure that the previously selected item is selected again. */
807 if (lSelected
>= 0) {
808 item
.mask
= LVIF_STATE
;
809 item
.state
= LVIS_SELECTED
;
810 item
.stateMask
= LVIS_SELECTED
;
811 SendDlgItemMessageW(dialog
, IDC_LIST_SFPATHS
, LVM_SETITEMSTATE
, lSelected
, (LPARAM
)&item
);
815 static void on_shell_folder_selection_changed(HWND hDlg
, LPNMLISTVIEW lpnm
) {
816 if (lpnm
->uNewState
& LVIS_SELECTED
) {
817 psfiSelected
= (struct ShellFolderInfo
*)lpnm
->lParam
;
818 EnableWindow(GetDlgItem(hDlg
, IDC_LINK_SFPATH
), 1);
819 if (*psfiSelected
->szLinkTarget
) {
821 CheckDlgButton(hDlg
, IDC_LINK_SFPATH
, BST_CHECKED
);
822 EnableWindow(GetDlgItem(hDlg
, IDC_EDIT_SFPATH
), 1);
823 EnableWindow(GetDlgItem(hDlg
, IDC_BROWSE_SFPATH
), 1);
824 link
= strdupU2W(psfiSelected
->szLinkTarget
);
825 set_textW(hDlg
, IDC_EDIT_SFPATH
, link
);
826 HeapFree(GetProcessHeap(), 0, link
);
828 CheckDlgButton(hDlg
, IDC_LINK_SFPATH
, BST_UNCHECKED
);
829 EnableWindow(GetDlgItem(hDlg
, IDC_EDIT_SFPATH
), 0);
830 EnableWindow(GetDlgItem(hDlg
, IDC_BROWSE_SFPATH
), 0);
831 set_text(hDlg
, IDC_EDIT_SFPATH
, "");
835 CheckDlgButton(hDlg
, IDC_LINK_SFPATH
, BST_UNCHECKED
);
836 set_text(hDlg
, IDC_EDIT_SFPATH
, "");
837 EnableWindow(GetDlgItem(hDlg
, IDC_LINK_SFPATH
), 0);
838 EnableWindow(GetDlgItem(hDlg
, IDC_EDIT_SFPATH
), 0);
839 EnableWindow(GetDlgItem(hDlg
, IDC_BROWSE_SFPATH
), 0);
843 /* Keep the contents of the edit control, the listview control and the symlink
844 * information in sync. */
845 static void on_shell_folder_edit_changed(HWND hDlg
) {
847 WCHAR
*text
= get_text(hDlg
, IDC_EDIT_SFPATH
);
848 LONG iSel
= SendDlgItemMessageW(hDlg
, IDC_LIST_SFPATHS
, LVM_GETNEXTITEM
, -1,
849 MAKELPARAM(LVNI_SELECTED
,0));
851 if (!text
|| !psfiSelected
|| iSel
< 0) {
852 HeapFree(GetProcessHeap(), 0, text
);
856 WideCharToMultiByte(CP_UNIXCP
, 0, text
, -1,
857 psfiSelected
->szLinkTarget
, FILENAME_MAX
, NULL
, NULL
);
859 item
.mask
= LVIF_TEXT
;
863 SendDlgItemMessageW(hDlg
, IDC_LIST_SFPATHS
, LVM_SETITEMW
, 0, (LPARAM
)&item
);
865 HeapFree(GetProcessHeap(), 0, text
);
867 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
870 static void apply_shell_folder_changes(void) {
871 WCHAR wszPath
[MAX_PATH
];
874 for (i
=0; i
<ARRAY_SIZE(asfiInfo
); i
++) {
875 if (SUCCEEDED( SHGetFolderPathW( NULL
, asfiInfo
[i
].nFolder
| CSIDL_FLAG_CREATE
, NULL
,
876 SHGFP_TYPE_CURRENT
, wszPath
)))
877 set_shell_folder( wszPath
, asfiInfo
[i
].szLinkTarget
);
881 static void refresh_sysparams(HWND hDlg
)
885 for (i
= 0; i
< ARRAY_SIZE(metrics
); i
++)
887 if (metrics
[i
].sm_idx
!= -1)
888 metrics
[i
].size
= GetSystemMetrics(metrics
[i
].sm_idx
);
889 if (metrics
[i
].color_idx
!= -1)
890 metrics
[i
].color
= GetSysColor(metrics
[i
].color_idx
);
893 on_sysparam_change(hDlg
);
896 static void read_sysparams(HWND hDlg
)
899 HWND list
= GetDlgItem(hDlg
, IDC_SYSPARAM_COMBO
);
900 NONCLIENTMETRICSW nonclient_metrics
;
903 for (i
= 0; i
< ARRAY_SIZE(metrics
); i
++)
905 LoadStringW(GetModuleHandleW(NULL
), i
+ IDC_SYSPARAMS_BUTTON
, buffer
, ARRAY_SIZE(buffer
));
906 idx
= SendMessageW(list
, CB_ADDSTRING
, 0, (LPARAM
)buffer
);
907 if (idx
!= CB_ERR
) SendMessageW(list
, CB_SETITEMDATA
, idx
, i
);
909 if (metrics
[i
].sm_idx
!= -1)
910 metrics
[i
].size
= GetSystemMetrics(metrics
[i
].sm_idx
);
911 if (metrics
[i
].color_idx
!= -1)
912 metrics
[i
].color
= GetSysColor(metrics
[i
].color_idx
);
915 nonclient_metrics
.cbSize
= sizeof(NONCLIENTMETRICSW
);
916 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
, sizeof(NONCLIENTMETRICSW
), &nonclient_metrics
, 0);
918 memcpy(&(metrics
[IDC_SYSPARAMS_MENU_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
),
919 &(nonclient_metrics
.lfMenuFont
), sizeof(LOGFONTW
));
920 memcpy(&(metrics
[IDC_SYSPARAMS_ACTIVE_TITLE_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
),
921 &(nonclient_metrics
.lfCaptionFont
), sizeof(LOGFONTW
));
922 memcpy(&(metrics
[IDC_SYSPARAMS_TOOLTIP_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
),
923 &(nonclient_metrics
.lfStatusFont
), sizeof(LOGFONTW
));
924 memcpy(&(metrics
[IDC_SYSPARAMS_MSGBOX_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
),
925 &(nonclient_metrics
.lfMessageFont
), sizeof(LOGFONTW
));
928 static void apply_sysparams(void)
930 NONCLIENTMETRICSW ncm
;
932 int colors_idx
[ARRAY_SIZE(metrics
)];
933 COLORREF colors
[ARRAY_SIZE(metrics
)];
938 dpi
= GetDeviceCaps( hdc
, LOGPIXELSY
);
941 ncm
.cbSize
= sizeof(ncm
);
942 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
, sizeof(ncm
), &ncm
, 0);
944 /* convert metrics back to twips */
945 ncm
.iMenuWidth
= ncm
.iMenuHeight
=
946 MulDiv( metrics
[IDC_SYSPARAMS_MENU
- IDC_SYSPARAMS_BUTTON
].size
, -1440, dpi
);
947 ncm
.iCaptionWidth
= ncm
.iCaptionHeight
=
948 MulDiv( metrics
[IDC_SYSPARAMS_ACTIVE_TITLE
- IDC_SYSPARAMS_BUTTON
].size
, -1440, dpi
);
949 ncm
.iScrollWidth
= ncm
.iScrollHeight
=
950 MulDiv( metrics
[IDC_SYSPARAMS_SCROLLBAR
- IDC_SYSPARAMS_BUTTON
].size
, -1440, dpi
);
951 ncm
.iSmCaptionWidth
= MulDiv( ncm
.iSmCaptionWidth
, -1440, dpi
);
952 ncm
.iSmCaptionHeight
= MulDiv( ncm
.iSmCaptionHeight
, -1440, dpi
);
954 ncm
.lfMenuFont
= metrics
[IDC_SYSPARAMS_MENU_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
;
955 ncm
.lfCaptionFont
= metrics
[IDC_SYSPARAMS_ACTIVE_TITLE_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
;
956 ncm
.lfStatusFont
= metrics
[IDC_SYSPARAMS_TOOLTIP_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
;
957 ncm
.lfMessageFont
= metrics
[IDC_SYSPARAMS_MSGBOX_TEXT
- IDC_SYSPARAMS_BUTTON
].lf
;
959 SystemParametersInfoW(SPI_SETNONCLIENTMETRICS
, sizeof(ncm
), &ncm
,
960 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
);
962 for (i
= 0; i
< ARRAY_SIZE(metrics
); i
++)
963 if (metrics
[i
].color_idx
!= -1)
965 colors_idx
[cnt
] = metrics
[i
].color_idx
;
966 colors
[cnt
++] = metrics
[i
].color
;
968 SetSysColors(cnt
, colors_idx
, colors
);
971 static void on_sysparam_change(HWND hDlg
)
973 int index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETCURSEL
, 0, 0);
975 index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETITEMDATA
, index
, 0);
979 EnableWindow(GetDlgItem(hDlg
, IDC_SYSPARAM_COLOR_TEXT
), metrics
[index
].color_idx
!= -1);
980 EnableWindow(GetDlgItem(hDlg
, IDC_SYSPARAM_COLOR
), metrics
[index
].color_idx
!= -1);
981 InvalidateRect(GetDlgItem(hDlg
, IDC_SYSPARAM_COLOR
), NULL
, TRUE
);
983 EnableWindow(GetDlgItem(hDlg
, IDC_SYSPARAM_SIZE_TEXT
), metrics
[index
].sm_idx
!= -1);
984 EnableWindow(GetDlgItem(hDlg
, IDC_SYSPARAM_SIZE
), metrics
[index
].sm_idx
!= -1);
985 EnableWindow(GetDlgItem(hDlg
, IDC_SYSPARAM_SIZE_UD
), metrics
[index
].sm_idx
!= -1);
986 if (metrics
[index
].sm_idx
!= -1)
987 SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_SIZE_UD
, UDM_SETPOS
, 0, MAKELONG(metrics
[index
].size
, 0));
989 set_text(hDlg
, IDC_SYSPARAM_SIZE
, "");
991 EnableWindow(GetDlgItem(hDlg
, IDC_SYSPARAM_FONT
),
992 index
== IDC_SYSPARAMS_MENU_TEXT
-IDC_SYSPARAMS_BUTTON
||
993 index
== IDC_SYSPARAMS_ACTIVE_TITLE_TEXT
-IDC_SYSPARAMS_BUTTON
||
994 index
== IDC_SYSPARAMS_TOOLTIP_TEXT
-IDC_SYSPARAMS_BUTTON
||
995 index
== IDC_SYSPARAMS_MSGBOX_TEXT
-IDC_SYSPARAMS_BUTTON
1001 static void on_draw_item(HWND hDlg
, WPARAM wParam
, LPARAM lParam
)
1003 static HBRUSH black_brush
= 0;
1004 LPDRAWITEMSTRUCT draw_info
= (LPDRAWITEMSTRUCT
)lParam
;
1006 if (!black_brush
) black_brush
= CreateSolidBrush(0);
1008 if (draw_info
->CtlID
== IDC_SYSPARAM_COLOR
)
1014 theme
= OpenThemeDataForDpi(NULL
, WC_BUTTONW
, GetDpiForWindow(hDlg
));
1019 if (draw_info
->itemState
& ODS_DISABLED
)
1020 state
= PBS_DISABLED
;
1021 else if (draw_info
->itemState
& ODS_SELECTED
)
1022 state
= PBS_PRESSED
;
1026 if (IsThemeBackgroundPartiallyTransparent(theme
, BP_PUSHBUTTON
, state
))
1027 DrawThemeParentBackground(draw_info
->hwndItem
, draw_info
->hDC
, NULL
);
1029 DrawThemeBackground(theme
, draw_info
->hDC
, BP_PUSHBUTTON
, state
, &draw_info
->rcItem
, NULL
);
1031 buttonrect
= draw_info
->rcItem
;
1033 GetThemeMargins(theme
, draw_info
->hDC
, BP_PUSHBUTTON
, state
, TMT_CONTENTMARGINS
, &draw_info
->rcItem
, &margins
);
1035 buttonrect
.left
+= margins
.cxLeftWidth
;
1036 buttonrect
.top
+= margins
.cyTopHeight
;
1037 buttonrect
.right
-= margins
.cxRightWidth
;
1038 buttonrect
.bottom
-= margins
.cyBottomHeight
;
1040 if (draw_info
->itemState
& ODS_FOCUS
)
1041 DrawFocusRect(draw_info
->hDC
, &buttonrect
);
1043 CloseThemeData(theme
);
1045 state
= DFCS_ADJUSTRECT
| DFCS_BUTTONPUSH
;
1047 if (draw_info
->itemState
& ODS_DISABLED
)
1048 state
|= DFCS_INACTIVE
;
1050 state
|= draw_info
->itemState
& ODS_SELECTED
? DFCS_PUSHED
: 0;
1052 DrawFrameControl(draw_info
->hDC
, &draw_info
->rcItem
, DFC_BUTTON
, state
);
1054 buttonrect
= draw_info
->rcItem
;
1057 if (!(draw_info
->itemState
& ODS_DISABLED
))
1060 int index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETCURSEL
, 0, 0);
1062 index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETITEMDATA
, index
, 0);
1063 brush
= CreateSolidBrush(metrics
[index
].color
);
1065 InflateRect(&buttonrect
, -1, -1);
1066 FrameRect(draw_info
->hDC
, &buttonrect
, black_brush
);
1067 InflateRect(&buttonrect
, -1, -1);
1068 FillRect(draw_info
->hDC
, &buttonrect
, brush
);
1069 DeleteObject(brush
);
1074 static void on_select_font(HWND hDlg
)
1077 int index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETCURSEL
, 0, 0);
1078 index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETITEMDATA
, index
, 0);
1080 ZeroMemory(&cf
, sizeof(cf
));
1081 cf
.lStructSize
= sizeof(CHOOSEFONTW
);
1082 cf
.hwndOwner
= hDlg
;
1083 cf
.lpLogFont
= &(metrics
[index
].lf
);
1084 cf
.Flags
= CF_SCREENFONTS
| CF_INITTOLOGFONTSTRUCT
| CF_NOSCRIPTSEL
| CF_NOVERTFONTS
;
1086 if (ChooseFontW(&cf
))
1087 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1090 static void init_mime_types(HWND hDlg
)
1092 WCHAR
*buf
= get_reg_key(config_key
, keypath(L
"FileOpenAssociations"), L
"Enable", L
"Y");
1093 int state
= IS_OPTION_TRUE(*buf
) ? BST_CHECKED
: BST_UNCHECKED
;
1095 CheckDlgButton(hDlg
, IDC_ENABLE_FILE_ASSOCIATIONS
, state
);
1097 HeapFree(GetProcessHeap(), 0, buf
);
1100 static void update_mime_types(HWND hDlg
)
1102 const WCHAR
*state
= L
"Y";
1104 if (IsDlgButtonChecked(hDlg
, IDC_ENABLE_FILE_ASSOCIATIONS
) != BST_CHECKED
)
1107 set_reg_key(config_key
, keypath(L
"FileOpenAssociations"), L
"Enable", state
);
1110 static BOOL CALLBACK
update_window_pos_proc(HWND hwnd
, LPARAM lp
)
1114 GetClientRect(hwnd
, &rect
);
1115 AdjustWindowRectEx(&rect
, GetWindowLongW(hwnd
, GWL_STYLE
), !!GetMenu(hwnd
),
1116 GetWindowLongW(hwnd
, GWL_EXSTYLE
));
1117 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1118 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
1122 /* Adjust the rectangle for top-level windows because the new non-client metrics may be different */
1123 static void update_window_pos(void)
1125 EnumWindows(update_window_pos_proc
, 0);
1129 ThemeDlgProc (HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1133 read_shell_folder_link_targets();
1134 init_shell_folder_listview_headers(hDlg
);
1135 update_shell_folder_listview(hDlg
);
1136 read_sysparams(hDlg
);
1137 init_mime_types(hDlg
);
1146 set_window_title(hDlg
);
1150 switch(HIWORD(wParam
)) {
1151 case CBN_SELCHANGE
: {
1152 if (updating_ui
) break;
1153 switch (LOWORD(wParam
))
1155 case IDC_THEME_THEMECOMBO
: on_theme_changed(hDlg
); break;
1156 case IDC_THEME_COLORCOMBO
: /* fall through */
1157 case IDC_THEME_SIZECOMBO
: theme_dirty
= TRUE
; break;
1158 case IDC_SYSPARAM_COMBO
: on_sysparam_change(hDlg
); return FALSE
;
1160 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1164 if (updating_ui
) break;
1165 switch (LOWORD(wParam
))
1167 case IDC_EDIT_SFPATH
: on_shell_folder_edit_changed(hDlg
); break;
1168 case IDC_SYSPARAM_SIZE
:
1170 WCHAR
*text
= get_text(hDlg
, IDC_SYSPARAM_SIZE
);
1171 int index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETCURSEL
, 0, 0);
1173 index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETITEMDATA
, index
, 0);
1177 metrics
[index
].size
= wcstol(text
, NULL
, 10);
1178 HeapFree(GetProcessHeap(), 0, text
);
1182 /* for empty string set to minimum value */
1183 SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_SIZE_UD
, UDM_GETRANGE32
, (WPARAM
)&metrics
[index
].size
, 0);
1186 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1193 switch (LOWORD(wParam
))
1195 case IDC_THEME_INSTALL
:
1196 on_theme_install (hDlg
);
1199 case IDC_SYSPARAM_FONT
:
1200 on_select_font(hDlg
);
1203 case IDC_BROWSE_SFPATH
:
1205 WCHAR link
[FILENAME_MAX
];
1206 if (browse_for_unix_folder(hDlg
, link
)) {
1207 WideCharToMultiByte(CP_UNIXCP
, 0, link
, -1,
1208 psfiSelected
->szLinkTarget
, FILENAME_MAX
,
1210 update_shell_folder_listview(hDlg
);
1211 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1216 case IDC_LINK_SFPATH
:
1217 if (IsDlgButtonChecked(hDlg
, IDC_LINK_SFPATH
)) {
1218 WCHAR link
[FILENAME_MAX
];
1219 if (browse_for_unix_folder(hDlg
, link
)) {
1220 WideCharToMultiByte(CP_UNIXCP
, 0, link
, -1,
1221 psfiSelected
->szLinkTarget
, FILENAME_MAX
,
1223 update_shell_folder_listview(hDlg
);
1224 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1226 CheckDlgButton(hDlg
, IDC_LINK_SFPATH
, BST_UNCHECKED
);
1229 psfiSelected
->szLinkTarget
[0] = '\0';
1230 update_shell_folder_listview(hDlg
);
1231 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1235 case IDC_SYSPARAM_COLOR
:
1237 static COLORREF user_colors
[16];
1238 CHOOSECOLORW c_color
;
1239 int index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETCURSEL
, 0, 0);
1241 index
= SendDlgItemMessageW(hDlg
, IDC_SYSPARAM_COMBO
, CB_GETITEMDATA
, index
, 0);
1243 memset(&c_color
, 0, sizeof(c_color
));
1244 c_color
.lStructSize
= sizeof(c_color
);
1245 c_color
.lpCustColors
= user_colors
;
1246 c_color
.rgbResult
= metrics
[index
].color
;
1247 c_color
.Flags
= CC_ANYCOLOR
| CC_RGBINIT
;
1248 c_color
.hwndOwner
= hDlg
;
1249 if (ChooseColorW(&c_color
))
1251 metrics
[index
].color
= c_color
.rgbResult
;
1252 save_sys_color(index
, metrics
[index
].color
);
1253 InvalidateRect(GetDlgItem(hDlg
, IDC_SYSPARAM_COLOR
), NULL
, TRUE
);
1254 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1259 case IDC_ENABLE_FILE_ASSOCIATIONS
:
1260 update_mime_types(hDlg
);
1261 SendMessageW(GetParent(hDlg
), PSM_CHANGED
, 0, 0);
1269 switch (((LPNMHDR
)lParam
)->code
) {
1270 case PSN_KILLACTIVE
: {
1271 SetWindowLongPtrW(hDlg
, DWLP_MSGRESULT
, FALSE
);
1277 apply_shell_folder_changes();
1279 read_shell_folder_link_targets();
1280 update_shell_folder_listview(hDlg
);
1281 update_mime_types(hDlg
);
1282 update_window_pos();
1283 SetWindowLongPtrW(hDlg
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
1286 case LVN_ITEMCHANGED
: {
1287 if (wParam
== IDC_LIST_SFPATHS
)
1288 on_shell_folder_selection_changed(hDlg
, (LPNMLISTVIEW
)lParam
);
1291 case PSN_SETACTIVE
: {
1292 update_dialog(hDlg
);
1299 on_draw_item(hDlg
, wParam
, lParam
);