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 24 WINE_DEFAULT_DEBUG_CHANNEL (fprop); 25 26 static const LPCWSTR s_pszExplorerKey = 27 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"; 28 29 ///////////////////////////////////////////////////////////////////////////// 30 // Shell settings 31 32 EXTERN_C void 33 SHELL32_GetDefaultShellState(LPSHELLSTATE pss) 34 { 35 ZeroMemory(pss, sizeof(*pss)); 36 pss->fShowAllObjects = TRUE; 37 pss->fShowExtensions = TRUE; 38 pss->fShowCompColor = TRUE; 39 pss->fDoubleClickInWebView = TRUE; 40 pss->fShowAttribCol = TRUE; // ROS defaults to Details view with this column on 41 pss->fShowInfoTip = TRUE; 42 pss->fShowSuperHidden = FALSE; 43 pss->lParamSort = SHFSF_COL_NAME; 44 pss->iSortDirection = 1; 45 pss->version = REGSHELLSTATE_VERSION; 46 pss->fSepProcess = FALSE; 47 pss->fStartPanelOn = FALSE; // Note: This should be changed to TRUE when the modern start menu is implemented 48 } 49 50 EXTERN_C LSTATUS 51 SHELL32_WriteRegShellState(PREGSHELLSTATE prss) 52 { 53 prss->dwSize = REGSHELLSTATE_SIZE; 54 prss->ss.version = REGSHELLSTATE_VERSION; 55 return SHSetValueW(HKEY_CURRENT_USER, s_pszExplorerKey, L"ShellState", 56 REG_BINARY, prss, prss->dwSize); 57 } 58 59 // bDoubleClick is TRUE if "Double-click to open an item (single-click to select)". 60 // bDoubleClick is FALSE if "Single-click to open an item (point to select)". 61 ////////////////////////////////////////////////////////////////////////////// 62 // API Monitor: 63 // SHLWAPI.dll RegOpenKeyExW ( 0x000000c8, NULL, 0, MAXIMUM_ALLOWED, 0x00def234 ) ERROR_SUCCESS 0.0000243 64 // SHLWAPI.dll RegSetValueExW ( 0x000003e8, "ShellState", 0, REG_BINARY, 0x000c2050, 36 ) ERROR_SUCCESS 0.0001028 65 // SHLWAPI.dll RegCloseKey ( 0x000003e8 ) ERROR_SUCCESS 0.0000081 66 // Explorer.EXE SHSettingsChanged ( 0, "ShellState" ) 0.0000131 67 static BOOL 68 IntSetShellStateSettings(BOOL bDoubleClick, BOOL bUseCommonTasks) 69 { 70 SHELLSTATE shellstate; 71 shellstate.fDoubleClickInWebView = !!bDoubleClick; 72 shellstate.fWebView = !!bUseCommonTasks; 73 SHGetSetSettings(&shellstate, SSF_DOUBLECLICKINWEBVIEW | SSF_WEBVIEW, TRUE); 74 75 SHSettingsChanged(0, L"ShellState"); 76 return TRUE; 77 } 78 79 ////////////////////////////////////////////////////////////////////////////// 80 // API Monitor: 81 // SHLWAPI.dll RegOpenKeyExW ( 0x000000c8, NULL, 0, MAXIMUM_ALLOWED, 0x0007e484 ) ERROR_SUCCESS 0.0000388 82 // SHLWAPI.dll RegQueryValueExW ( 0x000005a8, "ShellState", NULL, 0x0007e474, 0x000c2050, 0x0007e4fc ) ERROR_SUCCESS 0.0000271 83 // SHLWAPI.dll RegCloseKey ( 0x000005a8 ) ERROR_SUCCESS 0.0000112 84 EXTERN_C BOOL 85 SHELL32_ReadRegShellState(PREGSHELLSTATE prss) 86 { 87 DWORD dwSize = sizeof(REGSHELLSTATE); 88 LSTATUS err = SHGetValueW(HKEY_CURRENT_USER, s_pszExplorerKey, 89 L"ShellState", NULL, prss, &dwSize); 90 return err == ERROR_SUCCESS && prss->dwSize >= REGSHELLSTATE_SIZE; 91 } 92 93 // bIconUnderline is TRUE if "Underline icon titles only when I point at them". 94 // bIconUnderline is FALSE if "Underline icon titles consistent with my browser". 95 ////////////////////////////////////////////////////////////////////////////// 96 // API Monitor: 97 // SHELL32.dll SHRegGetUSValueW ( "Software\Microsoft\Windows\CurrentVersion\Explorer", "IconUnderline", NULL, 0x00d2f324, 0x00d2f328, FALSE, 0x00d2f32c, 4 ) ERROR_SUCCESS 0.0002484 98 // SHELL32.dll IsDlgButtonChecked ( 0x0005009e, 30104 ) BST_CHECKED 0.0000212 99 // SHELL32.dll SHRegSetUSValueW ( "Software\Microsoft\Windows\CurrentVersion\Explorer", "IconUnderline", 0, 0x00d2f314, 4, 6 ) ERROR_SUCCESS 0.0008300 100 // Explorer.EXE SHSettingsChanged ( 0, "Software\Microsoft\Windows\CurrentVersion\Explorer\IconUnderline" ) 0.0000092 101 static BOOL IntSetUnderlineState(BOOL bIconUnderline) 102 { 103 LSTATUS Status; 104 DWORD dwValue = (bIconUnderline ? 3 : 2), dwSize = sizeof(DWORD); 105 Status = SHRegSetUSValue(s_pszExplorerKey, L"IconUnderline", REG_NONE, 106 &dwValue, dwSize, SHREGSET_FORCE_HKCU | SHREGSET_HKLM); 107 if (Status != ERROR_SUCCESS) 108 return FALSE; 109 110 SHSettingsChanged(0, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\IconUnderline"); 111 return TRUE; 112 } 113 114 static BOOL IntGetUnderlineState(VOID) 115 { 116 DWORD dwValue, dwDefault = 2, dwSize = sizeof(DWORD); 117 SHRegGetUSValue(s_pszExplorerKey, L"IconUnderline", NULL, &dwValue, &dwSize, FALSE, &dwDefault, sizeof(DWORD)); 118 return dwValue == 3; 119 } 120 121 // bNewWindowMode is TRUE if "Open each folder in its own window". 122 // bNewWindowMode is FALSE if "Open each folder in the same window". 123 ////////////////////////////////////////////////////////////////////////////// 124 // API Monitor: 125 // 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 126 // SHELL32.dll RegSetValueExW ( 0x00000854, "Settings", 0, REG_BINARY, 0x0210f170, 12 ) ERROR_SUCCESS 0.0001472 127 // SHELL32.dll RegSetValueExW ( 0x00000854, "FullPath", 0, REG_DWORD, 0x00d2f2ac, 4 ) ERROR_SUCCESS 0.0000168 128 // SHELL32.dll RegCloseKey ( 0x00000854 ) ERROR_SUCCESS 0.0000000 129 static HRESULT IntSetNewWindowMode(BOOL bNewWindowMode) 130 { 131 CABINETSTATE cs; 132 if (!ReadCabinetState(&cs, sizeof(cs))) 133 return E_FAIL; 134 135 BOOL changed = !!cs.fNewWindowMode != !!bNewWindowMode; 136 cs.fNewWindowMode = !!bNewWindowMode; 137 return WriteCabinetState(&cs) ? (changed ? S_OK : S_FALSE) : E_FAIL; 138 } 139 140 static BOOL IntGetNewWindowMode(VOID) 141 { 142 CABINETSTATE cs; 143 if (!ReadCabinetState(&cs, sizeof(cs))) 144 return FALSE; 145 146 return !!cs.fNewWindowMode; 147 } 148 149 ///////////////////////////////////////////////////////////////////////////// 150 // GeneralDlg 151 152 typedef struct GENERAL_DIALOG 153 { 154 HICON hTaskIcon; 155 HICON hFolderIcon; 156 HICON hClickIcon; 157 } GENERAL_DIALOG, *PGENERAL_DIALOG; 158 159 static VOID 160 GeneralDlg_UpdateIcons(HWND hDlg, UINT nCtrlID, PGENERAL_DIALOG pGeneral) 161 { 162 HICON hTaskIcon = NULL, hFolderIcon = NULL, hClickIcon = NULL; 163 LPTSTR lpTaskIconName = NULL, lpFolderIconName = NULL, lpClickIconName = NULL; 164 165 // Show task setting icon. 166 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED) 167 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS); 168 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_CLASSICFOLDERS) == BST_CHECKED) 169 lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS); 170 171 if (lpTaskIconName) 172 { 173 hTaskIcon = (HICON)LoadImage(shell32_hInstance, lpTaskIconName, 174 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 175 if (hTaskIcon) 176 { 177 HWND hwndTaskIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_TASKICON); 178 SendMessage(hwndTaskIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hTaskIcon); 179 } 180 } 181 182 // Show Folder setting icons 183 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED) 184 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW); 185 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_OWNWINDOW) == BST_CHECKED) 186 lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW); 187 188 if (lpFolderIconName) 189 { 190 hFolderIcon = (HICON)LoadImage(shell32_hInstance, lpFolderIconName, 191 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 192 if (hFolderIcon) 193 { 194 HWND hwndFolderIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_FOLDERICON); 195 SendMessage(hwndFolderIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hFolderIcon); 196 } 197 } 198 199 // Show click setting icon 200 if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED) 201 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN); 202 else if (IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_DOUBLECLICK) == BST_CHECKED) 203 lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN); 204 205 if (lpClickIconName) 206 { 207 hClickIcon = (HICON)LoadImage(shell32_hInstance, lpClickIconName, 208 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 209 if (hClickIcon) 210 { 211 HWND hwndClickIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_CLICKICON); 212 SendMessage(hwndClickIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hClickIcon); 213 } 214 } 215 216 // Replace icons 217 if (hTaskIcon) 218 { 219 DestroyIcon(pGeneral->hTaskIcon); 220 pGeneral->hTaskIcon = hTaskIcon; 221 } 222 if (hFolderIcon) 223 { 224 DestroyIcon(pGeneral->hFolderIcon); 225 pGeneral->hFolderIcon = hFolderIcon; 226 } 227 if (hClickIcon) 228 { 229 DestroyIcon(pGeneral->hClickIcon); 230 pGeneral->hClickIcon = hClickIcon; 231 } 232 233 if (nCtrlID == IDC_FOLDER_OPTIONS_SINGLECLICK) 234 { 235 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER), TRUE); 236 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULPOINT), TRUE); 237 } 238 239 if (nCtrlID == IDC_FOLDER_OPTIONS_DOUBLECLICK) 240 { 241 CheckRadioButton(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 242 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULBROWSER), FALSE); 243 EnableWindow(GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_ULPOINT), FALSE); 244 } 245 } 246 247 static void 248 GeneralDlg_StoreToUI(HWND hwndDlg, BOOL bDoubleClick, BOOL bUseCommonTasks, 249 BOOL bUnderline, BOOL bNewWindowMode, PGENERAL_DIALOG pGeneral) 250 { 251 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS), bUseCommonTasks); // FIXME: ROS DefView does not support WebView nor the tasks pane 252 253 if (bUseCommonTasks) 254 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_COMMONTASKS); 255 else 256 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS); 257 258 if (bDoubleClick) 259 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK); 260 else 261 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK, IDC_FOLDER_OPTIONS_DOUBLECLICK, IDC_FOLDER_OPTIONS_SINGLECLICK); 262 263 if (bNewWindowMode) 264 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW); 265 else 266 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW, IDC_FOLDER_OPTIONS_OWNWINDOW, IDC_FOLDER_OPTIONS_SAMEWINDOW); 267 268 if (!bDoubleClick) 269 { 270 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER), TRUE); 271 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT), TRUE); 272 if (bUnderline) 273 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULPOINT); 274 else 275 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 276 } 277 else 278 { 279 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER), FALSE); 280 EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT), FALSE); 281 CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_ULBROWSER, IDC_FOLDER_OPTIONS_ULPOINT, IDC_FOLDER_OPTIONS_ULBROWSER); 282 } 283 } 284 285 static BOOL 286 GeneralDlg_OnInitDialog(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 287 { 288 SHELLSTATE ss; 289 SHGetSetSettings(&ss, SSF_DOUBLECLICKINWEBVIEW | SSF_WEBVIEW, FALSE); 290 BOOL bDoubleClick = !!ss.fDoubleClickInWebView; 291 BOOL bUseCommonTasks = !!ss.fWebView; 292 BOOL bUnderline = IntGetUnderlineState(); 293 BOOL bNewWindowMode = IntGetNewWindowMode(); 294 295 GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderline, bNewWindowMode, pGeneral); 296 GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral); 297 298 return TRUE; 299 } 300 301 static void 302 GeneralDlg_OnRestoreDefaults(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 303 { 304 // default values 305 BOOL bDoubleClick = TRUE; 306 BOOL bUseCommonTasks = TRUE; 307 BOOL bUnderline = FALSE; 308 BOOL bNewWindowMode = (_WIN32_WINNT < _WIN32_WINNT_WIN2K); 309 310 GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderline, bNewWindowMode, pGeneral); 311 GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral); 312 } 313 314 static BOOL 315 GeneralDlg_OnApply(HWND hwndDlg, PGENERAL_DIALOG pGeneral) 316 { 317 BOOL bDoubleClick = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED); 318 BOOL bUseCommonTasks = (IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED); 319 BOOL bUnderline = (IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_ULPOINT) == BST_CHECKED); 320 BOOL bNewWindowMode = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED); 321 322 IntSetUnderlineState(bUnderline); 323 BOOL updateCabinets = IntSetNewWindowMode(bNewWindowMode) == S_OK; 324 IntSetShellStateSettings(bDoubleClick, bUseCommonTasks); 325 if (updateCabinets) 326 PostCabinetMessage(CWM_STATECHANGE, 0, 0); 327 return TRUE; 328 } 329 330 INT_PTR CALLBACK 331 FolderOptionsGeneralDlg( 332 HWND hwndDlg, 333 UINT uMsg, 334 WPARAM wParam, 335 LPARAM lParam) 336 { 337 static GENERAL_DIALOG general; 338 339 switch (uMsg) 340 { 341 case WM_INITDIALOG: 342 general.hTaskIcon = NULL; 343 general.hFolderIcon = NULL; 344 general.hClickIcon = NULL; 345 return GeneralDlg_OnInitDialog(hwndDlg, &general); 346 347 case WM_COMMAND: 348 switch (LOWORD(wParam)) 349 { 350 case IDC_FOLDER_OPTIONS_COMMONTASKS: 351 case IDC_FOLDER_OPTIONS_CLASSICFOLDERS: 352 case IDC_FOLDER_OPTIONS_SAMEWINDOW: 353 case IDC_FOLDER_OPTIONS_OWNWINDOW: 354 case IDC_FOLDER_OPTIONS_SINGLECLICK: 355 case IDC_FOLDER_OPTIONS_DOUBLECLICK: 356 case IDC_FOLDER_OPTIONS_ULBROWSER: 357 case IDC_FOLDER_OPTIONS_ULPOINT: 358 if (HIWORD(wParam) == BN_CLICKED) 359 { 360 GeneralDlg_UpdateIcons(hwndDlg, LOWORD(wParam), &general); 361 362 // Enable the 'Apply' button 363 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 364 } 365 break; 366 case IDC_FOLDER_OPTIONS_RESTORE: 367 if (HIWORD(wParam) == BN_CLICKED) 368 { 369 GeneralDlg_OnRestoreDefaults(hwndDlg, &general); 370 371 // Enable the 'Apply' button 372 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 373 } 374 break; 375 } 376 break; 377 378 case WM_NOTIFY: 379 { 380 LPNMHDR pnmh = (LPNMHDR)lParam; 381 382 switch (pnmh->code) 383 { 384 case PSN_SETACTIVE: 385 break; 386 387 case PSN_APPLY: 388 return GeneralDlg_OnApply(hwndDlg, &general); 389 } 390 break; 391 } 392 393 case WM_DESTROY: 394 DestroyIcon(general.hTaskIcon); 395 DestroyIcon(general.hFolderIcon); 396 DestroyIcon(general.hClickIcon); 397 break; 398 399 default: 400 return FALSE; 401 } 402 return FALSE; 403 } 404