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 #ifdef Z7_LANG
30 static const UInt32 kLangIDs[] =
31 {
32 IDX_SYSTEM_INTEGRATE_TO_MENU,
33 IDX_SYSTEM_CASCADED_MENU,
34 IDX_SYSTEM_ICON_IN_MENU,
35 IDX_EXTRACT_ELIM_DUP,
36 IDT_SYSTEM_ZONE,
37 IDT_SYSTEM_CONTEXT_MENU_ITEMS
38 };
39 #endif
40
41 #define kMenuTopic "fm/options.htm#sevenZip"
42
43 struct CContextMenuItem
44 {
45 unsigned ControlID;
46 UInt32 Flag;
47 };
48
49 static const CContextMenuItem kMenuItems[] =
50 {
51 { IDS_CONTEXT_OPEN, kOpen },
52 { IDS_CONTEXT_OPEN, kOpenAs },
53 { IDS_CONTEXT_EXTRACT, kExtract },
54 { IDS_CONTEXT_EXTRACT_HERE, kExtractHere },
55 { IDS_CONTEXT_EXTRACT_TO, kExtractTo },
56
57 { IDS_CONTEXT_TEST, kTest },
58
59 { IDS_CONTEXT_COMPRESS, kCompress },
60 { IDS_CONTEXT_COMPRESS_TO, kCompressTo7z },
61 { IDS_CONTEXT_COMPRESS_TO, kCompressToZip },
62
63 #ifndef UNDER_CE
64 { IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail },
65 { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail },
66 { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail },
67 #endif
68
69 { IDS_PROP_CHECKSUM, kCRC },
70 { IDS_PROP_CHECKSUM, kCRC_Cascaded },
71 };
72
73
74 #if !defined(_WIN64)
75 extern bool g_Is_Wow64;
76 #endif
77
78 #ifndef KEY_WOW64_64KEY
79 #define KEY_WOW64_64KEY (0x0100)
80 #endif
81
82 #ifndef KEY_WOW64_32KEY
83 #define KEY_WOW64_32KEY (0x0200)
84 #endif
85
86
LoadLang_Spec(UString & s,UInt32 id,const char * eng)87 static void LoadLang_Spec(UString &s, UInt32 id, const char *eng)
88 {
89 LangString(id, s);
90 if (s.IsEmpty())
91 s = eng;
92 s.RemoveChar(L'&');
93 }
94
95
OnInit()96 bool CMenuPage::OnInit()
97 {
98 _initMode = true;
99
100 Clear_MenuChanged();
101
102 #ifdef Z7_LANG
103 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
104 #endif
105
106 #ifdef UNDER_CE
107
108 HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU);
109 HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU_2);
110
111 #else
112
113 {
114 UString s;
115 {
116 CWindow window(GetItem(IDX_SYSTEM_INTEGRATE_TO_MENU));
117 window.GetText(s);
118 }
119 UString bit64 = LangString(IDS_PROP_BIT64);
120 if (bit64.IsEmpty())
121 bit64 = "64-bit";
122 #ifdef _WIN64
123 bit64.Replace(L"64", L"32");
124 #endif
125 s.Add_Space();
126 s.Add_Char('(');
127 s += bit64;
128 s.Add_Char(')');
129 SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s);
130 }
131
132 const FString prefix = NDLL::GetModuleDirPrefix();
133
134 _dlls[0].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU;
135 _dlls[1].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU_2;
136
137 _dlls[0].wow = 0;
138 _dlls[1].wow =
139 #ifdef _WIN64
140 KEY_WOW64_32KEY
141 #else
142 KEY_WOW64_64KEY
143 #endif
144 ;
145
146 for (unsigned d = 0; d < 2; d++)
147 {
148 CShellDll &dll = _dlls[d];
149
150 dll.wasChanged = false;
151
152 #ifndef _WIN64
153 if (d != 0 && !g_Is_Wow64)
154 {
155 HideItem(dll.ctrl);
156 continue;
157 }
158 #endif
159
160 FString &path = dll.Path;
161 path = prefix;
162 path += (d == 0 ? "7-zip.dll" :
163 #ifdef _WIN64
164 "7-zip32.dll"
165 #else
166 "7-zip64.dll"
167 #endif
168 );
169
170
171 if (!NFile::NFind::DoesFileExist_Raw(path))
172 {
173 path.Empty();
174 EnableItem(dll.ctrl, false);
175 }
176 else
177 {
178 dll.prevValue = CheckContextMenuHandler(fs2us(path), dll.wow);
179 CheckButton(dll.ctrl, dll.prevValue);
180 }
181 }
182
183 #endif
184
185
186 CContextMenuInfo ci;
187 ci.Load();
188
189 CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded.Val);
190 CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons.Val);
191 CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val);
192
193 _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS));
194 _zoneCombo.Attach(GetItem(IDC_SYSTEM_ZONE));
195
196 {
197 unsigned wz = ci.WriteZone;
198 if (wz == (UInt32)(Int32)-1)
199 wz = 0;
200 for (unsigned i = 0; i <= 3; i++)
201 {
202 unsigned val = i;
203 UString s;
204 if (i == 3)
205 {
206 if (wz < 3)
207 break;
208 val = wz;
209 }
210 else
211 {
212 #define MY_IDYES 406
213 #define MY_IDNO 407
214 if (i == 0)
215 LoadLang_Spec(s, MY_IDNO, "No");
216 else if (i == 1)
217 LoadLang_Spec(s, MY_IDYES, "Yes");
218 else
219 LangString(IDT_ZONE_FOR_OFFICE, s);
220 }
221 if (s.IsEmpty())
222 s.Add_UInt32(val);
223 if (i == 0)
224 s.Insert(0, L"* ");
225 const int index = (int)_zoneCombo.AddString(s);
226 _zoneCombo.SetItemData(index, (LPARAM)val);
227 if (val == wz)
228 _zoneCombo.SetCurSel(index);
229 }
230 }
231
232
233 const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;
234 _listView.SetExtendedListViewStyle(newFlags, newFlags);
235
236 _listView.InsertColumn(0, L"", 200);
237
238 for (unsigned i = 0; i < Z7_ARRAY_SIZE(kMenuItems); i++)
239 {
240 const CContextMenuItem &menuItem = kMenuItems[i];
241
242 UString s = LangString(menuItem.ControlID);
243 if (menuItem.Flag == kCRC)
244 s = "CRC SHA";
245 else if (menuItem.Flag == kCRC_Cascaded)
246 s = "7-Zip > CRC SHA";
247 if (menuItem.Flag == kOpenAs
248 || menuItem.Flag == kCRC
249 || menuItem.Flag == kCRC_Cascaded)
250 s += " >";
251
252 switch (menuItem.ControlID)
253 {
254 case IDS_CONTEXT_EXTRACT_TO:
255 {
256 s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER));
257 break;
258 }
259 case IDS_CONTEXT_COMPRESS_TO:
260 case IDS_CONTEXT_COMPRESS_TO_EMAIL:
261 {
262 UString s2 = LangString(IDS_CONTEXT_ARCHIVE);
263 switch (menuItem.Flag)
264 {
265 case kCompressTo7z:
266 case kCompressTo7zEmail:
267 s2 += (".7z");
268 break;
269 case kCompressToZip:
270 case kCompressToZipEmail:
271 s2 += (".zip");
272 break;
273 }
274 s = MyFormatNew(s, s2);
275 break;
276 }
277 }
278
279 const int itemIndex = _listView.InsertItem(i, s);
280 _listView.SetCheckState((unsigned)itemIndex, ((ci.Flags & menuItem.Flag) != 0));
281 }
282
283 _listView.SetColumnWidthAuto(0);
284 _initMode = false;
285
286 return CPropertyPage::OnInit();
287 }
288
289
290 #ifndef UNDER_CE
291
ShowMenuErrorMessage(const wchar_t * m,HWND hwnd)292 static void ShowMenuErrorMessage(const wchar_t *m, HWND hwnd)
293 {
294 MessageBoxW(hwnd, m, L"7-Zip", MB_ICONERROR);
295 }
296
297 #endif
298
299
OnApply()300 LONG CMenuPage::OnApply()
301 {
302 #ifndef UNDER_CE
303
304 for (unsigned d = 2; d != 0;)
305 {
306 d--;
307 CShellDll &dll = _dlls[d];
308 if (dll.wasChanged && !dll.Path.IsEmpty())
309 {
310 const bool newVal = IsButtonCheckedBool(dll.ctrl);
311 const LONG res = SetContextMenuHandler(newVal, fs2us(dll.Path), dll.wow);
312 if (res != ERROR_SUCCESS && (dll.prevValue != newVal || newVal))
313 ShowMenuErrorMessage(NError::MyFormatMessage(res), *this);
314 dll.prevValue = CheckContextMenuHandler(fs2us(dll.Path), dll.wow);
315 CheckButton(dll.ctrl, dll.prevValue);
316 dll.wasChanged = false;
317 }
318 }
319
320 #endif
321
322 if (_cascaded_Changed
323 || _menuIcons_Changed
324 || _elimDup_Changed
325 || _writeZone_Changed
326 || _flags_Changed)
327 {
328 CContextMenuInfo ci;
329 ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU);
330 ci.Cascaded.Def = _cascaded_Changed;
331
332 ci.MenuIcons.Val = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU);
333 ci.MenuIcons.Def = _menuIcons_Changed;
334
335 ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);
336 ci.ElimDup.Def = _elimDup_Changed;
337
338 {
339 int zoneIndex = (int)_zoneCombo.GetItemData_of_CurSel();
340 if (zoneIndex <= 0)
341 zoneIndex = -1;
342 ci.WriteZone = (UInt32)(Int32)zoneIndex;
343 }
344
345 ci.Flags = 0;
346
347 for (unsigned i = 0; i < Z7_ARRAY_SIZE(kMenuItems); i++)
348 if (_listView.GetCheckState(i))
349 ci.Flags |= kMenuItems[i].Flag;
350
351 ci.Flags_Def = _flags_Changed;
352 ci.Save();
353
354 Clear_MenuChanged();
355 }
356
357 // UnChanged();
358
359 return PSNRET_NOERROR;
360 }
361
OnNotifyHelp()362 void CMenuPage::OnNotifyHelp()
363 {
364 ShowHelpWindow(kMenuTopic);
365 }
366
OnButtonClicked(unsigned buttonID,HWND buttonHWND)367 bool CMenuPage::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
368 {
369 switch (buttonID)
370 {
371 #ifndef UNDER_CE
372 case IDX_SYSTEM_INTEGRATE_TO_MENU:
373 case IDX_SYSTEM_INTEGRATE_TO_MENU_2:
374 {
375 for (unsigned d = 0; d < 2; d++)
376 {
377 CShellDll &dll = _dlls[d];
378 if (buttonID == dll.ctrl && !dll.Path.IsEmpty())
379 dll.wasChanged = true;
380 }
381 break;
382 }
383 #endif
384
385 case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break;
386 case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break;
387 case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break;
388 // case IDX_EXTRACT_WRITE_ZONE: _writeZone_Changed = true; break;
389
390 default:
391 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
392 }
393
394 Changed();
395 return true;
396 }
397
398
OnCommand(unsigned code,unsigned itemID,LPARAM param)399 bool CMenuPage::OnCommand(unsigned code, unsigned itemID, LPARAM param)
400 {
401 if (code == CBN_SELCHANGE && itemID == IDC_SYSTEM_ZONE)
402 {
403 _writeZone_Changed = true;
404 Changed();
405 return true;
406 }
407 return CPropertyPage::OnCommand(code, itemID, param);
408 }
409
410
OnNotify(UINT controlID,LPNMHDR lParam)411 bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam)
412 {
413 if (lParam->hwndFrom == HWND(_listView))
414 {
415 switch (lParam->code)
416 {
417 case (LVN_ITEMCHANGED):
418 return OnItemChanged((const NMLISTVIEW *)lParam);
419 }
420 }
421 return CPropertyPage::OnNotify(controlID, lParam);
422 }
423
424
OnItemChanged(const NMLISTVIEW * info)425 bool CMenuPage::OnItemChanged(const NMLISTVIEW *info)
426 {
427 if (_initMode)
428 return true;
429 if ((info->uChanged & LVIF_STATE) != 0)
430 {
431 UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;
432 UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;
433 if (oldState != newState)
434 {
435 _flags_Changed = true;
436 Changed();
437 }
438 }
439 return true;
440 }
441