]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/ole/droptgt.cpp
fixed several problems due to use of GetEditHWND() when the edit control is not available
[wxWidgets.git] / src / msw / ole / droptgt.cpp
index 8bc18646cdaf746ee8c2315e99ed65632639f754..4601d19be486af54ee3d6ab37280729da0cacabc 100644 (file)
@@ -1,12 +1,12 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        ole/droptgt.cpp
+// Name:        src/msw/ole/droptgt.cpp
 // Purpose:     wxDropTarget implementation
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
 // Purpose:     wxDropTarget implementation
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 ///////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 // headers
 // ----------------------------------------------------------------------------
 
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-#pragma implementation "droptgt.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #if defined(__BORLANDC__)
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #if defined(__BORLANDC__)
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #endif
 
-#include "wx/setup.h"
-
 #if wxUSE_OLE && wxUSE_DRAG_AND_DROP
 
 #if wxUSE_OLE && wxUSE_DRAG_AND_DROP
 
-#include "wx/log.h"
+#ifndef WX_PRECOMP
+    #include "wx/msw/wrapwin.h"
+    #include "wx/log.h"
+#endif
+
+#include "wx/msw/private.h"
+
+#ifdef __WXWINCE__
+    #include <winreg.h>
+    #include <ole2.h>
+#endif
 
 #ifdef __WIN32__
     #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
 
 #ifdef __WIN32__
     #if !defined(__GNUWIN32__) || wxUSE_NORLANDER_HEADERS
-        #if wxCHECK_W32API_VERSION( 1, 0 )
-            #include <windows.h>
-        #endif
         #include <shlobj.h>            // for DROPFILES structure
     #endif
 #else
         #include <shlobj.h>            // for DROPFILES structure
     #endif
 #else
 
 #include "wx/dnd.h"
 
 
 #include "wx/dnd.h"
 
-#ifndef __WIN32__
-    #include <ole2.h>
-    #include <olestd.h>
-#endif
-
 #include "wx/msw/ole/oleutils.h"
 
 // ----------------------------------------------------------------------------
 #include "wx/msw/ole/oleutils.h"
 
 // ----------------------------------------------------------------------------
@@ -84,7 +80,9 @@ protected:
     HWND          m_hwnd;         // window we're associated with
 
     // get default drop effect for given keyboard flags
     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)
 };
 
 // ----------------------------------------------------------------------------
 };
 
 // ----------------------------------------------------------------------------
@@ -101,19 +99,43 @@ 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
 // 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)
 // 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)
+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)
 {
 }
 
 wxIDropTarget::wxIDropTarget(wxDropTarget *pTarget)
 {
-  m_cRef         = 0;
   m_pTarget      = pTarget;
   m_pIDataObject = NULL;
 }
   m_pTarget      = pTarget;
   m_pIDataObject = NULL;
 }
@@ -132,10 +154,12 @@ IMPLEMENT_IUNKNOWN_METHODS(wxIDropTarget)
 // Name    : wxIDropTarget::DragEnter
 // Purpose : Called when the mouse enters the window (dragging something)
 // Returns : S_OK
 // 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,
 // Notes   :
 STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
                                       DWORD        grfKeyState,
@@ -148,7 +172,7 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
                   _T("drop target must have data object") );
 
     // show the list of formats supported by the source data object for the
                   _T("drop target must have data object") );
 
     // show the list of formats supported by the source data object for the
-    // debugging purposes
+    // debugging purposes, this is quite useful sometimes - please don't remove
 #if 0
     IEnumFORMATETC *penumFmt;
     if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) )
 #if 0
     IEnumFORMATETC *penumFmt;
     if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) )
@@ -187,8 +211,8 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource,
 
     // give some visual feedback
     *pdwEffect = ConvertDragResultToEffect(
 
     // 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))
                     )
                  );
 
                     )
                  );
 
@@ -199,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
 // 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,
 // Notes   : We're called on every WM_MOUSEMOVE, so this function should be
 //           very efficient.
 STDMETHODIMP wxIDropTarget::DragOver(DWORD   grfKeyState,
@@ -212,7 +236,8 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD   grfKeyState,
 
     wxDragResult result;
     if ( m_pIDataObject ) {
 
     wxDragResult result;
     if ( m_pIDataObject ) {
-        result = ConvertDragEffectToResult(GetDropEffect(grfKeyState));
+        result = ConvertDragEffectToResult(
+            GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect));
     }
     else {
         // can't accept data anyhow normally
     }
     else {
         // can't accept data anyhow normally
@@ -253,10 +278,10 @@ STDMETHODIMP wxIDropTarget::DragLeave()
 // Purpose : Instructs the drop target to paste data that was just now
 //           dropped on it.
 // Returns : 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 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,
 // Notes   :
 STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
                                  DWORD        grfKeyState,
@@ -269,9 +294,6 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
     //      that it's the same we've already got in DragEnter
     wxASSERT( m_pIDataObject == 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) )
     {
     // we need client coordinates to pass to wxWin functions
     if ( !ScreenToClient(m_hwnd, (POINT *)&pt) )
     {
@@ -284,15 +306,21 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource,
         m_pTarget->SetDataSource(pIDataSource);
 
         // and now it has the data
         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);
         }
         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);
 
     // release the held object
     RELEASE_AND_NULL(m_pIDataObject);
