Reactos
1/*
2 * 'View' 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 inline CFolderOptions*
27GetFolderOptions(HWND hwndDlg)
28{
29 return (CFolderOptions*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
30}
31
32static inline IRegTreeOptions*
33GetRegTreeOptions(HWND hwndDlg)
34{
35 return (IRegTreeOptions*)GetWindowLongPtr(hwndDlg, DWLP_USER);
36}
37
38static void
39ViewDlg_OnDestroy(HWND hwndDlg)
40{
41 if (IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg))
42 {
43 pRTO->WalkTree(WALK_TREE_DESTROY);
44 pRTO->Release();
45 SetWindowLongPtr(hwndDlg, DWLP_USER, 0);
46 }
47}
48
49static BOOL
50ViewDlg_OnInitDialog(HWND hwndDlg, LPPROPSHEETPAGE psp)
51{
52 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, psp->lParam);
53 CFolderOptions *pFO = (CFolderOptions*)psp->lParam;
54
55 if (!pFO || !pFO->CanSetDefFolderSettings())
56 {
57 // The global options (started from rundll32 or control panel)
58 // has no browser to copy the current settings from.
59 EnableWindow(GetDlgItem(hwndDlg, IDC_VIEW_APPLY_TO_ALL), FALSE);
60 }
61
62 IRegTreeOptions *pRTO = NULL;
63 if (SUCCEEDED(SHCoCreateInstance(NULL, &CLSID_CRegTreeOptions, NULL, IID_PPV_ARG(IRegTreeOptions, &pRTO))))
64 {
65 SetWindowLongPtr(hwndDlg, DWLP_USER, (LPARAM)pRTO);
66
67 CHAR apath[MAX_PATH];
68 SHUnicodeToAnsi(REGSTR_PATH_EXPLORER L"\\Advanced", apath, _countof(apath));
69 HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
70 pRTO->InitTree(hwndTreeView, HKEY_LOCAL_MACHINE, apath, NULL);
71 }
72
73 return TRUE; // Set focus
74}
75
76static BOOL
77ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem)
78{
79 IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg);
80 return pRTO && SUCCEEDED(pRTO->ToggleItem(hItem));
81}
82
83static VOID
84ViewDlg_OnTreeViewClick(HWND hwndDlg)
85{
86 HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
87
88 // do hit test to get the clicked item
89 TV_HITTESTINFO HitTest;
90 ZeroMemory(&HitTest, sizeof(HitTest));
91 DWORD dwPos = GetMessagePos();
92 HitTest.pt.x = GET_X_LPARAM(dwPos);
93 HitTest.pt.y = GET_Y_LPARAM(dwPos);
94 ScreenToClient(hwndTreeView, &HitTest.pt);
95 HTREEITEM hItem = TreeView_HitTest(hwndTreeView, &HitTest);
96
97 // toggle the check mark if possible
98 if (ViewDlg_ToggleCheckItem(hwndDlg, hItem))
99 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
100}
101
102static void
103ViewDlg_OnTreeViewKeyDown(HWND hwndDlg, TV_KEYDOWN *KeyDown)
104{
105 HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW);
106
107 if (KeyDown->wVKey == VK_SPACE)
108 {
109 HTREEITEM hItem = TreeView_GetSelection(hwndTreeView);
110 if (ViewDlg_ToggleCheckItem(hwndDlg, hItem))
111 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
112 }
113 else if (KeyDown->wVKey == VK_F5)
114 {
115 IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg);
116 if (pRTO)
117 pRTO->WalkTree(WALK_TREE_REFRESH);
118 }
119}
120
121static INT_PTR
122ViewDlg_OnTreeCustomDraw(HWND hwndDlg, NMTVCUSTOMDRAW *Draw)
123{
124 NMCUSTOMDRAW& nmcd = Draw->nmcd;
125 switch (nmcd.dwDrawStage)
126 {
127 case CDDS_PREPAINT:
128 return CDRF_NOTIFYITEMDRAW; // for CDDS_ITEMPREPAINT
129
130 case CDDS_ITEMPREPAINT:
131 if (!(nmcd.uItemState & CDIS_SELECTED)) // not selected
132 {
133 LPARAM lParam = nmcd.lItemlParam;
134 if ((HKEY)lParam == HKEY_REGTREEOPTION_GRAYED) // disabled
135 {
136 // draw as grayed
137 Draw->clrText = GetSysColor(COLOR_GRAYTEXT);
138 Draw->clrTextBk = GetSysColor(COLOR_WINDOW);
139 return CDRF_NEWFONT;
140 }
141 }
142 break;
143
144 default:
145 break;
146 }
147 return CDRF_DODEFAULT;
148}
149
150static VOID
151ViewDlg_RestoreDefaults(HWND hwndDlg)
152{
153 if (IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg))
154 {
155 pRTO->WalkTree(WALK_TREE_DEFAULT);
156 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
157 }
158}
159
160static BOOL CALLBACK
161PostCabinetMessageCallback(HWND hWnd, LPARAM param)
162{
163 MSG &data = *(MSG*)param;
164 WCHAR ClassName[100];
165 if (GetClassNameW(hWnd, ClassName, _countof(ClassName)))
166 {
167 if (!wcscmp(ClassName, L"Progman") ||
168 !wcscmp(ClassName, L"CabinetWClass") ||
169 !wcscmp(ClassName, L"ExploreWClass"))
170 {
171 PostMessage(hWnd, data.message, data.wParam, data.lParam);
172 }
173 }
174 return TRUE;
175}
176
177void
178PostCabinetMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
179{
180 MSG data;
181 data.message = Msg;
182 data.wParam = wParam;
183 data.lParam = lParam;
184 EnumWindows(PostCabinetMessageCallback, (LPARAM)&data);
185}
186
187static VOID
188ViewDlg_Apply(HWND hwndDlg)
189{
190 IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg);
191 if (!pRTO || FAILED(pRTO->WalkTree(WALK_TREE_SAVE)))
192 return;
193
194 SHSettingsChanged(0, 0); // Invalidate restrictions
195 SHGetSetSettings(NULL, 0, TRUE); // Invalidate SHELLSTATE
196
197 CABINETSTATE cs;
198 cs.cLength = sizeof(cs);
199 if (ReadCabinetState(&cs, sizeof(cs)))
200 WriteCabinetState(&cs); // Write the settings and invalidate global counter
201
202 SHSendMessageBroadcastW(WM_SETTINGCHANGE, 0, 0);
203 PostCabinetMessage(WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0);
204}
205
206// IDD_FOLDER_OPTIONS_VIEW
207INT_PTR CALLBACK
208FolderOptionsViewDlg(
209 HWND hwndDlg,
210 UINT uMsg,
211 WPARAM wParam,
212 LPARAM lParam)
213{
214 INT_PTR Result;
215
216 switch (uMsg)
217 {
218 case WM_INITDIALOG:
219 return ViewDlg_OnInitDialog(hwndDlg, (LPPROPSHEETPAGE)lParam);
220
221 case WM_DESTROY:
222 ViewDlg_OnDestroy(hwndDlg);
223 break;
224
225 case WM_COMMAND:
226 switch (LOWORD(wParam))
227 {
228 case IDC_VIEW_RESTORE_DEFAULTS: // Restore Defaults
229 ViewDlg_RestoreDefaults(hwndDlg);
230 break;
231
232 case IDC_VIEW_APPLY_TO_ALL:
233 case IDC_VIEW_RESET_ALL:
234 {
235 HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
236 bool ResetToDefault = LOWORD(wParam) == IDC_VIEW_RESET_ALL;
237 CFolderOptions *pFO = GetFolderOptions(hwndDlg);
238 if (pFO)
239 hr = pFO->ApplyDefFolderSettings(ResetToDefault); // Use IBrowserService2
240 if (ResetToDefault && hr == HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED))
241 hr = CFolderOptions::ResetGlobalAndDefViewFolderSettings(); // No browser
242 if (FAILED(hr))
243 SHELL_ErrorBox(hwndDlg, hr);
244 break;
245 }
246 }
247 break;
248
249 case WM_NOTIFY:
250 switch (LPNMHDR(lParam)->code)
251 {
252 case NM_CLICK: // clicked on treeview
253 ViewDlg_OnTreeViewClick(hwndDlg);
254 break;
255
256 case NM_CUSTOMDRAW: // custom draw (for graying)
257 Result = ViewDlg_OnTreeCustomDraw(hwndDlg, (NMTVCUSTOMDRAW*)lParam);
258 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, Result);
259 return Result;
260
261 case TVN_KEYDOWN: // key is down
262 ViewDlg_OnTreeViewKeyDown(hwndDlg, (TV_KEYDOWN *)lParam);
263 break;
264
265 case PSN_APPLY: // [Apply] is clicked
266 ViewDlg_Apply(hwndDlg);
267 break;
268
269 default:
270 break;
271 }
272 break;
273 }
274
275 return FALSE;
276}