5 #include <Windowsx.h>
\r
7 #include "Common/Defs.h"
\r
8 #include "Common/IntToString.h"
\r
9 #include "Common/StringConvert.h"
\r
11 #include "Windows/Error.h"
\r
12 #include "Windows/PropVariant.h"
\r
13 #include "Windows/Thread.h"
\r
15 #include "../../PropID.h"
\r
17 #include "resource.h"
\r
18 #include "../GUI/ExtractRes.h"
\r
20 #include "../Common/ArchiveName.h"
\r
21 #include "../Common/CompressCall.h"
\r
23 #include "../Agent/IFolderArchive.h"
\r
26 #include "ExtractCallback.h"
\r
27 #include "FSFolder.h"
\r
28 #include "FormatUtils.h"
\r
30 #include "RootFolder.h"
\r
33 using namespace NWindows;
\r
34 using namespace NControl;
\r
40 static const UINT_PTR kTimerID = 1;
\r
41 static const UINT kTimerElapse = 1000;
\r
43 static DWORD kStyles[4] = { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT };
\r
45 // static const int kCreateFolderID = 101;
\r
46 // static const UINT kFileChangeNotifyMessage = WM_APP;
\r
48 extern HINSTANCE g_hInstance;
\r
49 extern DWORD g_ComCtl32Version;
\r
51 void CPanel::Release()
\r
53 // It's for unloading COM dll's: don't change it.
\r
55 _sevenZipContextMenu.Release();
\r
56 _systemContextMenu.Release();
\r
64 HWND CPanel::GetParent()
\r
66 HWND h = CWindow2::GetParent();
\r
67 return (h == 0) ? _mainWindow : h;
\r
70 static LPCWSTR kClassName = L"7-Zip::Panel";
\r
73 HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id,
\r
74 const UString ¤tFolderPrefix,
\r
75 const UString &arcFormat,
\r
76 CPanelCallback *panelCallback, CAppState *appState,
\r
77 bool &archiveIsOpened, bool &encrypted)
\r
79 _mainWindow = mainWindow;
\r
80 _processTimer = true;
\r
81 _processNotify = true;
\r
83 _panelCallback = panelCallback;
\r
84 _appState = appState;
\r
87 _comboBoxID = _baseID + 3;
\r
88 _statusBarID = _comboBoxID + 1;
\r
90 UString cfp = currentFolderPrefix;
\r
92 if (!currentFolderPrefix.IsEmpty())
\r
93 if (currentFolderPrefix[0] == L'.')
\r
94 if (!NFile::NDirectory::MyGetFullPathName(currentFolderPrefix, cfp))
\r
95 cfp = currentFolderPrefix;
\r
96 RINOK(BindToPath(cfp, arcFormat, archiveIsOpened, encrypted));
\r
98 if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE,
\r
100 parentWindow, (HMENU)(UINT_PTR)id, g_hInstance))
\r
105 LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
\r
109 case kShiftSelectMessage:
\r
110 OnShiftSelectMessage();
\r
112 case kReLoadMessage:
\r
113 RefreshListCtrl(_selectedState);
\r
115 case kSetFocusToListView:
\r
116 _listView.SetFocus();
\r
118 case kOpenItemChanged:
\r
119 return OnOpenItemChanged(lParam);
\r
120 case kRefreshStatusBar:
\r
121 OnRefreshStatusBar();
\r
123 case kRefreshHeaderComboBox:
\r
124 LoadFullPathAndShow();
\r
129 case WM_CONTEXTMENU:
\r
130 if (OnContextMenu(HANDLE(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))
\r
135 CompressDropFiles(HDROP(wParam));
\r
139 return CWindow2::OnMessage(message, wParam, lParam);
\r
142 static LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
144 CWindow tempDialog(hwnd);
\r
145 CMyListView *w = (CMyListView *)(tempDialog.GetUserDataLongPtr());
\r
148 return w->OnMessage(message, wParam, lParam);
\r
151 LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
\r
153 if (message == WM_CHAR)
\r
155 UINT scanCode = (UINT)((lParam >> 16) & 0xFF);
\r
156 bool extended = ((lParam & 0x1000000) != 0);
\r
157 UINT virtualKey = MapVirtualKey(scanCode, 1);
\r
158 if (virtualKey == VK_MULTIPLY || virtualKey == VK_ADD ||
\r
159 virtualKey == VK_SUBTRACT)
\r
161 if ((wParam == '/' && extended)
\r
162 || wParam == '\\' || wParam == '/')
\r
164 _panel->OpenDrivesFolder();
\r
168 else if (message == WM_SYSCHAR)
\r
170 // For Alt+Enter Beep disabling
\r
171 UINT scanCode = (UINT)(lParam >> 16) & 0xFF;
\r
172 UINT virtualKey = MapVirtualKey(scanCode, 1);
\r
173 if (virtualKey == VK_RETURN || virtualKey == VK_MULTIPLY ||
\r
174 virtualKey == VK_ADD || virtualKey == VK_SUBTRACT)
\r
178 else if (message == WM_SYSKEYDOWN)
\r
183 else if (message == WM_KEYDOWN)
\r
185 bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
\r
186 bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
\r
187 // bool leftCtrl = (::GetKeyState(VK_LCONTROL) & 0x8000) != 0;
\r
188 // bool RightCtrl = (::GetKeyState(VK_RCONTROL) & 0x8000) != 0;
\r
189 bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
\r
195 if (shift && !alt && !ctrl)
\r
197 _panel->OpenSelectedItems(false);
\r
205 if (ctrl && !alt && !shift)
\r
207 _panel->OpenFocusedItemAsInternal();
\r
213 if (ctrl && !alt && !shift)
\r
215 _panel->OpenParentFolder();
\r
221 else if (message == WM_KEYUP)
\r
223 if (wParam == VK_F2) // it's VK_TSOFT2
\r
226 ::PostMessage(g_HWND, WM_SYSCOMMAND, SC_KEYMENU, 0);
\r
231 else if (message == WM_SETFOCUS)
\r
233 _panel->_lastFocusedIsList = true;
\r
234 _panel->_panelCallback->PanelWasFocused();
\r
238 return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);
\r
241 return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);
\r
245 static LRESULT APIENTRY ComboBoxSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
247 CWindow tempDialog(hwnd);
\r
248 CMyComboBox *w = (CMyComboBox *)(tempDialog.GetUserDataLongPtr());
\r
251 return w->OnMessage(message, wParam, lParam);
\r
254 LRESULT CMyComboBox::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
\r
256 return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);
\r
259 static LRESULT APIENTRY ComboBoxEditSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
261 CWindow tempDialog(hwnd);
\r
262 CMyComboBoxEdit *w = (CMyComboBoxEdit *)(tempDialog.GetUserDataLongPtr());
\r
265 return w->OnMessage(message, wParam, lParam);
\r
268 LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
\r
270 // See MSDN / Subclassing a Combo Box / Creating a Combo-box Toolbar
\r
273 case WM_SYSKEYDOWN:
\r
280 if ((lParam & (1<<29)) == 0)
\r
282 bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
\r
283 bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
\r
284 bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
\r
285 if (alt && !ctrl && !shift)
\r
287 _panel->_panelCallback->SetFocusToPath(wParam == VK_F1 ? 0 : 1);
\r
298 // SendMessage(hwndMain, WM_ENTER, 0, 0);
\r
299 _panel->SetFocusToList();
\r
303 bool alt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
\r
304 bool ctrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
\r
305 bool shift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
\r
306 if (!alt && !ctrl && !shift)
\r
308 g_App.SwitchOnOffOnePanel();;
\r
325 return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);
\r
328 return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);
\r
331 bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
\r
333 // _virtualMode = false;
\r
335 _sortID = kpidName;
\r
337 _lastFocusedIsList = true;
\r
339 DWORD style = WS_CHILD | WS_VISIBLE; // | WS_BORDER ; // | LVS_SHAREIMAGELISTS; // | LVS_SHOWSELALWAYS;;
\r
341 style |= LVS_SHAREIMAGELISTS;
\r
342 // style |= LVS_AUTOARRANGE;
\r
343 style |= WS_CLIPCHILDREN;
\r
344 style |= WS_CLIPSIBLINGS;
\r
346 const UInt32 kNumListModes = sizeof(kStyles) / sizeof(kStyles[0]);
\r
347 if (_ListViewMode >= kNumListModes)
\r
348 _ListViewMode = kNumListModes - 1;
\r
350 style |= kStyles[_ListViewMode]
\r
354 style |= LVS_SINGLESEL;
\r
358 style |= LVS_OWNERDATA;
\r
362 exStyle = WS_EX_CLIENTEDGE;
\r
364 if (!_listView.CreateEx(exStyle, style, 0, 0, 116, 260,
\r
365 HWND(*this), (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL))
\r
369 _listView.SetUnicodeFormat(true);
\r
372 _listView.SetUserDataLongPtr(LONG_PTR(&_listView));
\r
373 _listView._panel = this;
\r
377 _listView._origWindowProc =
\r
378 (WNDPROC)_listView.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc));
\r
381 _listView._origWindowProc =
\r
382 (WNDPROC)_listView.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ListViewSubclassProc));
\r
384 _listView.SetImageList(GetSysImageList(true), LVSIL_SMALL);
\r
385 _listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
\r
387 // _exStyle |= LVS_EX_HEADERDRAGDROP;
\r
388 // DWORD extendedStyle = _listView.GetExtendedListViewStyle();
\r
389 // extendedStyle |= _exStyle;
\r
390 // _listView.SetExtendedListViewStyle(extendedStyle);
\r
391 SetExtendedStyle();
\r
393 _listView.Show(SW_SHOW);
\r
394 _listView.InvalidateRect(NULL, true);
\r
395 _listView.Update();
\r
397 // Ensure that the common control DLL is loaded.
\r
398 INITCOMMONCONTROLSEX icex;
\r
400 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
\r
401 icex.dwICC = ICC_BAR_CLASSES;
\r
402 InitCommonControlsEx(&icex);
\r
406 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
\r
407 {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
\r
408 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
\r
409 // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
\r
413 if (g_ComCtl32Version >= MAKELONG(71, 4))
\r
416 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
\r
417 icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
\r
418 InitCommonControlsEx(&icex);
\r
420 _headerReBar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW,
\r
422 NULL, WS_VISIBLE | WS_BORDER | WS_CHILD |
\r
423 WS_CLIPCHILDREN | WS_CLIPSIBLINGS
\r
425 // | CCS_NOPARENTALIGN
\r
429 ,0,0,0,0, HWND(*this), NULL, g_hInstance, NULL));
\r
432 DWORD toolbarStyle = WS_CHILD | WS_VISIBLE ;
\r
436 // | WS_CLIPCHILDREN
\r
437 // | WS_CLIPSIBLINGS
\r
446 _headerToolBar.Attach(::CreateToolbarEx ((*this), toolbarStyle,
\r
448 (HINSTANCE)HINST_COMMCTRL,
\r
449 IDB_VIEW_SMALL_COLOR,
\r
450 (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]),
\r
451 0, 0, 0, 0, sizeof (TBBUTTON)));
\r
454 // Load ComboBoxEx class
\r
455 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
\r
456 icex.dwICC = ICC_USEREX_CLASSES;
\r
457 InitCommonControlsEx(&icex);
\r
460 _headerComboBox.CreateEx(0,
\r
467 WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,
\r
469 ((_headerReBar == 0) ? HWND(*this) : _headerToolBar),
\r
470 (HMENU)(UINT_PTR)(_comboBoxID),
\r
471 g_hInstance, NULL);
\r
473 _headerComboBox.SetUnicodeFormat(true);
\r
475 _headerComboBox.SetImageList(GetSysImageList(true));
\r
477 _headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);
\r
480 _headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));
\r
481 _headerComboBox._panel = this;
\r
482 _headerComboBox._origWindowProc =
\r
483 (WNDPROC)_headerComboBox.SetLongPtr(GWLP_WNDPROC,
\r
484 LONG_PTR(ComboBoxSubclassProc));
\r
486 _comboBoxEdit.Attach(_headerComboBox.GetEditControl());
\r
488 // _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);
\r
490 _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
\r
491 _comboBoxEdit._panel = this;
\r
494 _comboBoxEdit._origWindowProc =
\r
495 (WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
\r
498 _comboBoxEdit._origWindowProc =
\r
499 (WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
\r
506 rbi.cbSize = sizeof(REBARINFO); // Required when using this struct.
\r
508 rbi.himl = (HIMAGELIST)NULL;
\r
509 _headerReBar.SetBarInfo(&rbi);
\r
511 // Send the TB_BUTTONSTRUCTSIZE message, which is required for
\r
512 // backward compatibility.
\r
513 // _headerToolBar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
\r
515 _headerToolBar.GetMaxSize(&size);
\r
517 REBARBANDINFO rbBand;
\r
518 rbBand.cbSize = sizeof(REBARBANDINFO); // Required
\r
519 rbBand.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
\r
520 rbBand.fStyle = RBBS_NOGRIPPER;
\r
521 rbBand.cxMinChild = size.cx;
\r
522 rbBand.cyMinChild = size.cy;
\r
523 rbBand.cyChild = size.cy;
\r
524 rbBand.cx = size.cx;
\r
525 rbBand.hwndChild = _headerToolBar;
\r
526 _headerReBar.InsertBand(-1, &rbBand);
\r
529 ::GetWindowRect(_headerComboBox, &rc);
\r
530 rbBand.cxMinChild = 30;
\r
531 rbBand.cyMinChild = rc.bottom - rc.top;
\r
533 rbBand.hwndChild = _headerComboBox;
\r
534 _headerReBar.InsertBand(-1, &rbBand);
\r
535 // _headerReBar.MaximizeBand(1, false);
\r
538 _statusBar.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID);
\r
539 // _statusBar2.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID + 1);
\r
541 int sizes[] = {150, 250, 350, -1};
\r
542 _statusBar.SetParts(4, sizes);
\r
543 // _statusBar2.SetParts(5, sizes);
\r
547 GetClientRect(&rect);
\r
548 OnSize(0, rect.right - rect.left, rect.top - rect.bottom);
\r
551 SetTimer(kTimerID, kTimerElapse);
\r
555 RefreshStatusBar();
\r
560 void CPanel::OnDestroy()
\r
562 SaveListViewInfo();
\r
563 CWindow2::OnDestroy();
\r
566 void CPanel::ChangeWindowSize(int xSize, int ySize)
\r
568 if ((HWND)*this == 0)
\r
571 int kStatusBarSize;
\r
572 // int kStatusBar2Size;
\r
575 _headerReBar.GetWindowRect(&rect);
\r
577 _headerToolBar.GetWindowRect(&rect);
\r
579 kHeaderSize = rect.bottom - rect.top;
\r
581 _statusBar.GetWindowRect(&rect);
\r
582 kStatusBarSize = rect.bottom - rect.top;
\r
584 // _statusBar2.GetWindowRect(&rect);
\r
585 // kStatusBar2Size = rect.bottom - rect.top;
\r
587 int yListViewSize = MyMax(ySize - kHeaderSize - kStatusBarSize, 0);
\r
588 const int kStartXPos = 32;
\r
594 _headerToolBar.Move(0, 0, xSize, 0);
\r
595 _headerComboBox.Move(kStartXPos, 2,
\r
596 MyMax(xSize - kStartXPos - 10, kStartXPos), 0);
\r
598 _listView.Move(0, kHeaderSize, xSize, yListViewSize);
\r
599 _statusBar.Move(0, kHeaderSize + yListViewSize, xSize, kStatusBarSize);
\r
600 // _statusBar2.MoveWindow(0, kHeaderSize + yListViewSize + kStatusBarSize, xSize, kStatusBar2Size);
\r
601 // _statusBar.MoveWindow(0, 100, xSize, kStatusBarSize);
\r
602 // _statusBar2.MoveWindow(0, 200, xSize, kStatusBar2Size);
\r
605 bool CPanel::OnSize(WPARAM /* wParam */, int xSize, int ySize)
\r
607 if ((HWND)*this == 0)
\r
610 _headerReBar.Move(0, 0, xSize, 0);
\r
611 ChangeWindowSize(xSize, ySize);
\r
615 bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */)
\r
617 switch(header->code)
\r
619 case RBN_HEIGHTCHANGE:
\r
622 GetWindowRect(&rect);
\r
623 ChangeWindowSize(rect.right - rect.left, rect.bottom - rect.top);
\r
630 bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result)
\r
632 if (!_processNotify)
\r
634 if (header->hwndFrom == _headerComboBox)
\r
635 return OnNotifyComboBox(header, result);
\r
636 else if (header->hwndFrom == _headerReBar)
\r
637 return OnNotifyReBar(header, result);
\r
638 // if (header->hwndFrom == _listView)
\r
639 else if (header->hwndFrom == _listView)
\r
640 return OnNotifyList(header, result);
\r
641 else if (::GetParent(header->hwndFrom) == _listView &&
\r
642 header->code == NM_RCLICK)
\r
643 return OnRightClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header, result);
\r
647 bool CPanel::OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result)
\r
649 if (itemID == kParentFolderID)
\r
651 OpenParentFolder();
\r
656 if (itemID == kCreateFolderID)
\r
663 if (itemID == _comboBoxID)
\r
665 if (OnComboBoxCommand(code, lParam, result))
\r
668 return CWindow2::OnCommand(code, itemID, lParam, result);
\r
671 void CPanel::MessageBoxInfo(LPCWSTR message, LPCWSTR caption)
\r
672 { ::MessageBoxW(HWND(*this), message, caption, MB_OK); }
\r
673 void CPanel::MessageBox(LPCWSTR message, LPCWSTR caption)
\r
674 { ::MessageBoxW(HWND(*this), message, caption, MB_OK | MB_ICONSTOP); }
\r
675 void CPanel::MessageBox(LPCWSTR message)
\r
676 { MessageBox(message, L"7-Zip"); }
\r
677 void CPanel::MessageBoxMyError(LPCWSTR message)
\r
678 { MessageBox(message, L"Error"); }
\r
681 void CPanel::MessageBoxError(HRESULT errorCode, LPCWSTR caption)
\r
683 MessageBox(HResultToMessage(errorCode), caption);
\r
686 void CPanel::MessageBoxError(HRESULT errorCode)
\r
687 { MessageBoxError(errorCode, L"7-Zip"); }
\r
688 void CPanel::MessageBoxLastError(LPCWSTR caption)
\r
689 { MessageBoxError(::GetLastError(), caption); }
\r
690 void CPanel::MessageBoxLastError()
\r
691 { MessageBoxLastError(L"Error"); }
\r
693 void CPanel::MessageBoxErrorLang(UINT resourceID, UInt32 langID)
\r
694 { MessageBox(LangString(resourceID, langID)); }
\r
697 void CPanel::SetFocusToList()
\r
699 _listView.SetFocus();
\r
700 // SetCurrentPathText();
\r
703 void CPanel::SetFocusToLastRememberedItem()
\r
705 if (_lastFocusedIsList)
\r
708 _headerComboBox.SetFocus();
\r
711 UString CPanel::GetFolderTypeID() const
\r
713 NCOM::CPropVariant prop;
\r
714 if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)
\r
715 if (prop.vt == VT_BSTR)
\r
716 return (const wchar_t *)prop.bstrVal;
\r
720 bool CPanel::IsFolderTypeEqTo(const wchar_t *s) const
\r
722 return GetFolderTypeID() == s;
\r
725 bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo(L"RootFolder"); }
\r
726 bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo(L"FSFolder"); }
\r
727 bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo(L"FSDrives"); }
\r
728 bool CPanel::IsArcFolder() const
\r
730 UString s = GetFolderTypeID();
\r
731 return s.Left(5) == L"7-Zip";
\r
734 UString CPanel::GetFsPath() const
\r
736 if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())
\r
738 return _currentFolderPrefix;
\r
741 UString CPanel::GetDriveOrNetworkPrefix() const
\r
745 UString drive = GetFsPath();
\r
746 if (drive.Length() < 3)
\r
748 if (drive[0] == L'\\' && drive[1] == L'\\')
\r
751 int pos = drive.Find(L'\\', 2);
\r
754 pos = drive.Find(L'\\', pos + 1);
\r
757 return drive.Left(pos + 1);
\r
759 if (drive[1] != L':' || drive[2] != L'\\')
\r
761 return drive.Left(3);
\r
764 bool CPanel::DoesItSupportOperations() const
\r
766 CMyComPtr<IFolderOperations> folderOperations;
\r
767 return _folder.QueryInterface(IID_IFolderOperations, &folderOperations) == S_OK;
\r
770 void CPanel::SetListViewMode(UInt32 index)
\r
774 _ListViewMode = index;
\r
775 DWORD oldStyle = (DWORD)_listView.GetStyle();
\r
776 DWORD newStyle = kStyles[index];
\r
777 if ((oldStyle & LVS_TYPEMASK) != newStyle)
\r
778 _listView.SetStyle((oldStyle & ~LVS_TYPEMASK) | newStyle);
\r
779 // RefreshListCtrlSaveFocused();
\r
782 void CPanel::ChangeFlatMode()
\r
784 _flatMode = !_flatMode;
\r
785 if (_parentFolders.Size() > 0)
\r
786 _flatModeForArc = _flatMode;
\r
788 _flatModeForDisk = _flatMode;
\r
789 RefreshListCtrlSaveFocused();
\r
793 void CPanel::RefreshStatusBar()
\r
795 PostMessage(kRefreshStatusBar);
\r
798 void CPanel::AddToArchive()
\r
800 CRecordVector<UInt32> indices;
\r
801 GetOperatedItemIndices(indices);
\r
802 if (!IsFsOrDrivesFolder())
\r
804 MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
\r
807 if (indices.Size() == 0)
\r
809 MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03);
\r
812 UStringVector names;
\r
814 UString curPrefix = _currentFolderPrefix;
\r
815 UString destCurDirPrefix = _currentFolderPrefix;
\r
816 if (IsFSDrivesFolder())
\r
818 destCurDirPrefix = ROOT_FS_FOLDER;
\r
819 if (!IsDeviceDrivesPrefix())
\r
823 for (int i = 0; i < indices.Size(); i++)
\r
824 names.Add(curPrefix + GetItemRelPath(indices[i]));
\r
825 const UString archiveName = CreateArchiveName(names.Front(), (names.Size() > 1), false);
\r
826 HRESULT res = CompressFiles(destCurDirPrefix, archiveName, L"", names, false, true, false);
\r
829 if (destCurDirPrefix.Length() >= MAX_PATH)
\r
830 MessageBoxErrorLang(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER, 0x03020A01);
\r
832 // KillSelection();
\r
835 static UString GetSubFolderNameForExtract(const UString &archiveName)
\r
837 int slashPos = archiveName.ReverseFind(WCHAR_PATH_SEPARATOR);
\r
838 int dotPos = archiveName.ReverseFind(L'.');
\r
839 if (dotPos < 0 || slashPos > dotPos)
\r
840 return archiveName + UString(L"~");
\r
841 UString res = archiveName.Left(dotPos);
\r
846 void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths)
\r
848 for (int i = 0; i < indices.Size(); i++)
\r
850 int index = indices[i];
\r
851 if (IsItemFolder(index))
\r
856 paths.Add(GetItemFullPath(index));
\r
858 if (paths.Size() == 0)
\r
860 MessageBoxErrorLang(IDS_SELECT_FILES, 0x03020A03);
\r
865 void CPanel::ExtractArchives()
\r
867 if (_parentFolders.Size() > 0)
\r
869 _panelCallback->OnCopy(false, false);
\r
872 CRecordVector<UInt32> indices;
\r
873 GetOperatedItemIndices(indices);
\r
874 UStringVector paths;
\r
875 GetFilePaths(indices, paths);
\r
876 if (paths.IsEmpty())
\r
878 UString folderName;
\r
879 if (indices.Size() == 1)
\r
880 folderName = GetSubFolderNameForExtract(GetItemRelPath(indices[0]));
\r
883 ::ExtractArchives(paths, _currentFolderPrefix + folderName + UString(WCHAR_PATH_SEPARATOR), true);
\r
886 static void AddValuePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)
\r
889 s += LangString(resourceID, langID);
\r
891 ConvertUInt64ToString(value, sz);
\r
896 class CThreadTest: public CProgressThreadVirt
\r
898 HRESULT ProcessVirt();
\r
900 CRecordVector<UInt32> Indices;
\r
901 CExtractCallbackImp *ExtractCallbackSpec;
\r
902 CMyComPtr<IFolderArchiveExtractCallback> ExtractCallback;
\r
903 CMyComPtr<IArchiveFolder> ArchiveFolder;
\r
906 HRESULT CThreadTest::ProcessVirt()
\r
908 RINOK(ArchiveFolder->Extract(&Indices[0], Indices.Size(),
\r
909 NExtract::NPathMode::kFullPathnames, NExtract::NOverwriteMode::kAskBefore,
\r
910 NULL, BoolToInt(true), ExtractCallback));
\r
911 if (ExtractCallbackSpec->IsOK())
\r
914 AddValuePair(IDS_FOLDERS_COLON, 0x02000321, ExtractCallbackSpec->NumFolders, s);
\r
915 AddValuePair(IDS_FILES_COLON, 0x02000320, ExtractCallbackSpec->NumFiles, s);
\r
916 // AddSizePair(IDS_SIZE_COLON, 0x02000322, Stat.UnpackSize, s);
\r
917 // AddSizePair(IDS_COMPRESSED_COLON, 0x02000323, Stat.PackSize, s);
\r
919 s += LangString(IDS_MESSAGE_NO_ERRORS, 0x02000608);
\r
926 static void AddSizePair(UINT resourceID, UInt32 langID, UInt64 value, UString &s)
\r
929 s += LangString(resourceID, langID);
\r
931 ConvertUInt64ToString(value, sz);
\r
933 ConvertUInt64ToString(value >> 20, sz);
\r
941 void CPanel::TestArchives()
\r
943 CRecordVector<UInt32> indices;
\r
944 GetOperatedIndicesSmart(indices);
\r
945 CMyComPtr<IArchiveFolder> archiveFolder;
\r
946 _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder);
\r
950 CThreadTest extracter;
\r
952 extracter.ArchiveFolder = archiveFolder;
\r
953 extracter.ExtractCallbackSpec = new CExtractCallbackImp;
\r
954 extracter.ExtractCallback = extracter.ExtractCallbackSpec;
\r
955 extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;
\r
957 if (indices.IsEmpty())
\r
960 extracter.Indices = indices;
\r
962 UString title = LangString(IDS_PROGRESS_TESTING, 0x02000F90);
\r
963 UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);
\r
965 extracter.ProgressDialog.CompressingMode = false;
\r
966 extracter.ProgressDialog.MainWindow = GetParent();
\r
967 extracter.ProgressDialog.MainTitle = progressWindowTitle;
\r
968 extracter.ProgressDialog.MainAddTitle = title + L" ";
\r
970 extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
\r
971 extracter.ExtractCallbackSpec->Init();
\r
973 if (extracter.Create(title, GetParent()) != S_OK)
\r
977 RefreshTitleAlways();
\r
983 MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
\r
986 UStringVector paths;
\r
987 GetFilePaths(indices, paths);
\r
988 if (paths.IsEmpty())
\r
990 ::TestArchives(paths);
\r