X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a40b3f5df713bc2c6b670eef1130d2129c9121bf..d53f610c1c224b6a0f58e4009b2bce553b1ff7b9:/src/msw/ole/droptgt.cpp diff --git a/src/msw/ole/droptgt.cpp b/src/msw/ole/droptgt.cpp index 23ff76e111..3ca2761733 100644 --- a/src/msw/ole/droptgt.cpp +++ b/src/msw/ole/droptgt.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: ole/droptgt.cpp +// Name: src/msw/ole/droptgt.cpp // Purpose: wxDropTarget implementation // Author: Vadim Zeitlin // Modified by: @@ -17,23 +17,21 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "droptgt.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #if defined(__BORLANDC__) -#pragma hdrstop + #pragma hdrstop #endif -#include "wx/setup.h" - #if wxUSE_OLE && wxUSE_DRAG_AND_DROP +#ifndef WX_PRECOMP + #include "wx/msw/wrapwin.h" + #include "wx/log.h" +#endif + #include "wx/msw/private.h" -#include "wx/log.h" #ifdef __WXWINCE__ #include @@ -42,9 +40,6 @@ #ifdef __WIN32__ #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS - #if wxCHECK_W32API_VERSION( 1, 0 ) - #include "wx/msw/wrapwin.h" - #endif #include // for DROPFILES structure #endif #else @@ -85,7 +80,7 @@ protected: HWND m_hwnd; // window we're associated with // get default drop effect for given keyboard flags - static inline DWORD GetDropEffect(DWORD flags); + static DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction, DWORD pdwEffect); DECLARE_NO_COPY_CLASS(wxIDropTarget) }; @@ -104,14 +99,39 @@ static DWORD ConvertDragResultToEffect(wxDragResult result); // 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 is pressed, // which is the standard behaviour (currently there is no // way to redefine it) -DWORD wxIDropTarget::GetDropEffect(DWORD flags) +DWORD wxIDropTarget::GetDropEffect(DWORD flags, + wxDragResult defaultAction, + DWORD pdwEffect) { - 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) @@ -134,10 +154,12 @@ IMPLEMENT_IUNKNOWN_METHODS(wxIDropTarget) // 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, @@ -189,8 +211,8 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource, // give some visual feedback *pdwEffect = ConvertDragResultToEffect( - m_pTarget->OnEnter(pt.x, pt.y, - ConvertDragEffectToResult(GetDropEffect(grfKeyState)) + m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult( + GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect)) ) ); @@ -201,9 +223,9 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource, // 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, @@ -214,22 +236,28 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState, wxDragResult result; if ( m_pIDataObject ) { - result = ConvertDragEffectToResult(GetDropEffect(grfKeyState)); + result = ConvertDragEffectToResult( + 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; } @@ -255,10 +283,10 @@ STDMETHODIMP wxIDropTarget::DragLeave() // 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 occured? -// [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, @@ -271,9 +299,6 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource, // 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) ) { @@ -286,15 +311,21 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource, m_pTarget->SetDataSource(pIDataSource); // and now it has the data - wxDragResult rc = ConvertDragEffectToResult(GetDropEffect(grfKeyState)); + wxDragResult rc = ConvertDragEffectToResult( + 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); @@ -335,7 +366,8 @@ bool wxDropTarget::Register(WXHWND hwnd) // Or maybe we can dynamically load them from ceshell.dll // or similar. #if defined(__WXWINCE__) && _WIN32_WCE >= 400 - return FALSE; + wxUnusedVar(hwnd); + return false; #else HRESULT hr; @@ -344,7 +376,7 @@ bool wxDropTarget::Register(WXHWND hwnd) hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE); if ( FAILED(hr) ) { wxLogApiError(wxT("CoLockObjectExternal"), hr); - return FALSE; + return false; } #endif @@ -355,13 +387,13 @@ bool wxDropTarget::Register(WXHWND hwnd) ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE); #endif wxLogApiError(wxT("RegisterDragDrop"), hr); - return FALSE; + return false; } // we will need the window handle for coords transformation later m_pIDropTarget->SetHwnd((HWND)hwnd); - return TRUE; + return true; #endif } @@ -369,6 +401,7 @@ void wxDropTarget::Revoke(WXHWND hwnd) { #if defined(__WXWINCE__) && _WIN32_WCE >= 400 // Not available, see note above + wxUnusedVar(hwnd); #else HRESULT hr = ::RevokeDragDrop((HWND) hwnd); @@ -389,11 +422,11 @@ void wxDropTarget::Revoke(WXHWND hwnd) // base class pure virtuals // ---------------------------------------------------------------------------- -// OnDrop() is called only if we previously returned TRUE from +// 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; + return true; } // copy the data from the data source to the target data object @@ -404,7 +437,7 @@ bool wxDropTarget::GetData() // this is strange because IsAcceptedData() succeeded previously! wxFAIL_MSG(wxT("strange - did supported formats list change?")); - return FALSE; + return false; } STGMEDIUM stm; @@ -415,7 +448,7 @@ bool wxDropTarget::GetData() fmtMemory.lindex = -1; fmtMemory.tymed = TYMED_HGLOBAL; // TODO to add other media - bool rc = FALSE; + bool rc = false; HRESULT hr = m_pIDataSource->GetData(&fmtMemory, &stm); if ( SUCCEEDED(hr) ) { @@ -423,7 +456,7 @@ bool wxDropTarget::GetData() hr = dataObject->SetData(&fmtMemory, &stm, TRUE); if ( SUCCEEDED(hr) ) { - rc = TRUE; + rc = true; } else { wxLogApiError(wxT("IDataObject::SetData()"), hr); @@ -544,5 +577,4 @@ static DWORD ConvertDragResultToEffect(wxDragResult result) } } -#endif - // wxUSE_DRAG_AND_DROP +#endif // wxUSE_OLE && wxUSE_DRAG_AND_DROP