X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1a7f306263595bff3b74e96e4c2bee6f0a008500..98af9c738332c9a24475ad19efbfabe2b152c429:/src/msw/ole/droptgt.cpp?ds=sidebyside diff --git a/src/msw/ole/droptgt.cpp b/src/msw/ole/droptgt.cpp index 897e2279dd..0362766a9f 100644 --- a/src/msw/ole/droptgt.cpp +++ b/src/msw/ole/droptgt.cpp @@ -6,7 +6,7 @@ // Created: // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ -#pragma implementation "droptgt.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -30,12 +26,21 @@ #include "wx/setup.h" -#if wxUSE_DRAG_AND_DROP +#if wxUSE_OLE && wxUSE_DRAG_AND_DROP +#include "wx/msw/private.h" #include "wx/log.h" +#ifdef __WXWINCE__ + #include + #include +#endif + #ifdef __WIN32__ - #ifndef __GNUWIN32__ + #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS + #if wxCHECK_W32API_VERSION( 1, 0 ) + #include "wx/msw/wrapwin.h" + #endif #include // for DROPFILES structure #endif #else @@ -44,11 +49,6 @@ #include "wx/dnd.h" -#ifndef __WIN32__ - #include - #include -#endif - #include "wx/msw/ole/oleutils.h" // ---------------------------------------------------------------------------- @@ -60,23 +60,30 @@ class wxIDropTarget : public IDropTarget { public: - wxIDropTarget(wxDropTarget *p); - ~wxIDropTarget(); + wxIDropTarget(wxDropTarget *p); + virtual ~wxIDropTarget(); - // IDropTarget methods - STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD); - STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD); - STDMETHODIMP DragLeave(void); - STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD); + // accessors for wxDropTarget + void SetHwnd(HWND hwnd) { m_hwnd = hwnd; } - DECLARE_IUNKNOWN_METHODS; + // IDropTarget methods + STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD); + STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD); + STDMETHODIMP DragLeave(); + STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD); + + 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) + + HWND m_hwnd; // window we're associated with -private: - static inline DWORD GetDropEffect(DWORD flags); + // get default drop effect for given keyboard flags + static inline DWORD GetDropEffect(DWORD flags, wxDragResult defaultAction); + + DECLARE_NO_COPY_CLASS(wxIDropTarget) }; // ---------------------------------------------------------------------------- @@ -90,7 +97,7 @@ 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 @@ -98,14 +105,15 @@ static DWORD ConvertDragResultToEffect(wxDragResult result); // 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) { + if (defaultAction == wxDragCopy) + return flags & MK_SHIFT ? DROPEFFECT_MOVE : DROPEFFECT_COPY; return flags & MK_CONTROL ? DROPEFFECT_COPY : DROPEFFECT_MOVE; } wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget) { - m_cRef = 0; m_pTarget = pTarget; m_pIDataObject = NULL; } @@ -134,31 +142,57 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource, POINTL pt, DWORD *pdwEffect) { - wxLogDebug(wxT("IDropTarget::DragEnter")); + wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter")); + + wxASSERT_MSG( m_pIDataObject == NULL, + _T("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 +#if 0 + IEnumFORMATETC *penumFmt; + if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) ) + { + FORMATETC fmt; + while ( penumFmt->Next(1, &fmt, NULL) == S_OK ) + { + wxLogDebug(_T("Drop source supports format %s"), + wxDataObject::GetFormatName(fmt.cfFormat)); + } - wxASSERT( m_pIDataObject == NULL ); + penumFmt->Release(); + } + else + { + wxLogLastError(_T("IDataObject::EnumFormatEtc")); + } +#endif // 0 - if ( !m_pTarget->IsAcceptedData(pIDataSource) ) { - // we don't accept this kind of data - *pdwEffect = DROPEFFECT_NONE; + if ( !m_pTarget->IsAcceptedData(pIDataSource) ) { + // we don't accept this kind of data + *pdwEffect = DROPEFFECT_NONE; - return S_OK; - } + return S_OK; + } + + // 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 - *pdwEffect = ConvertDragResultToEffect( - m_pTarget->OnEnter(pt.x, pt.y, - ConvertDragEffectToResult( - GetDropEffect(grfKeyState) - ) - ) - ); + // give some visual feedback + *pdwEffect = ConvertDragResultToEffect( + m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult( + GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction())) + ) + ); - return S_OK; + return S_OK; } // Name : wxIDropTarget::DragOver @@ -174,22 +208,29 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { - // there are too many of them... wxLogDebug("IDropTarget::DragOver"); + // there are too many of them... wxLogDebug("IDropTarget::DragOver"); + + wxDragResult result; + if ( m_pIDataObject ) { + result = ConvertDragEffectToResult( + GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction())); + } + else { + // can't accept data anyhow normally + result = wxDragNone; + } - 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) - ); + *pdwEffect = ConvertDragResultToEffect( + m_pTarget->OnDragOver(pt.x, pt.y, result) + ); - return S_OK; + return S_OK; } // Name : wxIDropTarget::DragLeave @@ -198,7 +239,7 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState, // Notes : good place to do any clean-up STDMETHODIMP wxIDropTarget::DragLeave() { - wxLogDebug(wxT("IDropTarget::DragLeave")); + wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragLeave")); // remove the UI feedback m_pTarget->OnLeave(); @@ -215,7 +256,7 @@ STDMETHODIMP wxIDropTarget::DragLeave() // Returns : S_OK // Params : [in] IDataObject *pIDataSource the data to paste // [in] DWORD grfKeyState kbd & mouse state -// [in] POINTL pt where the drop occured? +// [in] POINTL pt where the drop occurred? // [ouy]DWORD *pdwEffect operation effect // Notes : STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource, @@ -223,7 +264,7 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource, POINTL pt, DWORD *pdwEffect) { - wxLogDebug(wxT("IDropTarget::Drop")); + wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::Drop")); // TODO I don't know why there is this parameter, but so far I assume // that it's the same we've already got in DragEnter @@ -232,19 +273,28 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource, // 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, m_pTarget->GetDefaultAction())); + 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 } - //else: OnDrop() returned FALSE, no need to copy data + //else: OnDrop() returned false, no need to copy data // release the held object RELEASE_AND_NULL(m_pIDataObject); @@ -280,43 +330,72 @@ wxDropTarget::~wxDropTarget() bool wxDropTarget::Register(WXHWND hwnd) { - HRESULT hr = ::CoLockObjectExternal(m_pIDropTarget, TRUE, FALSE); + // 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("CoLockObjectExternal", hr); - return FALSE; + 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); - - wxLogApiError("RegisterDragDrop", hr); - return FALSE; +#endif + wxLogApiError(wxT("RegisterDragDrop"), hr); + return false; } - return TRUE; + // 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("RevokeDragDrop", 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 +// 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 @@ -327,7 +406,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; @@ -338,7 +417,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) ) { @@ -346,14 +425,14 @@ bool wxDropTarget::GetData() hr = dataObject->SetData(&fmtMemory, &stm, TRUE); if ( SUCCEEDED(hr) ) { - rc = TRUE; + rc = true; } else { - wxLogLastError("IDataObject::SetData()"); + wxLogApiError(wxT("IDataObject::SetData()"), hr); } } else { - wxLogLastError("IDataObject::GetData()"); + wxLogApiError(wxT("IDataObject::GetData()"), hr); } return rc; @@ -393,7 +472,8 @@ wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const // get the list of supported formats size_t nFormats = m_dataObject->GetFormatCount(wxDataObject::Set); - wxDataFormat format, *formats; + wxDataFormat format; + wxDataFormat *formats; formats = nFormats == 1 ? &format : new wxDataFormat[nFormats]; m_dataObject->GetAllFormats(formats, wxDataObject::Set); @@ -417,42 +497,7 @@ wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const delete [] formats; } - return (n < nFormats) ? (wxDataFormat) format : (wxDataFormat) wxDF_INVALID; -} - -// ---------------------------------------------------------------------------- -// wxTextDropTarget -// ---------------------------------------------------------------------------- - -wxTextDropTarget::wxTextDropTarget() - : wxDropTarget(new wxTextDataObject) -{ -} - -bool wxTextDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText()); -} - -// ---------------------------------------------------------------------------- -// wxFileDropTarget -// ---------------------------------------------------------------------------- - -wxFileDropTarget::wxFileDropTarget() - : wxDropTarget(new wxFileDataObject) -{ -} - -bool wxFileDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropFiles(x, y, - ((wxFileDataObject *)m_dataObject)->GetFilenames()); + return n < nFormats ? format : wxFormatInvalid; } // ---------------------------------------------------------------------------- @@ -465,6 +510,9 @@ static wxDragResult ConvertDragEffectToResult(DWORD dwEffect) case DROPEFFECT_COPY: return wxDragCopy; + case DROPEFFECT_LINK: + return wxDragLink; + case DROPEFFECT_MOVE: return wxDragMove; @@ -483,6 +531,9 @@ static DWORD ConvertDragResultToEffect(wxDragResult result) case wxDragCopy: return DROPEFFECT_COPY; + case wxDragLink: + return DROPEFFECT_LINK; + case wxDragMove: return DROPEFFECT_MOVE;