diff options
Diffstat (limited to '7zip/FileManager/PanelDrag.cpp')
-rwxr-xr-x | 7zip/FileManager/PanelDrag.cpp | 200 |
1 files changed, 126 insertions, 74 deletions
diff --git a/7zip/FileManager/PanelDrag.cpp b/7zip/FileManager/PanelDrag.cpp index 2a563953..db342f73 100755 --- a/7zip/FileManager/PanelDrag.cpp +++ b/7zip/FileManager/PanelDrag.cpp @@ -155,11 +155,13 @@ class CDropSource: public IDropSource, public CMyUnknownImp { + DWORD m_Effect; public: MY_UNKNOWN_IMP1_MT(IDropSource) STDMETHOD(QueryContinueDrag)(BOOL escapePressed, DWORD keyState); STDMETHOD(GiveFeedback)(DWORD effect); + bool NeedExtract; CPanel *Panel; CRecordVector<UInt32> Indices; @@ -171,7 +173,7 @@ public: HRESULT Result; UStringVector Messages; - CDropSource(): NeedPostCopy(false), Panel(0), Result(S_OK) {} + CDropSource(): NeedPostCopy(false), Panel(0), Result(S_OK), m_Effect(DROPEFFECT_NONE) {} }; STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) @@ -180,6 +182,8 @@ STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) return DRAGDROP_S_CANCEL; if((keyState & MK_LBUTTON) == 0) { + if (m_Effect == DROPEFFECT_NONE) + return DRAGDROP_S_CANCEL; Result = S_OK; bool needExtract = NeedExtract; // MoveMode = (((keyState & MK_SHIFT) != 0) && MoveIsAllowed); @@ -204,6 +208,7 @@ STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) STDMETHODIMP CDropSource::GiveFeedback(DWORD effect) { + m_Effect = effect; return DRAGDROP_S_USEDEFAULTCURSORS; } @@ -319,7 +324,7 @@ void CPanel::OnDrag(LPNMLISTVIEW nmListView) else { if (res != DRAGDROP_S_CANCEL && res != S_OK) - MessageBoxError(res, L"7-Zip"); + MessageBoxError(res); res = dropSourceSpec->Result; } @@ -330,7 +335,7 @@ void CPanel::OnDrag(LPNMLISTVIEW nmListView) messagesDialog.Create((*this)); } if (res != S_OK && res != E_ABORT) - MessageBoxError(res, L"7-Zip"); + MessageBoxError(res); if (res == S_OK && dropSourceSpec->Messages.IsEmpty() && !canceled) KillSelection(); } @@ -339,6 +344,7 @@ void CDropTarget::QueryGetData(IDataObject *dataObject) { FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; m_DropIsAllowed = (dataObject->QueryGetData(&etc) == S_OK); + } static void MySetDropHighlighted(HWND hWnd, int index, bool enable) @@ -419,7 +425,7 @@ void CDropTarget::PositionCursor(POINTL ptl) if (index < 0) return; int realIndex = m_Panel->GetRealItemIndex(index); - if (realIndex == -1) + if (realIndex == kParentIndex) return; if (!m_Panel->IsItemFolder(realIndex)) return; @@ -436,6 +442,103 @@ bool CDropTarget::IsFsFolderPath() const return false; } +static void ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names) +{ + names.Clear(); + UString name; + for (;size > 0; size--) + { + wchar_t c = *p++; + if (c == 0) + { + if (name.IsEmpty()) + break; + names.Add(name); + name.Empty(); + } + else + name += c; + } +} + +static void ReadAnsiStrings(const char *p, size_t size, UStringVector &names) +{ + names.Clear(); + AString name; + for (;size > 0; size--) + { + char c = *p++; + if (c == 0) + { + if (name.IsEmpty()) + break; + names.Add(GetUnicodeString(name)); + name.Empty(); + } + else + name += c; + } +} + +static void GetNamesFromDataObject(IDataObject *dataObject, UStringVector &names) +{ + names.Clear(); + FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium; + HRESULT res = dataObject->GetData(&etc, &medium); + if (res != S_OK) + return; + if (medium.tymed != TYMED_HGLOBAL) + return; + { + NMemory::CGlobal global; + global.Attach(medium.hGlobal); + size_t blockSize = GlobalSize(medium.hGlobal); + NMemory::CGlobalLock dropLock(medium.hGlobal); + const DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer(); + if (dropFiles == 0) + return; + if (blockSize < dropFiles->pFiles) + return; + size_t size = blockSize - dropFiles->pFiles; + const void *namesData = (const Byte *)dropFiles + dropFiles->pFiles; + if (dropFiles->fWide) + ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names); + else + ReadAnsiStrings((const char *)namesData, size, names); + } +} + +bool CDropTarget::IsItSameDrive() const +{ + if (m_Panel == 0) + return false; + if (!IsFsFolderPath()) + return false; + UString drive; + if (m_Panel->IsFSFolder()) + { + drive = m_Panel->GetDriveOrNetworkPrefix(); + if (drive.IsEmpty()) + return false; + } + else if (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0) + drive = m_SubFolderName + L'\\'; + else + return false; + + if (m_SourcePaths.Size() == 0) + return false; + for (int i = 0; i < m_SourcePaths.Size(); i++) + { + const UString &path = m_SourcePaths[i]; + if (drive.CollateNoCase(path.Left(drive.Length())) != 0) + return false; + } + return true; + +} + DWORD CDropTarget::GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect) { if (!m_DropIsAllowed || !m_PanelDropIsAllowed) @@ -444,6 +547,9 @@ DWORD CDropTarget::GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect) if (!IsFsFolderPath()) allowedEffect &= ~DROPEFFECT_MOVE; + if (!m_SetPathIsOK) + allowedEffect &= ~DROPEFFECT_MOVE; + DWORD effect = 0; if(keyState & MK_CONTROL) effect = allowedEffect & DROPEFFECT_COPY; @@ -451,8 +557,13 @@ DWORD CDropTarget::GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect) effect = allowedEffect & DROPEFFECT_MOVE; if(effect == 0) { - if(allowedEffect & DROPEFFECT_COPY) effect = DROPEFFECT_COPY; - if(allowedEffect & DROPEFFECT_MOVE) effect = DROPEFFECT_MOVE; + if(allowedEffect & DROPEFFECT_COPY) + effect = DROPEFFECT_COPY; + if(allowedEffect & DROPEFFECT_MOVE) + { + if (IsItSameDrive()) + effect = DROPEFFECT_MOVE; + } } if(effect == 0) return DROPEFFECT_NONE; @@ -504,12 +615,14 @@ bool CDropTarget::SetPath(bool enablePath) const bool CDropTarget::SetPath() { - return SetPath(m_DropIsAllowed && m_PanelDropIsAllowed && IsFsFolderPath()); + m_SetPathIsOK = SetPath(m_DropIsAllowed && m_PanelDropIsAllowed && IsFsFolderPath()); + return m_SetPathIsOK; } STDMETHODIMP CDropTarget::DragEnter(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect) { + GetNamesFromDataObject(dataObject, m_SourcePaths); QueryGetData(dataObject); m_DataObject = dataObject; return DragOver(keyState, pt, effect); @@ -519,8 +632,8 @@ STDMETHODIMP CDropTarget::DragEnter(IDataObject * dataObject, DWORD keyState, STDMETHODIMP CDropTarget::DragOver(DWORD keyState, POINTL pt, DWORD *effect) { PositionCursor(pt); - *effect = GetEffect(keyState, pt, *effect); SetPath(); + *effect = GetEffect(keyState, pt, *effect); return S_OK; } @@ -541,13 +654,14 @@ STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState, { QueryGetData(dataObject); PositionCursor(pt); - *effect = GetEffect(keyState, pt, *effect); m_DataObject = dataObject; + bool needDrop = true; if(m_DropIsAllowed && m_PanelDropIsAllowed) - { - bool needDrop = true; if (IsFsFolderPath()) needDrop = !SetPath(); + *effect = GetEffect(keyState, pt, *effect); + if(m_DropIsAllowed && m_PanelDropIsAllowed) + { if (needDrop) { UString path = GetTargetPath(); @@ -562,75 +676,13 @@ STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState, return S_OK; } -static void ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names) -{ - names.Clear(); - UString name; - for (;size > 0; size--) - { - wchar_t c = *p++; - if (c == 0) - { - if (name.IsEmpty()) - break; - names.Add(name); - name.Empty(); - } - else - name += c; - } -} - -static void ReadAnsiStrings(const char *p, size_t size, UStringVector &names) -{ - names.Clear(); - AString name; - for (;size > 0; size--) - { - char c = *p++; - if (c == 0) - { - if (name.IsEmpty()) - break; - names.Add(GetUnicodeString(name)); - name.Empty(); - } - else - name += c; - } -} - void CPanel::DropObject(IDataObject *dataObject, const UString &folderPath) { - FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - STGMEDIUM medium; - HRESULT res = dataObject->GetData(&etc, &medium); - if (res != S_OK) - return; - if (medium.tymed != TYMED_HGLOBAL) - return; UStringVector names; - { - NMemory::CGlobal global; - global.Attach(medium.hGlobal); - size_t blockSize = GlobalSize(medium.hGlobal); - NMemory::CGlobalLock dropLock(medium.hGlobal); - const DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer(); - if (dropFiles == 0) - return; - if (blockSize < dropFiles->pFiles) - return; - size_t size = blockSize - dropFiles->pFiles; - const void *namesData = (const Byte *)dropFiles + dropFiles->pFiles; - if (dropFiles->fWide) - ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names); - else - ReadAnsiStrings((const char *)namesData, size, names); - } + GetNamesFromDataObject(dataObject, names); CompressDropFiles(names, folderPath); } - /* void CPanel::CompressDropFiles(HDROP dr) { |