add class dragdrop
This commit is contained in:
@@ -31,7 +31,7 @@ namespace nana
|
|||||||
simple_dragdrop(simple_dragdrop&&) = delete;
|
simple_dragdrop(simple_dragdrop&&) = delete;
|
||||||
simple_dragdrop& operator=(simple_dragdrop&&) = delete;
|
simple_dragdrop& operator=(simple_dragdrop&&) = delete;
|
||||||
public:
|
public:
|
||||||
simple_dragdrop(window drag_wd);
|
simple_dragdrop(window source);
|
||||||
~simple_dragdrop();
|
~simple_dragdrop();
|
||||||
|
|
||||||
/// Sets a condition that determines whether the drag&drop can start
|
/// Sets a condition that determines whether the drag&drop can start
|
||||||
@@ -40,6 +40,26 @@ namespace nana
|
|||||||
private:
|
private:
|
||||||
implementation* const impl_;
|
implementation* const impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class dragdrop
|
||||||
|
{
|
||||||
|
struct implementation;
|
||||||
|
|
||||||
|
dragdrop(const dragdrop&) = delete;
|
||||||
|
dragdrop& operator=(const dragdrop&) = delete;
|
||||||
|
|
||||||
|
dragdrop(dragdrop&&) = delete;
|
||||||
|
dragdrop& operator=(dragdrop&&) = delete;
|
||||||
|
public:
|
||||||
|
dragdrop(window source);
|
||||||
|
~dragdrop();
|
||||||
|
|
||||||
|
void condition(std::function<bool()> predicate_fn);
|
||||||
|
|
||||||
|
void make_data(std::function<void()> generator);
|
||||||
|
private:
|
||||||
|
implementation* const impl_;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -225,6 +225,36 @@ namespace nana
|
|||||||
FORMATETC * format;
|
FORMATETC * format;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
|
~drop_data()
|
||||||
|
{
|
||||||
|
if(hglobal_)
|
||||||
|
::GlobalFree(hglobal_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(const std::vector<std::wstring>& files)
|
||||||
|
{
|
||||||
|
std::size_t bytes = 0;
|
||||||
|
for (auto & f : files)
|
||||||
|
bytes += (f.size() + 1) * sizeof(f.front());
|
||||||
|
|
||||||
|
hglobal_ = ::GlobalAlloc(GHND | GMEM_SHARE, sizeof(DROPFILES) + bytes);
|
||||||
|
|
||||||
|
auto dropfiles = reinterpret_cast<DROPFILES*>(::GlobalLock(hglobal_));
|
||||||
|
dropfiles->pFiles = sizeof(DROPFILES);
|
||||||
|
dropfiles->fWide = true;
|
||||||
|
|
||||||
|
auto file_buf = reinterpret_cast<char*>(dropfiles) + sizeof(DROPFILES);
|
||||||
|
|
||||||
|
for (auto & f : files)
|
||||||
|
{
|
||||||
|
std::memcpy(file_buf, f.data(), (f.size() + 1) * sizeof(f.front()));
|
||||||
|
file_buf += f.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::GlobalUnlock(hglobal_);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// Implement IDataObject
|
||||||
STDMETHODIMP GetData(FORMATETC *request_format, STGMEDIUM *pmedium) override
|
STDMETHODIMP GetData(FORMATETC *request_format, STGMEDIUM *pmedium) override
|
||||||
{
|
{
|
||||||
if (!(request_format && pmedium))
|
if (!(request_format && pmedium))
|
||||||
@@ -385,8 +415,11 @@ namespace nana
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
HGLOBAL hglobal_{nullptr};
|
||||||
std::vector<medium> mediums_;
|
std::vector<medium> mediums_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
class x11_dragdrop: public detail::x11_dragdrop_interface, public dragdrop_session
|
class x11_dragdrop: public detail::x11_dragdrop_interface, public dragdrop_session
|
||||||
{
|
{
|
||||||
@@ -897,4 +930,122 @@ namespace nana
|
|||||||
impl_->ddrop->insert(impl_->window_handle, target);
|
impl_->ddrop->insert(impl_->window_handle, target);
|
||||||
impl_->targets[target].swap(drop_fn);
|
impl_->targets[target].swap(drop_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//This is class dragdrop
|
||||||
|
struct dragdrop::implementation
|
||||||
|
{
|
||||||
|
window source_handle;
|
||||||
|
bool dragging{ false };
|
||||||
|
std::function<bool()> predicate;
|
||||||
|
|
||||||
|
std::function<void()> generator;
|
||||||
|
|
||||||
|
|
||||||
|
struct event_handlers
|
||||||
|
{
|
||||||
|
nana::event_handle destroy;
|
||||||
|
nana::event_handle mouse_move;
|
||||||
|
nana::event_handle mouse_down;
|
||||||
|
}events;
|
||||||
|
|
||||||
|
void make_data()
|
||||||
|
{
|
||||||
|
//https://www.codeproject.com/Articles/840/How-to-Implement-Drag-and-Drop-Between-Your-Progra
|
||||||
|
|
||||||
|
std::vector<std::wstring> files;
|
||||||
|
files.push_back(L"D:\\universal_access");
|
||||||
|
files.push_back(L"D:\\<EFBFBD>½<EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ĵ<EFBFBD>.cpp");
|
||||||
|
|
||||||
|
std::size_t bytes = 0;
|
||||||
|
for (auto & f : files)
|
||||||
|
bytes += (f.size() + 1) * sizeof(f.front());
|
||||||
|
|
||||||
|
auto data_handle = ::GlobalAlloc(GHND | GMEM_SHARE, sizeof(DROPFILES) + bytes);
|
||||||
|
|
||||||
|
auto dropfiles = reinterpret_cast<DROPFILES*>(::GlobalLock(data_handle));
|
||||||
|
dropfiles->pFiles = sizeof(DROPFILES);
|
||||||
|
dropfiles->fWide = true;
|
||||||
|
|
||||||
|
auto file_buf = reinterpret_cast<char*>(dropfiles) + sizeof(DROPFILES);
|
||||||
|
|
||||||
|
for (auto & f : files)
|
||||||
|
{
|
||||||
|
std::memcpy(file_buf, f.data(), (f.size() + 1) * sizeof(f.front()));
|
||||||
|
file_buf += f.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::GlobalUnlock(data_handle);
|
||||||
|
|
||||||
|
|
||||||
|
generator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dragdrop::dragdrop(window source) :
|
||||||
|
impl_(new implementation)
|
||||||
|
{
|
||||||
|
impl_->source_handle = source;
|
||||||
|
|
||||||
|
auto & events = API::events(source);
|
||||||
|
impl_->events.destroy = events.destroy.connect_unignorable([this](const arg_destroy&) {
|
||||||
|
dragdrop_service::instance().remove(impl_->source_handle);
|
||||||
|
API::dev::window_draggable(impl_->source_handle, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_->events.mouse_down = events.mouse_down.connect_unignorable([this](const arg_mouse& arg) {
|
||||||
|
if (arg.is_left_button() && API::is_window(impl_->source_handle))
|
||||||
|
{
|
||||||
|
impl_->dragging = ((!impl_->predicate) || impl_->predicate());
|
||||||
|
|
||||||
|
using basic_window = ::nana::detail::basic_window;
|
||||||
|
auto real_wd = reinterpret_cast<::nana::detail::basic_window*>(impl_->source_handle);
|
||||||
|
real_wd->other.dnd_state = dragdrop_status::ready;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_->events.mouse_move = events.mouse_move.connect_unignorable([this](const arg_mouse& arg) {
|
||||||
|
if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
using basic_window = ::nana::detail::basic_window;
|
||||||
|
auto real_wd = reinterpret_cast<::nana::detail::basic_window*>(arg.window_handle);
|
||||||
|
real_wd->other.dnd_state = dragdrop_status::in_progress;
|
||||||
|
|
||||||
|
impl_->make_data();
|
||||||
|
|
||||||
|
auto has_dropped = dragdrop_service::instance().dragdrop(arg.window_handle);
|
||||||
|
|
||||||
|
real_wd->other.dnd_state = dragdrop_status::not_ready;
|
||||||
|
impl_->dragging = false;
|
||||||
|
|
||||||
|
if (has_dropped)
|
||||||
|
{
|
||||||
|
auto drop_wd = API::find_window(API::cursor_position());
|
||||||
|
//auto i = impl_->targets.find(drop_wd);
|
||||||
|
//if ((impl_->targets.end() != i) && i->second)
|
||||||
|
// i->second();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dragdrop::~dragdrop()
|
||||||
|
{
|
||||||
|
delete impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dragdrop::condition(std::function<bool()> predicate_fn)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void dragdrop::make_data(std::function<void()> generator)
|
||||||
|
{
|
||||||
|
impl_->generator = generator;
|
||||||
|
}
|
||||||
|
}//end namespace nana
|
||||||
Reference in New Issue
Block a user