From 62a9f1d0fa39b3d40208bd913e59cfc514722ee8 Mon Sep 17 00:00:00 2001 From: Thomas Knoefel Date: Sun, 8 Sep 2024 14:57:45 +0200 Subject: [PATCH] added Drag into List feature --- src/DropTarget.cpp | 82 ++++++++++++++++++++++++++++ src/DropTarget.h | 31 +++++++++++ src/MultiReplacePanel.cpp | 47 +++++++++++++++- src/MultiReplacePanel.h | 6 +- vs.proj/MultiReplace.vcxproj | 2 + vs.proj/MultiReplace.vcxproj.filters | 2 + 6 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 src/DropTarget.cpp create mode 100644 src/DropTarget.h diff --git a/src/DropTarget.cpp b/src/DropTarget.cpp new file mode 100644 index 0000000..4f55f90 --- /dev/null +++ b/src/DropTarget.cpp @@ -0,0 +1,82 @@ +#include "DropTarget.h" +#include "MultiReplacePanel.h" + +DropTarget::DropTarget(HWND hwnd, MultiReplace* parent) + : _refCount(1), _hwnd(hwnd), _parent(parent) {} + +HRESULT DropTarget::DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { + UNREFERENCED_PARAMETER(pDataObj); + UNREFERENCED_PARAMETER(grfKeyState); + UNREFERENCED_PARAMETER(pt); + + *pdwEffect = DROPEFFECT_COPY; // Indicate that only copy operations are allowed + return S_OK; +} + +HRESULT DropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { + UNREFERENCED_PARAMETER(grfKeyState); + UNREFERENCED_PARAMETER(pt); + + *pdwEffect = DROPEFFECT_COPY; // Continue to allow only copy operations + return S_OK; +} + +HRESULT DropTarget::DragLeave() { + // Handle the drag leave event with minimal overhead + return S_OK; +} + +HRESULT DropTarget::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { + UNREFERENCED_PARAMETER(grfKeyState); + UNREFERENCED_PARAMETER(pt); + + try { + STGMEDIUM stgMedium; + FORMATETC formatEtc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + // Check if the data is in file format + if (pDataObj->GetData(&formatEtc, &stgMedium) == S_OK) { + HDROP hDrop = static_cast(GlobalLock(stgMedium.hGlobal)); + if (hDrop) { + UINT numFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); + if (numFiles > 0) { + wchar_t filePath[MAX_PATH]; + DragQueryFile(hDrop, 0, filePath, MAX_PATH); + _parent->loadListFromCsv(filePath); // Load CSV file + } + GlobalUnlock(stgMedium.hGlobal); // Unlock the global memory object + } + ReleaseStgMedium(&stgMedium); // Release the storage medium + } + + *pdwEffect = DROPEFFECT_COPY; // Indicate that the operation was a copy + return S_OK; + } + catch (...) { + // Handle errors silently + *pdwEffect = DROPEFFECT_NONE; + return E_FAIL; + } +} + +HRESULT DropTarget::QueryInterface(REFIID riid, void** ppvObject) { + if (riid == IID_IUnknown || riid == IID_IDropTarget) { + *ppvObject = this; + AddRef(); + return S_OK; + } + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG DropTarget::AddRef() { + return InterlockedIncrement(&_refCount); +} + +ULONG DropTarget::Release() { + ULONG count = InterlockedDecrement(&_refCount); + if (count == 0) { + delete this; + } + return count; +} diff --git a/src/DropTarget.h b/src/DropTarget.h new file mode 100644 index 0000000..b9b5494 --- /dev/null +++ b/src/DropTarget.h @@ -0,0 +1,31 @@ +#ifndef DROP_TARGET_H +#define DROP_TARGET_H + +#include +#include // Include for IDropTarget and other shell functions + +class MultiReplace; // Forward declaration to avoid circular dependency + +class DropTarget : public IDropTarget { +public: + DropTarget(HWND hwnd, MultiReplace* parent); + virtual ~DropTarget() {} + + // Implement all IDropTarget methods + HRESULT STDMETHODCALLTYPE DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override; + HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override; + HRESULT STDMETHODCALLTYPE DragLeave() override; + HRESULT STDMETHODCALLTYPE Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) override; + + // IUnknown methods + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef() override; + ULONG STDMETHODCALLTYPE Release() override; + +private: + LONG _refCount; + HWND _hwnd; + MultiReplace* _parent; +}; + +#endif // DROP_TARGET_H diff --git a/src/MultiReplacePanel.cpp b/src/MultiReplacePanel.cpp index be1ac93..2f6d9f7 100644 --- a/src/MultiReplacePanel.cpp +++ b/src/MultiReplacePanel.cpp @@ -307,6 +307,18 @@ void MultiReplace::initializeListView() { ListView_SetExtendedListViewStyle(_replaceListView, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES); } +void MultiReplace::initializeDragAndDrop() { + dropTarget = new DropTarget(_replaceListView, this); // Create an instance of DropTarget + HRESULT hr = ::RegisterDragDrop(_replaceListView, dropTarget); // Register the ListView as a drop target + + if (FAILED(hr)) { + // Safely release the DropTarget instance to avoid memory leaks + delete dropTarget; + dropTarget = nullptr; // Set to nullptr to prevent any unintended usage + } +} + + void MultiReplace::moveAndResizeControls() { // IDs of controls to be moved or resized const int controlIds[] = { @@ -1658,6 +1670,7 @@ INT_PTR CALLBACK MultiReplace::run_dlgProc(UINT message, WPARAM wParam, LPARAM l initializePluginStyle(); initializeCtrlMap(); initializeListView(); + initializeDragAndDrop(); loadSettings(); updateButtonVisibilityBasedOnMode(); updateStatisticsColumnButtonIcon(); @@ -1709,15 +1722,45 @@ INT_PTR CALLBACK MultiReplace::run_dlgProc(UINT message, WPARAM wParam, LPARAM l if (_replaceListView && originalListViewProc) { SetWindowLongPtr(_replaceListView, GWLP_WNDPROC, (LONG_PTR)originalListViewProc); } - saveSettings(); + + saveSettings(); // Save any settings before destroying + + // Unregister Drag-and-Drop + if (dropTarget) { + RevokeDragDrop(_replaceListView); + delete dropTarget; + dropTarget = nullptr; + } + if (hwndEdit) { DestroyWindow(hwndEdit); } + DeleteObject(_hFont); - DestroyWindow(_hSelf); + + // Close the debug window if open + if (hDebugWnd != NULL) { + RECT rect; + if (GetWindowRect(hDebugWnd, &rect)) { + debugWindowPosition.x = rect.left; + debugWindowPosition.y = rect.top; + debugWindowPositionSet = true; + debugWindowSize.cx = rect.right - rect.left; + debugWindowSize.cy = rect.bottom - rect.top; + debugWindowSizeSet = true; + } + PostMessage(hDebugWnd, WM_CLOSE, 0, 0); + hDebugWnd = NULL; // Reset the handle after closing + } + + DestroyWindow(_hSelf); // Destroy the main window + + // Post a quit message to ensure the application terminates cleanly + PostQuitMessage(0); } break; + case WM_SIZE: { if (isWindowOpen) { diff --git a/src/MultiReplacePanel.h b/src/MultiReplacePanel.h index 08e9557..db222d4 100644 --- a/src/MultiReplacePanel.h +++ b/src/MultiReplacePanel.h @@ -19,6 +19,7 @@ #include "StaticDialog/StaticDialog.h" #include "StaticDialog/resource.h" #include "PluginInterface.h" +#include "DropTarget.h" #include #include @@ -299,6 +300,10 @@ class MultiReplace : public StaticDialog static std::vector logChanges; + // Drag-and-Drop functionality + DropTarget* dropTarget; // Pointer to DropTarget instance + void loadListFromCsv(const std::wstring& filePath); // used in DropTarget.cpp + void initializeDragAndDrop(); protected: virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) override; @@ -551,7 +556,6 @@ class MultiReplace : public StaticDialog bool saveListToCsvSilent(const std::wstring& filePath, const std::vector& list); void saveListToCsv(const std::wstring& filePath, const std::vector& list); void loadListFromCsvSilent(const std::wstring& filePath, std::vector& list); - void loadListFromCsv(const std::wstring& filePath); std::wstring escapeCsvValue(const std::wstring& value); std::wstring unescapeCsvValue(const std::wstring& value); diff --git a/vs.proj/MultiReplace.vcxproj b/vs.proj/MultiReplace.vcxproj index 60ca785..b7e8384 100644 --- a/vs.proj/MultiReplace.vcxproj +++ b/vs.proj/MultiReplace.vcxproj @@ -28,6 +28,7 @@ + @@ -63,6 +64,7 @@ + /w %(AdditionalOptions) diff --git a/vs.proj/MultiReplace.vcxproj.filters b/vs.proj/MultiReplace.vcxproj.filters index 11bd2c4..351c10d 100644 --- a/vs.proj/MultiReplace.vcxproj.filters +++ b/vs.proj/MultiReplace.vcxproj.filters @@ -109,6 +109,7 @@ + @@ -201,6 +202,7 @@ +