fix MinGW warnings of compiling dragdrop.cpp
This commit is contained in:
parent
6ac558e1b7
commit
2e0f29564f
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Drag and Drop Implementation
|
* Drag and Drop Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2019 Jinhao(cnjinhao@hotmail.com)
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -157,10 +157,16 @@ namespace nana
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NANA_WINDOWS
|
#ifdef NANA_WINDOWS
|
||||||
|
|
||||||
template<typename Interface, const IID& iid>
|
template<typename Interface, const IID& iid>
|
||||||
class win32com_iunknown : public Interface
|
class win32com_iunknown final: public Interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
template<typename ...Args>
|
||||||
|
win32com_iunknown(Args&& ... args) :
|
||||||
|
Interface(std::forward<Args>(args)...)
|
||||||
|
{}
|
||||||
|
|
||||||
//Implements IUnknown
|
//Implements IUnknown
|
||||||
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
|
||||||
{
|
{
|
||||||
@ -188,6 +194,7 @@ namespace nana
|
|||||||
LONG ref_count_{ 1 };
|
LONG ref_count_{ 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class win32com_drop_target : public IDropTarget, public dragdrop_session
|
class win32com_drop_target : public IDropTarget, public dragdrop_session
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -273,296 +280,300 @@ namespace nana
|
|||||||
DWORD effect_{ DROPEFFECT_NONE };
|
DWORD effect_{ DROPEFFECT_NONE };
|
||||||
};
|
};
|
||||||
|
|
||||||
class drop_source : public win32com_iunknown<IDropSource, IID_IDropSource>
|
class drop_source_impl : public IDropSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
drop_source_impl(window wd) :
|
||||||
|
window_handle_(wd)
|
||||||
|
{}
|
||||||
|
|
||||||
|
window source() const
|
||||||
{
|
{
|
||||||
public:
|
return window_handle_;
|
||||||
drop_source(window wd) :
|
}
|
||||||
window_handle_(wd)
|
private:
|
||||||
{}
|
// IDropSource
|
||||||
|
STDMETHODIMP QueryContinueDrag(BOOL esc_pressed, DWORD key_state) override
|
||||||
window source() const
|
|
||||||
{
|
|
||||||
return window_handle_;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
// IDropSource
|
|
||||||
STDMETHODIMP QueryContinueDrag(BOOL esc_pressed, DWORD key_state) override
|
|
||||||
{
|
|
||||||
if (esc_pressed)
|
|
||||||
return DRAGDROP_S_CANCEL;
|
|
||||||
|
|
||||||
//Drop the object if left button is released.
|
|
||||||
if (0 == (key_state & (MK_LBUTTON)))
|
|
||||||
return DRAGDROP_S_DROP;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP GiveFeedback(DWORD effect) override
|
|
||||||
{
|
|
||||||
return DRAGDROP_S_USEDEFAULTCURSORS;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
window const window_handle_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class win32_dropdata : public win32com_iunknown<IDataObject, IID_IDataObject>
|
|
||||||
{
|
{
|
||||||
public:
|
if (esc_pressed)
|
||||||
struct data_entry
|
return DRAGDROP_S_CANCEL;
|
||||||
|
|
||||||
|
//Drop the object if left button is released.
|
||||||
|
if (0 == (key_state & (MK_LBUTTON)))
|
||||||
|
return DRAGDROP_S_DROP;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP GiveFeedback(DWORD effect) override
|
||||||
|
{
|
||||||
|
return DRAGDROP_S_USEDEFAULTCURSORS;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
window const window_handle_;
|
||||||
|
};
|
||||||
|
using drop_source = win32com_iunknown<drop_source_impl, IID_IDropSource>;
|
||||||
|
|
||||||
|
|
||||||
|
class win32_dropdata_impl: public IDataObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct data_entry
|
||||||
|
{
|
||||||
|
FORMATETC format;
|
||||||
|
STGMEDIUM medium;
|
||||||
|
bool read_from; //Indicates the data which is used for reading.
|
||||||
|
|
||||||
|
~data_entry()
|
||||||
{
|
{
|
||||||
FORMATETC format;
|
::CoTaskMemFree(format.ptd);
|
||||||
STGMEDIUM medium;
|
::ReleaseStgMedium(&medium);
|
||||||
bool read_from; //Indicates the data which is used for reading.
|
}
|
||||||
|
|
||||||
~data_entry()
|
bool compare(const FORMATETC& fmt, bool rdfrom) const
|
||||||
{
|
{
|
||||||
::CoTaskMemFree(format.ptd);
|
return (format.cfFormat == fmt.cfFormat &&
|
||||||
::ReleaseStgMedium(&medium);
|
(format.tymed & fmt.tymed) != 0 &&
|
||||||
}
|
(format.dwAspect == DVASPECT_THUMBNAIL || format.dwAspect == DVASPECT_ICON || medium.tymed == TYMED_NULL || format.lindex == fmt.lindex || (format.lindex == 0 && fmt.lindex == -1) || (format.lindex == -1 && fmt.lindex == 0)) &&
|
||||||
|
format.dwAspect == fmt.dwAspect && read_from == rdfrom);
|
||||||
bool compare(const FORMATETC& fmt, bool rdfrom) const
|
}
|
||||||
{
|
|
||||||
return (format.cfFormat == fmt.cfFormat &&
|
|
||||||
(format.tymed & fmt.tymed) != 0 &&
|
|
||||||
(format.dwAspect == DVASPECT_THUMBNAIL || format.dwAspect == DVASPECT_ICON || medium.tymed == TYMED_NULL || format.lindex == fmt.lindex || (format.lindex == 0 && fmt.lindex == -1) || (format.lindex == -1 && fmt.lindex == 0)) &&
|
|
||||||
format.dwAspect == fmt.dwAspect && read_from == rdfrom);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
data_entry * find(const FORMATETC& fmt, bool read_from) const
|
data_entry * find(const FORMATETC& fmt, bool read_from) const
|
||||||
|
{
|
||||||
|
data_entry * last_weak_match = nullptr;
|
||||||
|
|
||||||
|
for (auto & entry : entries_)
|
||||||
{
|
{
|
||||||
data_entry * last_weak_match = nullptr;
|
if (entry->compare(fmt, read_from))
|
||||||
|
|
||||||
for (auto & entry : entries_)
|
|
||||||
{
|
{
|
||||||
if (entry->compare(fmt, read_from))
|
auto entry_ptd = entry->format.ptd;
|
||||||
{
|
if (entry_ptd && fmt.ptd && entry_ptd->tdSize == fmt.ptd->tdSize && (0 == std::memcmp(entry_ptd, fmt.ptd, fmt.ptd->tdSize)))
|
||||||
auto entry_ptd = entry->format.ptd;
|
return entry.get();
|
||||||
if (entry_ptd && fmt.ptd && entry_ptd->tdSize == fmt.ptd->tdSize && (0 == std::memcmp(entry_ptd, fmt.ptd, fmt.ptd->tdSize)))
|
else if (nullptr == entry_ptd && nullptr == fmt.ptd)
|
||||||
return entry.get();
|
return entry.get();
|
||||||
else if (nullptr == entry_ptd && nullptr == fmt.ptd)
|
|
||||||
return entry.get();
|
|
||||||
|
|
||||||
last_weak_match = entry.get();
|
last_weak_match = entry.get();
|
||||||
}
|
|
||||||
}
|
|
||||||
return last_weak_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assign(const detail::dragdrop_data& data)
|
|
||||||
{
|
|
||||||
if (!data.files.empty())
|
|
||||||
{
|
|
||||||
std::size_t bytes = sizeof(wchar_t);
|
|
||||||
for (auto & file : data.files)
|
|
||||||
{
|
|
||||||
auto file_s = file.wstring();
|
|
||||||
bytes += (file_s.size() + 1) * sizeof(file_s.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto 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 & file : data.files)
|
|
||||||
{
|
|
||||||
auto file_s = file.wstring();
|
|
||||||
std::memcpy(file_buf, file_s.data(), (file_s.size() + 1) * sizeof(file_s.front()));
|
|
||||||
file_buf += (file_s.size() + 1) * sizeof(file_s.front());
|
|
||||||
}
|
|
||||||
*reinterpret_cast<wchar_t*>(file_buf) = 0;
|
|
||||||
|
|
||||||
::GlobalUnlock(hglobal);
|
|
||||||
|
|
||||||
assign(hglobal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return last_weak_match;
|
||||||
|
}
|
||||||
|
|
||||||
data_entry* assign(HGLOBAL hglobal)
|
void assign(const detail::dragdrop_data& data)
|
||||||
|
{
|
||||||
|
if (!data.files.empty())
|
||||||
{
|
{
|
||||||
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
std::size_t bytes = sizeof(wchar_t);
|
||||||
auto entry = find(fmt, true);
|
for (auto & file : data.files)
|
||||||
if (entry)
|
|
||||||
{
|
{
|
||||||
//Free the current entry for reuse
|
auto file_s = file.wstring();
|
||||||
::CoTaskMemFree(entry->format.ptd);
|
bytes += (file_s.size() + 1) * sizeof(file_s.front());
|
||||||
::ReleaseStgMedium(&entry->medium);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Create a new entry
|
|
||||||
entries_.emplace_back(new data_entry);
|
|
||||||
entry = entries_.back().get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Assign the format to the entry.
|
auto hglobal = ::GlobalAlloc(GHND | GMEM_SHARE, sizeof(DROPFILES) + bytes);
|
||||||
entry->read_from = true;
|
|
||||||
entry->format = fmt;
|
|
||||||
|
|
||||||
//Assign the stgMedium
|
auto dropfiles = reinterpret_cast<DROPFILES*>(::GlobalLock(hglobal));
|
||||||
entry->medium.tymed = TYMED_HGLOBAL;
|
dropfiles->pFiles = sizeof(DROPFILES);
|
||||||
entry->medium.hGlobal = hglobal;
|
dropfiles->fWide = true;
|
||||||
entry->medium.pUnkForRelease = nullptr;
|
|
||||||
|
|
||||||
return entry;
|
auto file_buf = reinterpret_cast<char*>(dropfiles)+sizeof(DROPFILES);
|
||||||
}
|
|
||||||
public:
|
|
||||||
// Implement IDataObject
|
|
||||||
STDMETHODIMP GetData(FORMATETC *request_format, STGMEDIUM *pmedium) override
|
|
||||||
{
|
|
||||||
if (!(request_format && pmedium))
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
pmedium->hGlobal = nullptr;
|
for (auto & file : data.files)
|
||||||
|
|
||||||
auto entry = find(*request_format, true);
|
|
||||||
if (entry)
|
|
||||||
return _m_copy_medium(pmedium, &entry->medium, &entry->format);
|
|
||||||
|
|
||||||
return DV_E_FORMATETC;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium) override
|
|
||||||
{
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP QueryGetData(FORMATETC *pformatetc) override
|
|
||||||
{
|
|
||||||
if (NULL == pformatetc)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
if (!(DVASPECT_CONTENT & pformatetc->dwAspect))
|
|
||||||
return DV_E_DVASPECT;
|
|
||||||
|
|
||||||
HRESULT result = DV_E_TYMED;
|
|
||||||
|
|
||||||
for (auto & entry : entries_)
|
|
||||||
{
|
{
|
||||||
if (entry->format.tymed & pformatetc->tymed)
|
auto file_s = file.wstring();
|
||||||
{
|
std::memcpy(file_buf, file_s.data(), (file_s.size() + 1) * sizeof(file_s.front()));
|
||||||
if (entry->format.cfFormat == pformatetc->cfFormat)
|
file_buf += (file_s.size() + 1) * sizeof(file_s.front());
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
result = DV_E_FORMATETC;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
*reinterpret_cast<wchar_t*>(file_buf) = 0;
|
||||||
|
|
||||||
|
::GlobalUnlock(hglobal);
|
||||||
|
|
||||||
|
assign(hglobal);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut) override
|
data_entry* assign(HGLOBAL hglobal)
|
||||||
|
{
|
||||||
|
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||||
|
auto entry = find(fmt, true);
|
||||||
|
if (entry)
|
||||||
{
|
{
|
||||||
return E_NOTIMPL;
|
//Free the current entry for reuse
|
||||||
|
::CoTaskMemFree(entry->format.ptd);
|
||||||
|
::ReleaseStgMedium(&entry->medium);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
STDMETHODIMP SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease) override
|
|
||||||
{
|
{
|
||||||
if (!(pformatetc && pmedium))
|
//Create a new entry
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
if (pformatetc->tymed != pmedium->tymed)
|
|
||||||
return E_FAIL;
|
|
||||||
|
|
||||||
entries_.emplace_back(new data_entry);
|
entries_.emplace_back(new data_entry);
|
||||||
auto entry = entries_.back().get();
|
entry = entries_.back().get();
|
||||||
|
|
||||||
entry->format = *pformatetc;
|
|
||||||
|
|
||||||
_m_copy_medium(&entry->medium, pmedium, pformatetc);
|
|
||||||
|
|
||||||
if (TRUE == fRelease)
|
|
||||||
::ReleaseStgMedium(pmedium);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) override
|
//Assign the format to the entry.
|
||||||
|
entry->read_from = true;
|
||||||
|
entry->format = fmt;
|
||||||
|
|
||||||
|
//Assign the stgMedium
|
||||||
|
entry->medium.tymed = TYMED_HGLOBAL;
|
||||||
|
entry->medium.hGlobal = hglobal;
|
||||||
|
entry->medium.pUnkForRelease = nullptr;
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// Implement IDataObject
|
||||||
|
STDMETHODIMP GetData(FORMATETC *request_format, STGMEDIUM *pmedium) override
|
||||||
|
{
|
||||||
|
if (!(request_format && pmedium))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
pmedium->hGlobal = nullptr;
|
||||||
|
|
||||||
|
auto entry = find(*request_format, true);
|
||||||
|
if (entry)
|
||||||
|
return _m_copy_medium(pmedium, &entry->medium, &entry->format);
|
||||||
|
|
||||||
|
return DV_E_FORMATETC;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium) override
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP QueryGetData(FORMATETC *pformatetc) override
|
||||||
|
{
|
||||||
|
if (NULL == pformatetc)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (!(DVASPECT_CONTENT & pformatetc->dwAspect))
|
||||||
|
return DV_E_DVASPECT;
|
||||||
|
|
||||||
|
HRESULT result = DV_E_TYMED;
|
||||||
|
|
||||||
|
for (auto & entry : entries_)
|
||||||
{
|
{
|
||||||
if (NULL == ppenumFormatEtc)
|
if (entry->format.tymed & pformatetc->tymed)
|
||||||
|
{
|
||||||
|
if (entry->format.cfFormat == pformatetc->cfFormat)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
result = DV_E_FORMATETC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut) override
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease) override
|
||||||
|
{
|
||||||
|
if (!(pformatetc && pmedium))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (pformatetc->tymed != pmedium->tymed)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
entries_.emplace_back(new data_entry);
|
||||||
|
auto entry = entries_.back().get();
|
||||||
|
|
||||||
|
entry->format = *pformatetc;
|
||||||
|
|
||||||
|
_m_copy_medium(&entry->medium, pmedium, pformatetc);
|
||||||
|
|
||||||
|
if (TRUE == fRelease)
|
||||||
|
::ReleaseStgMedium(pmedium);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) override
|
||||||
|
{
|
||||||
|
if (NULL == ppenumFormatEtc)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (DATADIR_GET != dwDirection)
|
||||||
|
return E_NOTIMPL;
|
||||||
|
|
||||||
|
*ppenumFormatEtc = nullptr;
|
||||||
|
|
||||||
|
FORMATETC rgfmtetc[] =
|
||||||
|
{
|
||||||
|
//{ CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, 0, TYMED_HGLOBAL }
|
||||||
|
{ CF_HDROP, nullptr, DVASPECT_CONTENT, 0, TYMED_HGLOBAL }
|
||||||
|
};
|
||||||
|
return ::SHCreateStdEnumFmtEtc(ARRAYSIZE(rgfmtetc), rgfmtetc, ppenumFormatEtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) override
|
||||||
|
{
|
||||||
|
return OLE_E_ADVISENOTSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP DUnadvise(DWORD dwConnection) override
|
||||||
|
{
|
||||||
|
return OLE_E_ADVISENOTSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise) override
|
||||||
|
{
|
||||||
|
return OLE_E_ADVISENOTSUPPORTED;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static HRESULT _m_copy_medium(STGMEDIUM* stgmed_dst, STGMEDIUM* stgmed_src, FORMATETC* fmt_src)
|
||||||
|
{
|
||||||
|
if (!(stgmed_dst && stgmed_src && fmt_src))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
switch (stgmed_src->tymed)
|
||||||
|
{
|
||||||
|
case TYMED_HGLOBAL:
|
||||||
|
stgmed_dst->hGlobal = (HGLOBAL)OleDuplicateData(stgmed_src->hGlobal, fmt_src->cfFormat, 0);
|
||||||
|
break;
|
||||||
|
case TYMED_GDI:
|
||||||
|
case TYMED_ENHMF:
|
||||||
|
//GDI object can't be copied to an existing HANDLE
|
||||||
|
if (stgmed_dst->hGlobal)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if (DATADIR_GET != dwDirection)
|
stgmed_dst->hGlobal = (HBITMAP)OleDuplicateData(stgmed_src->hGlobal, fmt_src->cfFormat, 0);
|
||||||
return E_NOTIMPL;
|
break;
|
||||||
|
case TYMED_MFPICT:
|
||||||
*ppenumFormatEtc = nullptr;
|
stgmed_dst->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(stgmed_src->hMetaFilePict, fmt_src->cfFormat, 0);
|
||||||
|
break;
|
||||||
FORMATETC rgfmtetc[] =
|
case TYMED_FILE:
|
||||||
{
|
stgmed_dst->lpszFileName = (LPOLESTR)OleDuplicateData(stgmed_src->lpszFileName, fmt_src->cfFormat, 0);
|
||||||
//{ CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, 0, TYMED_HGLOBAL }
|
break;
|
||||||
{ CF_HDROP, nullptr, DVASPECT_CONTENT, 0, TYMED_HGLOBAL }
|
case TYMED_ISTREAM:
|
||||||
};
|
stgmed_dst->pstm = stgmed_src->pstm;
|
||||||
return ::SHCreateStdEnumFmtEtc(ARRAYSIZE(rgfmtetc), rgfmtetc, ppenumFormatEtc);
|
stgmed_src->pstm->AddRef();
|
||||||
|
break;
|
||||||
|
case TYMED_ISTORAGE:
|
||||||
|
stgmed_dst->pstg = stgmed_src->pstg;
|
||||||
|
stgmed_src->pstg->AddRef();
|
||||||
|
break;
|
||||||
|
case TYMED_NULL:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
stgmed_dst->tymed = stgmed_src->tymed;
|
||||||
STDMETHODIMP DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) override
|
stgmed_dst->pUnkForRelease = nullptr;
|
||||||
|
if (stgmed_src->pUnkForRelease)
|
||||||
{
|
{
|
||||||
return OLE_E_ADVISENOTSUPPORTED;
|
stgmed_dst->pUnkForRelease = stgmed_src->pUnkForRelease;
|
||||||
|
stgmed_src->pUnkForRelease->AddRef();
|
||||||
}
|
}
|
||||||
|
return S_OK;
|
||||||
STDMETHODIMP DUnadvise(DWORD dwConnection) override
|
}
|
||||||
{
|
private:
|
||||||
return OLE_E_ADVISENOTSUPPORTED;
|
std::vector<std::unique_ptr<data_entry>> entries_;
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise) override
|
|
||||||
{
|
|
||||||
return OLE_E_ADVISENOTSUPPORTED;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
static HRESULT _m_copy_medium(STGMEDIUM* stgmed_dst, STGMEDIUM* stgmed_src, FORMATETC* fmt_src)
|
|
||||||
{
|
|
||||||
if (!(stgmed_dst && stgmed_src && fmt_src))
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
switch (stgmed_src->tymed)
|
|
||||||
{
|
|
||||||
case TYMED_HGLOBAL:
|
|
||||||
stgmed_dst->hGlobal = (HGLOBAL)OleDuplicateData(stgmed_src->hGlobal, fmt_src->cfFormat, 0);
|
|
||||||
break;
|
|
||||||
case TYMED_GDI:
|
|
||||||
case TYMED_ENHMF:
|
|
||||||
//GDI object can't be copied to an existing HANDLE
|
|
||||||
if (stgmed_dst->hGlobal)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
stgmed_dst->hGlobal = (HBITMAP)OleDuplicateData(stgmed_src->hGlobal, fmt_src->cfFormat, 0);
|
|
||||||
break;
|
|
||||||
case TYMED_MFPICT:
|
|
||||||
stgmed_dst->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(stgmed_src->hMetaFilePict, fmt_src->cfFormat, 0);
|
|
||||||
break;
|
|
||||||
case TYMED_FILE:
|
|
||||||
stgmed_dst->lpszFileName = (LPOLESTR)OleDuplicateData(stgmed_src->lpszFileName, fmt_src->cfFormat, 0);
|
|
||||||
break;
|
|
||||||
case TYMED_ISTREAM:
|
|
||||||
stgmed_dst->pstm = stgmed_src->pstm;
|
|
||||||
stgmed_src->pstm->AddRef();
|
|
||||||
break;
|
|
||||||
case TYMED_ISTORAGE:
|
|
||||||
stgmed_dst->pstg = stgmed_src->pstg;
|
|
||||||
stgmed_src->pstg->AddRef();
|
|
||||||
break;
|
|
||||||
case TYMED_NULL:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stgmed_dst->tymed = stgmed_src->tymed;
|
|
||||||
stgmed_dst->pUnkForRelease = nullptr;
|
|
||||||
if (stgmed_src->pUnkForRelease)
|
|
||||||
{
|
|
||||||
stgmed_dst->pUnkForRelease = stgmed_src->pUnkForRelease;
|
|
||||||
stgmed_src->pUnkForRelease->AddRef();
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::vector<std::unique_ptr<data_entry>> entries_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using win32_dropdata = win32com_iunknown<win32_dropdata_impl, IID_IDataObject>;
|
||||||
|
|
||||||
|
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
class x11_dropdata
|
class x11_dropdata
|
||||||
@ -710,7 +721,7 @@ namespace nana
|
|||||||
i->second->set_current_source(drag_wd);
|
i->second->set_current_source(drag_wd);
|
||||||
|
|
||||||
DWORD result_effect{ DROPEFFECT_NONE };
|
DWORD result_effect{ DROPEFFECT_NONE };
|
||||||
auto status = ::DoDragDrop(dropdata, drop_src, DROPEFFECT_COPY, &result_effect);
|
::DoDragDrop(dropdata, drop_src, DROPEFFECT_COPY, &result_effect);
|
||||||
|
|
||||||
i->second->set_current_source(nullptr);
|
i->second->set_current_source(nullptr);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user