diff options
Diffstat (limited to 'wx+/file_drop.h')
-rw-r--r-- | wx+/file_drop.h | 113 |
1 files changed, 80 insertions, 33 deletions
diff --git a/wx+/file_drop.h b/wx+/file_drop.h index 664b4387..0e9e92ad 100644 --- a/wx+/file_drop.h +++ b/wx+/file_drop.h @@ -4,29 +4,41 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef FILE_DROP_H_INCLUDED -#define FILE_DROP_H_INCLUDED +#ifndef FILE_DROP_H_09457802957842560325626 +#define FILE_DROP_H_09457802957842560325626 #include <vector> +#include <functional> +#include <zen/zstring.h> +#include <zen/utf.h> #include <wx/window.h> #include <wx/event.h> #include <wx/dnd.h> +#ifdef ZEN_WIN_VISTA_AND_LATER +#include <zen/win.h> +#endif + + namespace zen { //register simple file drop event (without issue of freezing dialogs and without wxFileDropTarget overdesign) //CAVEAT: a drop target window must not be directly or indirectly contained within a wxStaticBoxSizer until the following wxGTK bug //is fixed. According to wxWidgets release cycles this is expected to be: never http://trac.wxwidgets.org/ticket/2763 -//1. setup a window to emit EVENT_DROP_FILE -void setupFileDrop(wxWindow& wnd); +/* +1. setup a window to emit EVENT_DROP_FILE: + - simple file system paths: setupFileDrop + - any shell paths with validation: setupShellItemDrop + +2. register events: +wnd.Connect (EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this); +wnd.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this); -//2. register events: -//wnd.Connect (EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this); -//wnd.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this); +3. do something: +void MyDlg::OnFilesDropped(FileDropEvent& event); +*/ -//3. do something: -//void MyDlg::OnFilesDropped(FileDropEvent& event); @@ -46,29 +58,20 @@ wxEventType createNewEventType() } } - //define new event type const wxEventType EVENT_DROP_FILE = impl::createNewEventType(); class FileDropEvent : public wxCommandEvent { public: - FileDropEvent(const std::vector<wxString>& filesDropped, const wxWindow& dropWindow, wxPoint dropPos) : - wxCommandEvent(EVENT_DROP_FILE), - filesDropped_(filesDropped), - dropWindow_(dropWindow), - dropPos_(dropPos) {} + FileDropEvent(const std::vector<Zstring>& filesDropped) : wxCommandEvent(EVENT_DROP_FILE), filesDropped_(filesDropped) {} - wxEvent* Clone() const override { return new FileDropEvent(*this); } - - const std::vector<wxString>& getFiles() const { return filesDropped_; } - const wxWindow& getDropWindow() const { return dropWindow_; } - wxPoint getDropPosition() const { return dropPos_; } //position relative to drop window + const std::vector<Zstring>& getFiles() const { return filesDropped_; } private: - const std::vector<wxString> filesDropped_; - const wxWindow& dropWindow_; - const wxPoint dropPos_; + wxEvent* Clone() const override { return new FileDropEvent(*this); } + + const std::vector<Zstring> filesDropped_; }; typedef void (wxEvtHandler::*FileDropEventFunction)(FileDropEvent&); @@ -77,6 +80,50 @@ typedef void (wxEvtHandler::*FileDropEventFunction)(FileDropEvent&); (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FileDropEventFunction, &func) + +#ifdef ZEN_WIN_VISTA_AND_LATER +using DragDropValidator = bool (*)(const std::vector<Zstring>& shellItemPaths); //plain static function => no lifetime management needed! +using DragDropConsumer = std::function<void (const std::vector<Zstring>& shellItemPaths)>; + +namespace impl +{ +void registerDragDrop(HWND hwnd, const DragDropValidator& acceptDrop, const DragDropConsumer& onDrop); +void unregisterDragDrop(HWND hwnd); + +class DragDropCleanupWindow : private wxWindow +{ +public: + DragDropCleanupWindow(wxWindow& dropWindow) : wxWindow(&dropWindow, wxID_ANY), dropHwnd(dropWindow.GetHWND()) + { + Hide(); //this is just a dummy window so that its parent can have ownership + Disable(); + } + ~DragDropCleanupWindow() { impl::unregisterDragDrop(dropHwnd); } + +private: + HWND dropHwnd; +}; +} + + +inline +void setupShellItemDrop(wxWindow& dropWindow, const DragDropValidator& acceptDrop) +{ + auto onDrop = [&dropWindow](const std::vector<Zstring>& shellItemPaths) + { + //create a custom event on drop window: execute event after file dropping is completed! (after mouse is released) + if (wxEvtHandler* handler = dropWindow.GetEventHandler()) + handler->AddPendingEvent(FileDropEvent(shellItemPaths)); + }; + + impl::registerDragDrop(static_cast<HWND>(dropWindow.GetHWND()), acceptDrop, onDrop); + + //make sure clean-up is tied to dropWindow life-time: + new impl::DragDropCleanupWindow(dropWindow); //ownership passed to "dropWindow" +} +#endif + + namespace impl { class WindowDropTarget : public wxFileDropTarget @@ -87,11 +134,14 @@ public: private: bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& fileArray) override { - std::vector<wxString> filepaths(fileArray.begin(), fileArray.end()); - if (!filepaths.empty()) - //create a custom event on drop window: execute event after file dropping is completed! (after mouse is released) - if (wxEvtHandler* handler = dropWindow_.GetEventHandler()) - handler->AddPendingEvent(FileDropEvent(filepaths, dropWindow_, wxPoint(x, y))); + //wxPoint clientDropPos(x, y) + std::vector<Zstring> filePaths; + for (const wxString& file : fileArray) + filePaths.push_back(utfCvrtTo<Zstring>(file)); + + //create a custom event on drop window: execute event after file dropping is completed! (after mouse is released) + if (wxEvtHandler* handler = dropWindow_.GetEventHandler()) + handler->AddPendingEvent(FileDropEvent(filePaths)); return true; } @@ -101,10 +151,7 @@ private: inline -void setupFileDrop(wxWindow& wnd) -{ - wnd.SetDropTarget(new impl::WindowDropTarget(wnd)); //takes ownership -} +void setupFileDrop(wxWindow& wnd) { wnd.SetDropTarget(new impl::WindowDropTarget(wnd)); /*takes ownership*/ } } -#endif // FILE_DROP_H_INCLUDED +#endif //FILE_DROP_H_09457802957842560325626 |