#include "wx/log.h"
#ifdef __WIN32__
- #ifndef __GNUWIN32__
+ #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
#include <shlobj.h> // for DROPFILES structure
#endif
#else
class wxIDropTarget : public IDropTarget
{
public:
- wxIDropTarget(wxDropTarget *p);
- ~wxIDropTarget();
+ wxIDropTarget(wxDropTarget *p);
+ // suppress gcc warning
+#ifdef __GNUG__
+ virtual
+#endif
+ ~wxIDropTarget();
+
+ // accessors for wxDropTarget
+ void SetHwnd(HWND hwnd) { m_hwnd = hwnd; }
- // IDropTarget methods
- STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
- STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD);
- STDMETHODIMP DragLeave(void);
- STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
+ // IDropTarget methods
+ STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
+ STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD);
+ STDMETHODIMP DragLeave();
+ STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD);
- DECLARE_IUNKNOWN_METHODS;
+ DECLARE_IUNKNOWN_METHODS;
protected:
- IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop
- wxDropTarget *m_pTarget; // the real target (we're just a proxy)
+ IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop
+ wxDropTarget *m_pTarget; // the real target (we're just a proxy)
-private:
- static inline DWORD GetDropEffect(DWORD flags);
+ HWND m_hwnd; // window we're associated with
+
+ // get default drop effect for given keyboard flags
+ static inline DWORD GetDropEffect(DWORD flags);
};
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+static wxDragResult ConvertDragEffectToResult(DWORD dwEffect);
+static DWORD ConvertDragResultToEffect(wxDragResult result);
+
// ============================================================================
// wxIDropTarget implementation
// ============================================================================
-// Name : static wxDropTarget::GetDropEffect
+// Name : static wxIDropTarget::GetDropEffect
// Purpose : determine the drop operation from keyboard/mouse state.
// Returns : DWORD combined from DROPEFFECT_xxx constants
// Params : [in] DWORD flags kbd & mouse flags as passed to
POINTL pt,
DWORD *pdwEffect)
{
- wxLogDebug(wxT("IDropTarget::DragEnter"));
+ wxLogDebug(wxT("IDropTarget::DragEnter"));
- wxASSERT( m_pIDataObject == NULL );
+ wxASSERT( m_pIDataObject == NULL );
- if ( !m_pTarget->IsAcceptedData(pIDataSource) ) {
- // we don't accept this kind of data
- *pdwEffect = DROPEFFECT_NONE;
-
- return S_OK;
- }
+ if ( !m_pTarget->IsAcceptedData(pIDataSource) ) {
+ // we don't accept this kind of data
+ *pdwEffect = DROPEFFECT_NONE;
- // TODO should check the point also?
+ return S_OK;
+ }
- *pdwEffect = GetDropEffect(grfKeyState);
+ // get hold of the data object
+ m_pIDataObject = pIDataSource;
+ m_pIDataObject->AddRef();
- // get hold of the data object
- m_pIDataObject = pIDataSource;
- m_pIDataObject->AddRef();
+ // we need client coordinates to pass to wxWin functions
+ if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
+ {
+ wxLogLastError(wxT("ScreenToClient"));
+ }
- // give some visual feedback
- m_pTarget->OnEnter();
+ // give some visual feedback
+ *pdwEffect = ConvertDragResultToEffect(
+ m_pTarget->OnEnter(pt.x, pt.y,
+ ConvertDragEffectToResult(GetDropEffect(grfKeyState))
+ )
+ );
- return S_OK;
+ return S_OK;
}
// Name : wxIDropTarget::DragOver
POINTL pt,
LPDWORD pdwEffect)
{
- // there are too many of them... wxLogDebug("IDropTarget::DragOver");
+ // there are too many of them... wxLogDebug("IDropTarget::DragOver");
- *pdwEffect = m_pIDataObject == NULL ? DROPEFFECT_NONE
- : GetDropEffect(grfKeyState);
- return S_OK;
+ wxDragResult result;
+ if ( m_pIDataObject ) {
+ result = ConvertDragEffectToResult(GetDropEffect(grfKeyState));
+ }
+ else {
+ // can't accept data anyhow normally
+ result = wxDragNone;
+ }
+
+ // we need client coordinates to pass to wxWin functions
+ if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
+ {
+ wxLogLastError(wxT("ScreenToClient"));
+ }
+
+ *pdwEffect = ConvertDragResultToEffect(
+ m_pTarget->OnDragOver(pt.x, pt.y, result)
+ );
+
+ return S_OK;
}
// Name : wxIDropTarget::DragLeave
// by default, nothing happens
*pdwEffect = DROPEFFECT_NONE;
+ // 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
- if ( m_pTarget->OnData(pt.x, pt.y) ) {
+ wxDragResult rc = ConvertDragEffectToResult(GetDropEffect(grfKeyState));
+ rc = m_pTarget->OnData(pt.x, pt.y, rc);
+ if ( wxIsDragResultOk(rc) ) {
// operation succeeded
- *pdwEffect = GetDropEffect(grfKeyState);
+ *pdwEffect = ConvertDragResultToEffect(rc);
}
//else: *pdwEffect is already DROPEFFECT_NONE
}
return FALSE;
}
+ // we will need the window handle for coords transformation later
+ m_pIDropTarget->SetHwnd((HWND)hwnd);
+
return TRUE;
}
}
::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
+
+ m_pIDropTarget->SetHwnd(0);
}
// ----------------------------------------------------------------------------
rc = TRUE;
}
else {
- wxLogLastError("IDataObject::SetData()");
+ wxLogLastError(wxT("IDataObject::SetData()"));
}
}
else {
- wxLogLastError("IDataObject::GetData()");
+ wxLogLastError(wxT("IDataObject::GetData()"));
}
return rc;
delete [] formats;
}
- return n < nFormats ? format : wxDF_INVALID;
+ return n < nFormats ? format : wxFormatInvalid;
}
// ----------------------------------------------------------------------------
-// wxTextDropTarget
+// private functions
// ----------------------------------------------------------------------------
-wxTextDropTarget::wxTextDropTarget()
- : wxDropTarget(new wxTextDataObject)
-{
-}
-
-bool wxTextDropTarget::OnData(wxCoord x, wxCoord y)
+static wxDragResult ConvertDragEffectToResult(DWORD dwEffect)
{
- if ( !GetData() )
- return FALSE;
+ switch ( dwEffect ) {
+ case DROPEFFECT_COPY:
+ return wxDragCopy;
- return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText());
-}
+ case DROPEFFECT_MOVE:
+ return wxDragMove;
-// ----------------------------------------------------------------------------
-// wxFileDropTarget
-// ----------------------------------------------------------------------------
+ default:
+ wxFAIL_MSG(wxT("invalid value in ConvertDragEffectToResult"));
+ // fall through
-wxFileDropTarget::wxFileDropTarget()
- : wxDropTarget(new wxFileDataObject)
-{
+ case DROPEFFECT_NONE:
+ return wxDragNone;
+ }
}
-bool wxFileDropTarget::OnData(wxCoord x, wxCoord y)
+static DWORD ConvertDragResultToEffect(wxDragResult result)
{
- if ( !GetData() )
- return FALSE;
+ switch ( result ) {
+ case wxDragCopy:
+ return DROPEFFECT_COPY;
+
+ case wxDragMove:
+ return DROPEFFECT_MOVE;
- return OnDropFiles(x, y,
- ((wxFileDataObject *)m_dataObject)->GetFilenames());
+ default:
+ wxFAIL_MSG(wxT("invalid value in ConvertDragResultToEffect"));
+ // fall through
+
+ case wxDragNone:
+ return DROPEFFECT_NONE;
+ }
}
#endif