1 // MenuPage.cpp
2
3 #include "StdAfx.h"
4
5 #include "../Common/ZipRegistry.h"
6
7 #include "../../../Windows/DLL.h"
8 #include "../../../Windows/ErrorMsg.h"
9 #include "../../../Windows/FileFind.h"
10
11 #include "../Explorer/ContextMenuFlags.h"
12 #include "../Explorer/RegistryContextMenu.h"
13 #include "../Explorer/resource.h"
14
15 #include "../FileManager/PropertyNameRes.h"
16
17 #include "../GUI/ExtractDialogRes.h"
18
19 #include "FormatUtils.h"
20 #include "HelpUtils.h"
21 #include "LangUtils.h"
22 #include "MenuPage.h"
23 #include "MenuPageRes.h"
24
25
26 using namespace NWindows;
27 using namespace NContextMenuFlags;
28
29 static const UInt32 kLangIDs[] =
30 {
31 IDX_SYSTEM_INTEGRATE_TO_MENU,
32 IDX_SYSTEM_CASCADED_MENU,
33 IDX_SYSTEM_ICON_IN_MENU,
34 IDX_EXTRACT_ELIM_DUP,
35 IDT_SYSTEM_CONTEXT_MENU_ITEMS
36 };
37
38 #define kMenuTopic "fm/options.htm#sevenZip"
39
40 struct CContextMenuItem
41 {
42 int ControlID;
43 UInt32 Flag;
44 };
45
46 static const CContextMenuItem kMenuItems[] =
47 {
48 { IDS_CONTEXT_OPEN, kOpen },
49 { IDS_CONTEXT_OPEN, kOpenAs },
50 { IDS_CONTEXT_EXTRACT, kExtract },
51 { IDS_CONTEXT_EXTRACT_HERE, kExtractHere },
52 { IDS_CONTEXT_EXTRACT_TO, kExtractTo },
53
54 { IDS_CONTEXT_TEST, kTest },
55
56 { IDS_CONTEXT_COMPRESS, kCompress },
57 { IDS_CONTEXT_COMPRESS_TO, kCompressTo7z },
58 { IDS_CONTEXT_COMPRESS_TO, kCompressToZip },
59
60 #ifndef UNDER_CE
61 { IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail },
62 { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail },
63 { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail },
64 #endif
65
66 { IDS_PROP_CHECKSUM, kCRC }
67 };
68
69
70 #if !defined(_WIN64)
71 extern bool g_Is_Wow64;
72 #endif
73
74 #ifndef KEY_WOW64_64KEY
75 #define KEY_WOW64_64KEY (0x0100)
76 #endif
77
78 #ifndef KEY_WOW64_32KEY
79 #define KEY_WOW64_32KEY (0x0200)
80 #endif
81
OnInit()82 bool CMenuPage::OnInit()
83 {
84 _initMode = true;
85
86 Clear_MenuChanged();
87
88 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
89
90 #ifdef UNDER_CE
91
92 HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU);
93 HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU_2);
94
95 #else
96
97 {
98 UString s;
99 {
100 CWindow window(GetItem(IDX_SYSTEM_INTEGRATE_TO_MENU));
101 window.GetText(s);
102 }
103 UString bit64 = LangString(IDS_PROP_BIT64);
104 if (bit64.IsEmpty())
105 bit64 = "64-bit";
106 #ifdef _WIN64
107 bit64.Replace(L"64", L"32");
108 #endif
109 s.Add_Space();
110 s += '(';
111 s += bit64;
112 s += ')';
113 SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s);
114 }
115
116 const FString prefix = NDLL::GetModuleDirPrefix();
117
118 _dlls[0].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU;
119 _dlls[1].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU_2;
120
121 _dlls[0].wow = 0;
122 _dlls[1].wow =
123 #ifdef _WIN64
124 KEY_WOW64_32KEY
125 #else
126 KEY_WOW64_64KEY
127 #endif
128 ;
129
130 for (unsigned d = 0; d < 2; d++)
131 {
132 CShellDll &dll = _dlls[d];
133
134 dll.wasChanged = false;
135
136 #ifndef _WIN64
137 if (d != 0 && !g_Is_Wow64)
138 {
139 HideItem(dll.ctrl);
140 continue;
141 }
142 #endif
143
144 FString &path = dll.Path;
145 path = prefix;
146 path += (d == 0 ? "7-zip.dll" :
147 #ifdef _WIN64
148 "7-zip32.dll"
149 #else
150 "7-zip64.dll"
151 #endif
152 );
153
154
155 if (!NFile::NFind::DoesFileExist(path))
156 {
157 path.Empty();
158 EnableItem(dll.ctrl, false);
159 }
160 else
161 {
162 dll.prevValue = CheckContextMenuHandler(fs2us(path), dll.wow);
163 CheckButton(dll.ctrl, dll.prevValue);
164 }
165 }
166
167 #endif
168
169
170 CContextMenuInfo ci;
171 ci.Load();
172
173 CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded.Val);
174 CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons.Val);
175 CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val);
176
177 _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS));
178
179 const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;
180 _listView.SetExtendedListViewStyle(newFlags, newFlags);
181
182 _listView.InsertColumn(0, L"", 200);
183
184 for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
185 {
186 const CContextMenuItem &menuItem = kMenuItems[i];
187
188 UString s = LangString(menuItem.ControlID);
189 if (menuItem.Flag == kCRC)
190 s = "CRC SHA";
191 if (menuItem.Flag == kOpenAs ||
192 menuItem.Flag == kCRC)
193 s += " >";
194
195 switch (menuItem.ControlID)
196 {
197 case IDS_CONTEXT_EXTRACT_TO:
198 {
199 s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER));
200 break;
201 }
202 case IDS_CONTEXT_COMPRESS_TO:
203 case IDS_CONTEXT_COMPRESS_TO_EMAIL:
204 {
205 UString s2 = LangString(IDS_CONTEXT_ARCHIVE);
206 switch (menuItem.Flag)
207 {
208 case kCompressTo7z:
209 case kCompressTo7zEmail:
210 s2 += (".7z");
211 break;
212 case kCompressToZip:
213 case kCompressToZipEmail:
214 s2 += (".zip");
215 break;
216 }
217 s = MyFormatNew(s, s2);
218 break;
219 }
220 }
221
222 int itemIndex = _listView.InsertItem(i, s);
223 _listView.SetCheckState(itemIndex, ((ci.Flags & menuItem.Flag) != 0));
224 }
225
226 _listView.SetColumnWidthAuto(0);
227 _initMode = false;
228
229 return CPropertyPage::OnInit();
230 }
231
232
233 #ifndef UNDER_CE
234
ShowMenuErrorMessage(const wchar_t * m,HWND hwnd)235 static void ShowMenuErrorMessage(const wchar_t *m, HWND hwnd)
236 {
237 MessageBoxW(hwnd, m, L"7-Zip", MB_ICONERROR);
238 }
239
240 #endif
241
242
OnApply()243 LONG CMenuPage::OnApply()
244 {
245 #ifndef UNDER_CE
246
247 for (unsigned d = 2; d != 0;)
248 {
249 d--;
250 CShellDll &dll = _dlls[d];
251 if (dll.wasChanged && !dll.Path.IsEmpty())
252 {
253 bool newVal = IsButtonCheckedBool(dll.ctrl);
254 LONG res = SetContextMenuHandler(newVal, fs2us(dll.Path), dll.wow);
255 if (res != ERROR_SUCCESS && (dll.prevValue != newVal || newVal))
256 ShowMenuErrorMessage(NError::MyFormatMessage(res), *this);
257 dll.prevValue = CheckContextMenuHandler(fs2us(dll.Path), dll.wow);
258 CheckButton(dll.ctrl, dll.prevValue);
259 dll.wasChanged = false;
260 }
261 }
262
263 #endif
264
265 if (_cascaded_Changed || _menuIcons_Changed || _elimDup_Changed || _flags_Changed)
266 {
267 CContextMenuInfo ci;
268 ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU);
269 ci.Cascaded.Def = _cascaded_Changed;
270
271 ci.MenuIcons.Val = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU);
272 ci.MenuIcons.Def = _menuIcons_Changed;
273
274 ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);
275 ci.ElimDup.Def = _elimDup_Changed;
276
277 ci.Flags = 0;
278
279 for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
280 if (_listView.GetCheckState(i))
281 ci.Flags |= kMenuItems[i].Flag;
282
283 ci.Flags_Def = _flags_Changed;
284 ci.Save();
285
286 Clear_MenuChanged();
287 }
288
289 // UnChanged();
290
291 return PSNRET_NOERROR;
292 }
293
OnNotifyHelp()294 void CMenuPage::OnNotifyHelp()
295 {
296 ShowHelpWindow(kMenuTopic);
297 }
298
OnButtonClicked(int buttonID,HWND buttonHWND)299 bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND)
300 {
301 switch (buttonID)
302 {
303 #ifndef UNDER_CE
304 case IDX_SYSTEM_INTEGRATE_TO_MENU:
305 case IDX_SYSTEM_INTEGRATE_TO_MENU_2:
306 {
307 for (unsigned d = 0; d < 2; d++)
308 {
309 CShellDll &dll = _dlls[d];
310 if (buttonID == dll.ctrl && !dll.Path.IsEmpty())
311 dll.wasChanged = true;
312 }
313 break;
314 }
315 #endif
316
317 case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break;
318 case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break;
319 case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break;
320
321 default:
322 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
323 }
324
325 Changed();
326 return true;
327 }
328
OnNotify(UINT controlID,LPNMHDR lParam)329 bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam)
330 {
331 if (lParam->hwndFrom == HWND(_listView))
332 {
333 switch (lParam->code)
334 {
335 case (LVN_ITEMCHANGED):
336 return OnItemChanged((const NMLISTVIEW *)lParam);
337 }
338 }
339 return CPropertyPage::OnNotify(controlID, lParam);
340 }
341
342
OnItemChanged(const NMLISTVIEW * info)343 bool CMenuPage::OnItemChanged(const NMLISTVIEW *info)
344 {
345 if (_initMode)
346 return true;
347 if ((info->uChanged & LVIF_STATE) != 0)
348 {
349 UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;
350 UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;
351 if (oldState != newState)
352 {
353 _flags_Changed = true;
354 Changed();
355 }
356 }
357 return true;
358 }
359