📄 droptgt.cpp
字号:
// we need client coordinates to pass to wxWin functions
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
{
wxLogLastError(wxT("ScreenToClient"));
}
// first ask the drop target if it wants data
if ( m_pTarget->OnDrop(pt.x, pt.y) ) {
// it does, so give it the data source
m_pTarget->SetDataSource(pIDataSource);
// and now it has the data
wxDragResult rc = ConvertDragEffectToResult(
GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction()));
rc = m_pTarget->OnData(pt.x, pt.y, rc);
if ( wxIsDragResultOk(rc) ) {
// operation succeeded
*pdwEffect = ConvertDragResultToEffect(rc);
}
//else: *pdwEffect is already DROPEFFECT_NONE
}
//else: OnDrop() returned false, no need to copy data
// release the held object
RELEASE_AND_NULL(m_pIDataObject);
return S_OK;
}
// ============================================================================
// wxDropTarget implementation
// ============================================================================
// ----------------------------------------------------------------------------
// ctor/dtor
// ----------------------------------------------------------------------------
wxDropTarget::wxDropTarget(wxDataObject *dataObj)
: wxDropTargetBase(dataObj)
{
// create an IDropTarget implementation which will notify us about d&d
// operations.
m_pIDropTarget = new wxIDropTarget(this);
m_pIDropTarget->AddRef();
}
wxDropTarget::~wxDropTarget()
{
ReleaseInterface(m_pIDropTarget);
}
// ----------------------------------------------------------------------------
// [un]register drop handler
// ----------------------------------------------------------------------------
bool wxDropTarget::Register(WXHWND hwnd)
{
// FIXME
// RegisterDragDrop not available on Windows CE >= 400?
// Or maybe we can dynamically load them from ceshell.dll
// or similar.
#if defined(__WXWINCE__) && _WIN32_WCE >= 400
wxUnusedVar(hwnd);
return false;
#else
HRESULT hr;
// May exist in later WinCE versions
#ifndef __WXWINCE__
hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE);
if ( FAILED(hr) ) {
wxLogApiError(wxT("CoLockObjectExternal"), hr);
return false;
}
#endif
hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
if ( FAILED(hr) ) {
// May exist in later WinCE versions
#ifndef __WXWINCE__
::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
#endif
wxLogApiError(wxT("RegisterDragDrop"), hr);
return false;
}
// we will need the window handle for coords transformation later
m_pIDropTarget->SetHwnd((HWND)hwnd);
return true;
#endif
}
void wxDropTarget::Revoke(WXHWND hwnd)
{
#if defined(__WXWINCE__) && _WIN32_WCE >= 400
// Not available, see note above
wxUnusedVar(hwnd);
#else
HRESULT hr = ::RevokeDragDrop((HWND) hwnd);
if ( FAILED(hr) ) {
wxLogApiError(wxT("RevokeDragDrop"), hr);
}
// May exist in later WinCE versions
#ifndef __WXWINCE__
::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
#endif
m_pIDropTarget->SetHwnd(0);
#endif
}
// ----------------------------------------------------------------------------
// base class pure virtuals
// ----------------------------------------------------------------------------
// OnDrop() is called only if we previously returned true from
// IsAcceptedData(), so no need to check anything here
bool wxDropTarget::OnDrop(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y))
{
return true;
}
// copy the data from the data source to the target data object
bool wxDropTarget::GetData()
{
wxDataFormat format = GetSupportedFormat(m_pIDataSource);
if ( format == wxDF_INVALID ) {
// this is strange because IsAcceptedData() succeeded previously!
wxFAIL_MSG(wxT("strange - did supported formats list change?"));
return false;
}
STGMEDIUM stm;
FORMATETC fmtMemory;
fmtMemory.cfFormat = format;
fmtMemory.ptd = NULL;
fmtMemory.dwAspect = DVASPECT_CONTENT;
fmtMemory.lindex = -1;
fmtMemory.tymed = TYMED_HGLOBAL; // TODO to add other media
bool rc = false;
HRESULT hr = m_pIDataSource->GetData(&fmtMemory, &stm);
if ( SUCCEEDED(hr) ) {
IDataObject *dataObject = m_dataObject->GetInterface();
hr = dataObject->SetData(&fmtMemory, &stm, TRUE);
if ( SUCCEEDED(hr) ) {
rc = true;
}
else {
wxLogApiError(wxT("IDataObject::SetData()"), hr);
}
}
else {
wxLogApiError(wxT("IDataObject::GetData()"), hr);
}
return rc;
}
// ----------------------------------------------------------------------------
// callbacks used by wxIDropTarget
// ----------------------------------------------------------------------------
// we need a data source, so wxIDropTarget gives it to us using this function
void wxDropTarget::SetDataSource(IDataObject *pIDataSource)
{
m_pIDataSource = pIDataSource;
}
// determine if we accept data of this type
bool wxDropTarget::IsAcceptedData(IDataObject *pIDataSource) const
{
return GetSupportedFormat(pIDataSource) != wxDF_INVALID;
}
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const
{
// this strucutre describes a data of any type (first field will be
// changing) being passed through global memory block.
static FORMATETC s_fmtMemory = {
0,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL // TODO is it worth supporting other tymeds here?
};
// get the list of supported formats
size_t nFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
wxDataFormat format;
wxDataFormat *formats;
formats = nFormats == 1 ? &format : new wxDataFormat[nFormats];
m_dataObject->GetAllFormats(formats, wxDataObject::Set);
// cycle through all supported formats
size_t n;
for ( n = 0; n < nFormats; n++ ) {
s_fmtMemory.cfFormat = formats[n];
// NB: don't use SUCCEEDED macro here: QueryGetData returns S_FALSE
// for file drag and drop (format == CF_HDROP)
if ( pIDataSource->QueryGetData(&s_fmtMemory) == S_OK ) {
format = formats[n];
break;
}
}
if ( formats != &format ) {
// free memory if we allocated it
delete [] formats;
}
return n < nFormats ? format : wxFormatInvalid;
}
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
static wxDragResult ConvertDragEffectToResult(DWORD dwEffect)
{
switch ( dwEffect ) {
case DROPEFFECT_COPY:
return wxDragCopy;
case DROPEFFECT_LINK:
return wxDragLink;
case DROPEFFECT_MOVE:
return wxDragMove;
default:
wxFAIL_MSG(wxT("invalid value in ConvertDragEffectToResult"));
// fall through
case DROPEFFECT_NONE:
return wxDragNone;
}
}
static DWORD ConvertDragResultToEffect(wxDragResult result)
{
switch ( result ) {
case wxDragCopy:
return DROPEFFECT_COPY;
case wxDragLink:
return DROPEFFECT_LINK;
case wxDragMove:
return DROPEFFECT_MOVE;
default:
wxFAIL_MSG(wxT("invalid value in ConvertDragResultToEffect"));
// fall through
case wxDragNone:
return DROPEFFECT_NONE;
}
}
#endif // wxUSE_OLE && wxUSE_DRAG_AND_DROP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -