#if wxUSE_OLE && wxUSE_DRAG_AND_DROP
#ifndef WX_PRECOMP
+ #include "wx/msw/wrapwin.h"
#include "wx/log.h"
#endif
#ifdef __WIN32__
#if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
- #if wxCHECK_W32API_VERSION( 1, 0 )
- #include "wx/msw/wrapwin.h"
- #endif
#include <shlobj.h> // for DROPFILES structure
#endif
#else
HWND m_hwnd; // window we're associated with
// get default drop effect for given keyboard flags
- static inline DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction);
+ static DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction, DWORD pdwEffect);
- DECLARE_NO_COPY_CLASS(wxIDropTarget)
+ wxDECLARE_NO_COPY_CLASS(wxIDropTarget);
};
// ----------------------------------------------------------------------------
// 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
-// IDropTarget methods
+// Params : [in] DWORD flags kbd & mouse flags as passed to
+// IDropTarget methods
+// [in] wxDragResult defaultAction the default action of the drop target
+// [in] DWORD pdwEffect the supported actions of the drop
+// source passed to IDropTarget methods
// Notes : We do "move" normally and "copy" if <Ctrl> is pressed,
// which is the standard behaviour (currently there is no
// way to redefine it)
-DWORD wxIDropTarget::GetDropEffect(DWORD flags, wxDragResult defaultAction)
+DWORD wxIDropTarget::GetDropEffect(DWORD flags,
+ wxDragResult defaultAction,
+ DWORD pdwEffect)
{
- if (defaultAction == wxDragCopy)
- return flags & MK_SHIFT ? DROPEFFECT_MOVE : DROPEFFECT_COPY;
- return flags & MK_CONTROL ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
+ DWORD effectiveAction;
+ if ( defaultAction == wxDragCopy )
+ effectiveAction = flags & MK_SHIFT ? DROPEFFECT_MOVE : DROPEFFECT_COPY;
+ else
+ effectiveAction = flags & MK_CONTROL ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
+
+ if ( !(effectiveAction & pdwEffect) )
+ {
+ // the action is not supported by drag source, fall back to something
+ // that it does support
+ if ( pdwEffect & DROPEFFECT_MOVE )
+ effectiveAction = DROPEFFECT_MOVE;
+ else if ( pdwEffect & DROPEFFECT_COPY )
+ effectiveAction = DROPEFFECT_COPY;
+ else if ( pdwEffect & DROPEFFECT_LINK )
+ effectiveAction = DROPEFFECT_LINK;
+ else
+ effectiveAction = DROPEFFECT_NONE;
+ }
+
+ return effectiveAction;
}
wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
// Name : wxIDropTarget::DragEnter
// Purpose : Called when the mouse enters the window (dragging something)
// Returns : S_OK
-// Params : [in] IDataObject *pIDataSource : source data
-// [in] DWORD grfKeyState : kbd & mouse state
-// [in] POINTL pt : mouse coordinates
-// [out]DWORD *pdwEffect : effect flag
+// Params : [in] IDataObject *pIDataSource : source data
+// [in] DWORD grfKeyState : kbd & mouse state
+// [in] POINTL pt : mouse coordinates
+// [in/out]DWORD *pdwEffect : effect flag
+// In: Supported effects
+// Out: Resulting effect
// Notes :
STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
DWORD grfKeyState,
wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter"));
wxASSERT_MSG( m_pIDataObject == NULL,
- _T("drop target must have data object") );
+ wxT("drop target must have data object") );
// show the list of formats supported by the source data object for the
// debugging purposes, this is quite useful sometimes - please don't remove
FORMATETC fmt;
while ( penumFmt->Next(1, &fmt, NULL) == S_OK )
{
- wxLogDebug(_T("Drop source supports format %s"),
+ wxLogDebug(wxT("Drop source supports format %s"),
wxDataObject::GetFormatName(fmt.cfFormat));
}
}
else
{
- wxLogLastError(_T("IDataObject::EnumFormatEtc"));
+ wxLogLastError(wxT("IDataObject::EnumFormatEtc"));
}
#endif // 0
- if ( !m_pTarget->IsAcceptedData(pIDataSource) ) {
+ if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) {
// we don't accept this kind of data
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
+ // for use in OnEnter and OnDrag calls
+ m_pTarget->MSWSetDataSource(pIDataSource);
+
// get hold of the data object
m_pIDataObject = pIDataSource;
m_pIDataObject->AddRef();
// give some visual feedback
*pdwEffect = ConvertDragResultToEffect(
m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult(
- GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction()))
+ GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect))
)
);
// Purpose : Indicates that the mouse was moved inside the window represented
// by this drop target.
// Returns : S_OK
-// Params : [in] DWORD grfKeyState kbd & mouse state
-// [in] POINTL pt mouse coordinates
-// [out]LPDWORD pdwEffect effect flag
+// Params : [in] DWORD grfKeyState kbd & mouse state
+// [in] POINTL pt mouse coordinates
+// [in/out]LPDWORD pdwEffect current effect flag
// Notes : We're called on every WM_MOUSEMOVE, so this function should be
// very efficient.
STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState,
wxDragResult result;
if ( m_pIDataObject ) {
result = ConvertDragEffectToResult(
- GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction()));
+ GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
}
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"));
- }
+ if ( 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)
- );
+ *pdwEffect = ConvertDragResultToEffect(
+ m_pTarget->OnDragOver(pt.x, pt.y, result)
+ );
+ }
+ else {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
return S_OK;
}
// Purpose : Instructs the drop target to paste data that was just now
// dropped on it.
// Returns : S_OK
-// Params : [in] IDataObject *pIDataSource the data to paste
-// [in] DWORD grfKeyState kbd & mouse state
-// [in] POINTL pt where the drop occurred?
-// [ouy]DWORD *pdwEffect operation effect
+// Params : [in] IDataObject *pIDataSource the data to paste
+// [in] DWORD grfKeyState kbd & mouse state
+// [in] POINTL pt where the drop occurred?
+// [in/out]DWORD *pdwEffect operation effect
// Notes :
STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
DWORD grfKeyState,
// that it's the same we've already got in DragEnter
wxASSERT( m_pIDataObject == pIDataSource );
- // by default, nothing happens
- *pdwEffect = DROPEFFECT_NONE;
-
// we need client coordinates to pass to wxWin functions
if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
{
// 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);
+ m_pTarget->MSWSetDataSource(pIDataSource);
// and now it has the data
wxDragResult rc = ConvertDragEffectToResult(
- GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction()));
+ GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
rc = m_pTarget->OnData(pt.x, pt.y, rc);
if ( wxIsDragResultOk(rc) ) {
// operation succeeded
*pdwEffect = ConvertDragResultToEffect(rc);
}
- //else: *pdwEffect is already DROPEFFECT_NONE
+ else {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ }
+ else {
+ // OnDrop() returned false, no need to copy data
+ *pdwEffect = DROPEFFECT_NONE;
}
- //else: OnDrop() returned false, no need to copy data
// release the held object
RELEASE_AND_NULL(m_pIDataObject);
// copy the data from the data source to the target data object
bool wxDropTarget::GetData()
{
- wxDataFormat format = GetSupportedFormat(m_pIDataSource);
+ wxDataFormat format = MSWGetSupportedFormat(m_pIDataSource);
if ( format == wxDF_INVALID ) {
// this is strange because IsAcceptedData() succeeded previously!
wxFAIL_MSG(wxT("strange - did supported formats list change?"));
// ----------------------------------------------------------------------------
// we need a data source, so wxIDropTarget gives it to us using this function
-void wxDropTarget::SetDataSource(IDataObject *pIDataSource)
+void wxDropTarget::MSWSetDataSource(IDataObject *pIDataSource)
{
m_pIDataSource = pIDataSource;
}
// determine if we accept data of this type
-bool wxDropTarget::IsAcceptedData(IDataObject *pIDataSource) const
+bool wxDropTarget::MSWIsAcceptedData(IDataObject *pIDataSource) const
{
- return GetSupportedFormat(pIDataSource) != wxDF_INVALID;
+ return MSWGetSupportedFormat(pIDataSource) != wxDF_INVALID;
}
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
-wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const
+wxDataFormat wxDropTarget::GetMatchingPair()
+{
+ return MSWGetSupportedFormat( m_pIDataSource );
+}
+
+wxDataFormat wxDropTarget::MSWGetSupportedFormat(IDataObject *pIDataSource) const
{
// this strucutre describes a data of any type (first field will be
// changing) being passed through global memory block.