@@ -328,48 +356,72 @@ wxDropTarget::~wxDropTarget()
 
 bool wxDropTarget::Register(WXHWND hwnd)
 {
 
 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(wxT("CoLockObjectExternal"), hr);
     if ( FAILED(hr) ) {
         wxLogApiError(wxT("CoLockObjectExternal"), hr);
-        return FALSE;
+        return false;
     }
     }
+#endif
 
     hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
     if ( FAILED(hr) ) {
 
     hr = ::RegisterDragDrop((HWND) hwnd, m_pIDropTarget);
     if ( FAILED(hr) ) {
+    // May exist in later WinCE versions
+#ifndef __WXWINCE__
         ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
         ::CoLockObjectExternal(m_pIDropTarget, FALSE, FALSE);
-
+#endif
         wxLogApiError(wxT("RegisterDragDrop"), hr);
         wxLogApiError(wxT("RegisterDragDrop"), hr);
-        return FALSE;
+        return false;
     }
 
     // we will need the window handle for coords transformation later
     m_pIDropTarget->SetHwnd((HWND)hwnd);
 
     }
 
     // we will need the window handle for coords transformation later
     m_pIDropTarget->SetHwnd((HWND)hwnd);
 
-    return TRUE;
+    return true;
+#endif
 }
 
 void wxDropTarget::Revoke(WXHWND hwnd)
 {
 }
 
 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);
     }
 
     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);
     ::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE);
+#endif
 
     m_pIDropTarget->SetHwnd(0);
 
     m_pIDropTarget->SetHwnd(0);
+#endif
 }
 
 // ----------------------------------------------------------------------------
 // base class pure virtuals
 // ----------------------------------------------------------------------------
 
 }
 
 // ----------------------------------------------------------------------------
 // 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))
 {
 // 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
 }
 
 // copy the data from the data source to the target data object
@@ -380,7 +432,7 @@ bool wxDropTarget::GetData()
         // this is strange because IsAcceptedData() succeeded previously!
         wxFAIL_MSG(wxT("strange - did supported formats list change?"));
 
         // this is strange because IsAcceptedData() succeeded previously!
         wxFAIL_MSG(wxT("strange - did supported formats list change?"));
 
-        return FALSE;
+        return false;
     }
 
     STGMEDIUM stm;
     }
 
     STGMEDIUM stm;
@@ -391,7 +443,7 @@ bool wxDropTarget::GetData()
     fmtMemory.lindex    = -1;
     fmtMemory.tymed     = TYMED_HGLOBAL;  // TODO to add other media
 
     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) ) {
 
     HRESULT hr = m_pIDataSource->GetData(&fmtMemory, &stm);
     if ( SUCCEEDED(hr) ) {
@@ -399,14 +451,14 @@ bool wxDropTarget::GetData()
 
         hr = dataObject->SetData(&fmtMemory, &stm, TRUE);
         if ( SUCCEEDED(hr) ) {
 
         hr = dataObject->SetData(&fmtMemory, &stm, TRUE);
         if ( SUCCEEDED(hr) ) {
-            rc = TRUE;
+            rc = true;
         }
         else {
         }
         else {
-            wxLogLastError(wxT("IDataObject::SetData()"));
+            wxLogApiError(wxT("IDataObject::SetData()"), hr);
         }
     }
     else {
         }
     }
     else {
-        wxLogLastError(wxT("IDataObject::GetData()"));
+        wxLogApiError(wxT("IDataObject::GetData()"), hr);
     }
 
     return rc;
     }
 
     return rc;
@@ -484,6 +536,9 @@ static wxDragResult ConvertDragEffectToResult(DWORD dwEffect)
         case DROPEFFECT_COPY:
             return wxDragCopy;
 
         case DROPEFFECT_COPY:
             return wxDragCopy;
 
+        case DROPEFFECT_LINK:
+            return wxDragLink;
+
         case DROPEFFECT_MOVE:
             return wxDragMove;
 
         case DROPEFFECT_MOVE:
             return wxDragMove;
 
@@ -502,6 +557,9 @@ static DWORD ConvertDragResultToEffect(wxDragResult result)
         case wxDragCopy:
             return DROPEFFECT_COPY;
 
         case wxDragCopy:
             return DROPEFFECT_COPY;
 
+        case wxDragLink:
+            return DROPEFFECT_LINK;
+
         case wxDragMove:
             return DROPEFFECT_MOVE;
 
         case wxDragMove:
             return DROPEFFECT_MOVE;
 
@@ -514,5 +572,4 @@ static DWORD ConvertDragResultToEffect(wxDragResult result)
     }
 }
 
     }
 }
 
-#endif
- // wxUSE_DRAG_AND_DROP
+#endif // wxUSE_OLE && wxUSE_DRAG_AND_DROP