Reactos
at master 423 lines 16 kB view raw
1/* 2 * 'General' tab property sheet of Folder Options 3 * 4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org> 5 * Copyright 2016-2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22#include "precomp.h" 23 24WINE_DEFAULT_DEBUG_CHANNEL (fprop); 25 26static const LPCWSTR s_pszExplorerKey = REGSTR_PATH_EXPLORER; 27 28enum { UNDERLINE_ON, UNDERLINE_OFF, UNDERLINE_HOVER, UNDERLINE_IE }; 29 30///////////////////////////////////////////////////////////////////////////// 31// Shell settings 32 33EXTERN_C void 34SHELL32_GetDefaultShellState(LPSHELLSTATE pss) 35{ 36 ZeroMemory(pss, sizeof(*pss)); 37 pss->fShowAllObjects = TRUE; 38 pss->fShowExtensions = TRUE; 39 pss->fShowCompColor = TRUE; 40 pss->fDoubleClickInWebView = TRUE; 41 pss->fShowAttribCol = TRUE; // ROS defaults to Details view with this column on 42 pss->fShowInfoTip = TRUE; 43 pss->fShowSuperHidden = FALSE; 44 pss->lParamSort = SHFSF_COL_NAME; 45 pss->iSortDirection = 1; 46 pss->version = REGSHELLSTATE_VERSION; 47 pss->fSepProcess = FALSE; 48 pss->fStartPanelOn = FALSE; // Note: This should be changed to TRUE when the modern start menu is implemented 49} 50 51EXTERN_C LSTATUS 52SHELL32_WriteRegShellState(PREGSHELLSTATE prss) 53{ 54 prss->dwSize = REGSHELLSTATE_SIZE; 55 prss->ss.version = REGSHELLSTATE_VERSION; 56 return SHSetValueW(HKEY_CURRENT_USER, s_pszExplorerKey, L"ShellState", 57 REG_BINARY, prss, prss->dwSize); 58} 59 60// bDoubleClick is TRUE if "Double-click to open an item (single-click to select)". 61// bDoubleClick is FALSE if "Single-click to open an item (point to select)". 62////////////////////////////////////////////////////////////////////////////// 63// API Monitor: 64// SHLWAPI.dll RegOpenKeyExW ( 0x000000c8, NULL, 0, MAXIMUM_ALLOWED, 0x00def234 ) ERROR_SUCCESS 65// SHLWAPI.dll RegSetValueExW ( 0x000003e8, "ShellState", 0, REG_BINARY, 0x000c2050, 36 ) ERROR_SUCCESS 66// SHLWAPI.dll RegCloseKey ( 0x000003e8 ) ERROR_SUCCESS 67// Explorer.EXE SHSettingsChanged ( 0, "ShellState" ) (WM_SETTINGCHANGE handling) 68static BOOL 69IntSetShellStateSettings(BOOL bDoubleClick, BOOL bUseCommonTasks) 70{ 71 SHELLSTATE shellstate; 72 shellstate.fDoubleClickInWebView = !!bDoubleClick; 73 shellstate.fWebView = !!bUseCommonTasks; 74 SHGetSetSettings(&shellstate, SSF_DOUBLECLICKINWEBVIEW | SSF_WEBVIEW, TRUE); 75 return TRUE; 76} 77 78EXTERN_C BOOL 79SHELL32_ReadRegShellState(PREGSHELLSTATE prss) 80{ 81 DWORD dwSize = sizeof(REGSHELLSTATE); 82 LSTATUS err = SHGetValueW(HKEY_CURRENT_USER, s_pszExplorerKey, 83 L"ShellState", NULL, prss, &dwSize); 84 return err == ERROR_SUCCESS && prss->dwSize >= REGSHELLSTATE_SIZE; 85} 86 87// bUnderlineHover is TRUE if "Underline icon titles only when I point at them". 88// bUnderlineHover is FALSE if "Underline icon titles consistent with my browser". 89////////////////////////////////////////////////////////////////////////////// 90// API Monitor: 91// SHELL32.dll SHRegGetUSValueW ( "Software\Microsoft\Windows\CurrentVersion\Explorer", "IconUnderline", NULL, 0x00d2f324, 0x00d2f328, FALSE, 0x00d2f32c, 4 ) ERROR_SUCCESS 92// SHELL32.dll IsDlgButtonChecked ( 0x0005009e, 30104 ) BST_CHECKED 93// SHELL32.dll SHRegSetUSValueW ( "Software\Microsoft\Windows\CurrentVersion\Explorer", "IconUnderline", 0, 0x00d2f314, 4, 6 ) ERROR_SUCCESS 94// Explorer.EXE SHSettingsChanged ( 0, "Software\Microsoft\Windows\CurrentVersion\Explorer\IconUnderline" ) (WM_SETTINGCHANGE handling) 95static BOOL IntSetUnderlineState(BOOL bUnderlineHover) 96{ 97 LSTATUS Status; 98 DWORD dwValue = bUnderlineHover ? UNDERLINE_HOVER : UNDERLINE_IE; 99 Status = SHRegSetUSValue(s_pszExplorerKey, L"IconUnderline", REG_NONE, 100 &dwValue, sizeof(dwValue), SHREGSET_FORCE_HKCU | SHREGSET_HKLM); 101 if (Status != ERROR_SUCCESS) 102 return FALSE; 103 104 SHSendMessageBroadcastW(WM_SETTINGCHANGE, 0, (LPARAM)(REGSTR_PATH_EXPLORER L"\\IconUnderline")); 105 return TRUE; 106} 107 108static UINT IntGetRawIconUnderlineValue() 109{ 110 DWORD dwValue, dwDefault = UNDERLINE_ON; 111 DWORD dwSize = sizeof(dwValue); 112 SHRegGetUSValue(s_pszExplorerKey, L"IconUnderline", NULL, &dwValue, &dwSize, FALSE, &dwDefault, sizeof(dwDefault)); 113 return dwValue; 114} 115 116static UINT SHELL_GetIconUnderlineMode() 117{ 118 UINT mode = IntGetRawIconUnderlineValue(); 119 if (mode < UNDERLINE_IE) 120 return mode; 121 122 WCHAR buf[sizeof("hoverX")]; 123 *buf = UNICODE_NULL; 124 DWORD cb = sizeof(buf); 125 SHRegGetUSValueW(L"Software\\Microsoft\\Internet Explorer\\Main", 126 L"Anchor Underline", NULL, buf, &cb, FALSE, buf, cb); 127 if (!lstrcmpiW(buf, L"no")) 128 return UNDERLINE_OFF; 129 if (!lstrcmpiW(buf, L"hover")) 130 return UNDERLINE_HOVER; 131 return UNDERLINE_ON; 132} 133 134UINT SHELL_GetIconUnderlineFlags() 135{ 136 UINT mode = SHELL_GetIconUnderlineMode(); 137 if (mode == UNDERLINE_HOVER) 138 return LVS_EX_UNDERLINEHOT; 139 if (mode == UNDERLINE_ON) 140 return LVS_EX_UNDERLINEHOT | LVS_EX_UNDERLINECOLD; 141 return 0; 142} 143 144// bNewWindowMode is TRUE if "Open each folder in its own window". 145// bNewWindowMode is FALSE if "Open each folder in the same window". 146////////////////////////////////////////////////////////////////////////////// 147// API Monitor: 148// SHELL32.dll RegCreateKeyExW ( HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState", 0, NULL, 0, KEY_SET_VALUE, NULL, 0x00d2f2b8, NULL ) ERROR_SUCCESS 0.0000455 149// SHELL32.dll RegSetValueExW ( 0x00000854, "Settings", 0, REG_BINARY, 0x0210f170, 12 ) ERROR_SUCCESS 0.0001472 150// SHELL32.dll RegSetValueExW ( 0x00000854, "FullPath", 0, REG_DWORD, 0x00d2f2ac, 4 ) ERROR_SUCCESS 0.0000168 151// SHELL32.dll RegCloseKey ( 0x00000854 ) ERROR_SUCCESS 0.0000000 152static HRESULT IntSetNewWindowMode(BOOL bNewWindowMode) 153{ 154 CABINETSTATE cs; 155 if (!ReadCabinetState(&cs, sizeof(cs))) 156 return E_FAIL; 157 158 BOOL changed = !!cs.fNewWindowMode != !!bNewWindowMode; 159 cs.fNewWindowMode = !!bNewWindowMode; 160 return WriteCabinetState(&cs) ? (changed ? S_OK : S_FALSE) : E_FAIL; 161} 162 163static BOOL IntGetNewWindowMode(VOID) 164{ 165 CABINETSTATE cs; 166 if (!ReadCabinetState(&cs, sizeof(cs))) 167 return FALSE; 168 169 return !!cs.fNewWindowMode; 170} 171 172///////////////////////////////////////////////////////////////////////////// 173// GeneralDlg 174 175typedef struct GENERAL_DIALOG 176{ 177 HICON hTaskIcon; 178 HICON hFolderIcon; 179 HICON hClickIcon; 180} GENERAL_DIALOG, *PGENERAL_DIALOG; 181 182static VOID 183GeneralDlg_UpdateIcons(HWND hDlg, UINT nCtrlID, PGENERAL_DIALOG pGeneral) 184{ 185 HICON hTaskIcon = NULL, hFolderIcon = NULL, hClickIcon = NULL; 186 LPTSTR lpTaskIconName = NULL, lpFolderIconName = NULL, lpClickIconName = NULL; 187 188 // Show task setting icon. 189 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED) 190 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS); 191 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_CLASSICFOLDERS) == BST_CHECKED) 192 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS); 193 194 if (lpTaskIconName) 195 { 196 hTaskIcon = (HICON)LoadImage(shell32_hInstance, lpTaskIconName, 197 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 198 if (hTaskIcon) 199 { 200 HWND hwndTaskIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_TASKICON); 201 SendMessage(hwndTaskIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hTaskIcon); 202 } 203 } 204 205 // Show Folder setting icons 206 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED) 207 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW); 208 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_OWNWINDOW) == BST_CHECKED) 209 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW); 210 211 if (lpFolderIconName) 212 { 213 hFolderIcon = (HICON)LoadImage(shell32_hInstance, lpFolderIconName, 214 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 215 if (hFolderIcon) 216 { 217 HWND hwndFolderIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_FOLDERICON); 218 SendMessage(hwndFolderIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hFolderIcon); 219 } 220 } 221 222 // Show click setting icon 223 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED) 224 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN); 225 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_DOUBLECLICK) == BST_CHECKED) 226 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN); 227 228 if (lpClickIconName) 229 { 230 hClickIcon = (HICON)LoadImage(shell32_hInstance, lpClickIconName, 231 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 232 if (hClickIcon) 233 { 234 HWND hwndClickIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_CLICKICON); 235 SendMessage(hwndClickIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hClickIcon); 236 } 237 } 238 239 // Replace icons 240 if (hTaskIcon) 241 { 242 DestroyIcon(pGeneral->hTaskIcon); 243 pGeneral->hTaskIcon = hTaskIcon; 244 } 245 if (hFolderIcon) 246 { 247 DestroyIcon(pGeneral->hFolderIcon); 248 pGeneral->hFolderIcon = hFolderIcon; 249 } 250 if (hClickIcon) 251 { 252 DestroyIcon(pGeneral->hClickIcon); 253 pGeneral->hClickIcon = hClickIcon; 254 } 255 256 if (nCtrlID == IDC_FOLDER_OPTIONS_SINGLECLICK) 257 { 258 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER), TRUE); 259 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULPOINT), TRUE); 260 } 261 262 if (nCtrlID == IDC_FOLDER_OPTIONS_DOUBLECLICK) 263 { 264 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER), FALSE); 265 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULPOINT), FALSE); 266 } 267} 268 269static void 270GeneralDlg_StoreToUI(HWND hwndDlg, BOOL bDoubleClick, BOOL bUseCommonTasks, 271 BOOL bUnderlineHover, BOOL bNewWindowMode, PGENERAL_DIALOG pGeneral) 272{ 273 if (SHRestricted(REST_CLASSICSHELL)) 274 { 275 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK), FALSE); 276 bDoubleClick = TRUE; 277 bUseCommonTasks = FALSE; 278 } 279 280 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS), bUseCommonTasks); // TODO: ROS DefView does not support WebView nor the tasks pane 281 282 if (bUseCommonTasks) 283 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_COMMONTASKS); 284 else 285 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS); 286 287 if (bDoubleClick) 288 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK); 289 else 290 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK, IDC_FOLDER_OPTIONS_SINGLECLICK); 291 292 if (bNewWindowMode) 293 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW); 294 else 295 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW, IDC_FOLDER_OPTIONS_SAMEWINDOW); 296 297 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER), !bDoubleClick); 298 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT), !bDoubleClick); 299 if (bUnderlineHover) 300 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULPOINT); 301 else 302 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 303} 304 305static BOOL 306GeneralDlg_OnInitDialog(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 307{ 308 SHELLSTATE ss; 309 SHGetSetSettings(&ss, SSF_DOUBLECLICKINWEBVIEW | SSF_WEBVIEW, FALSE); 310 BOOL bDoubleClick = !!ss.fDoubleClickInWebView; 311 BOOL bUseCommonTasks = !!ss.fWebView; 312 BOOL bUnderlineHover = IntGetRawIconUnderlineValue() == UNDERLINE_HOVER; 313 BOOL bNewWindowMode = IntGetNewWindowMode(); 314 315 GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderlineHover, bNewWindowMode, pGeneral); 316 GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral); 317 318 return TRUE; 319} 320 321static void 322GeneralDlg_OnRestoreDefaults(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 323{ 324 // default values 325 BOOL bDoubleClick = TRUE; 326 BOOL bUseCommonTasks = TRUE; 327 BOOL bUnderlineHover = FALSE; 328 BOOL bNewWindowMode = (_WIN32_WINNT < _WIN32_WINNT_WIN2K); 329 330 GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderlineHover, bNewWindowMode, pGeneral); 331 GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral); 332} 333 334static BOOL 335GeneralDlg_OnApply(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 336{ 337 BOOL bDoubleClick = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED); 338 BOOL bUseCommonTasks = (IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED); 339 BOOL bUnderlineHover = (IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT) == BST_CHECKED); 340 BOOL bNewWindowMode = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED); 341 342 IntSetUnderlineState(bUnderlineHover); 343 BOOL updateCabinets = IntSetNewWindowMode(bNewWindowMode) == S_OK; 344 IntSetShellStateSettings(bDoubleClick, bUseCommonTasks); 345 if (updateCabinets) 346 PostCabinetMessage(CWM_STATECHANGE, 0, 0); 347 return TRUE; 348} 349 350INT_PTR CALLBACK 351FolderOptionsGeneralDlg( 352 HWND hwndDlg, 353 UINT uMsg, 354 WPARAM wParam, 355 LPARAM lParam) 356{ 357 static GENERAL_DIALOG general; 358 359 switch (uMsg) 360 { 361 case WM_INITDIALOG: 362 general.hTaskIcon = NULL; 363 general.hFolderIcon = NULL; 364 general.hClickIcon = NULL; 365 return GeneralDlg_OnInitDialog(hwndDlg, &general); 366 367 case WM_COMMAND: 368 switch (LOWORD(wParam)) 369 { 370 case IDC_FOLDER_OPTIONS_COMMONTASKS: 371 case IDC_FOLDER_OPTIONS_CLASSICFOLDERS: 372 case IDC_FOLDER_OPTIONS_SAMEWINDOW: 373 case IDC_FOLDER_OPTIONS_OWNWINDOW: 374 case IDC_FOLDER_OPTIONS_SINGLECLICK: 375 case IDC_FOLDER_OPTIONS_DOUBLECLICK: 376 case IDC_FOLDER_OPTIONS_ULBROWSER: 377 case IDC_FOLDER_OPTIONS_ULPOINT: 378 if (HIWORD(wParam) == BN_CLICKED) 379 { 380 GeneralDlg_UpdateIcons(hwndDlg, LOWORD(wParam), &general); 381 382 // Enable the 'Apply' button 383 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 384 } 385 break; 386 case IDC_FOLDER_OPTIONS_RESTORE: 387 if (HIWORD(wParam) == BN_CLICKED) 388 { 389 GeneralDlg_OnRestoreDefaults(hwndDlg, &general); 390 391 // Enable the 'Apply' button 392 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 393 } 394 break; 395 } 396 break; 397 398 case WM_NOTIFY: 399 { 400 LPNMHDR pnmh = (LPNMHDR)lParam; 401 402 switch (pnmh->code) 403 { 404 case PSN_SETACTIVE: 405 break; 406 407 case PSN_APPLY: 408 return GeneralDlg_OnApply(hwndDlg, &general); 409 } 410 break; 411 } 412 413 case WM_DESTROY: 414 DestroyIcon(general.hTaskIcon); 415 DestroyIcon(general.hFolderIcon); 416 DestroyIcon(general.hClickIcon); 417 break; 418 419 default: 420 return FALSE; 421 } 422 return FALSE; 423}