1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/ole/dropsrc.cpp 
   3 // Purpose:     implementation of wxIDropSource and wxDropSource 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21   #pragma implementation "dropsrc.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  27 #if defined(__BORLANDC__) 
  31 #include "wx/window.h" 
  36 #if wxUSE_OLE && wxUSE_DRAG_AND_DROP 
  41 #include "wx/msw/private.h" 
  43 // for some compilers, the entire ole2.h must be included, not only oleauto.h 
  44 #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__) 
  50 #include "wx/msw/ole/oleutils.h" 
  52 // ---------------------------------------------------------------------------- 
  53 // wxIDropSource implementation of IDropSource interface 
  54 // ---------------------------------------------------------------------------- 
  56 class wxIDropSource 
: public IDropSource
 
  59   wxIDropSource(wxDropSource 
*pDropSource
); 
  61   DECLARE_IUNKNOWN_METHODS
; 
  64   STDMETHODIMP 
QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
); 
  65   STDMETHODIMP 
GiveFeedback(DWORD dwEffect
); 
  68   DWORD         m_grfInitKeyState
;  // button which started the d&d operation 
  69   wxDropSource 
*m_pDropSource
;      // pointer to C++ class we belong to 
  71     DECLARE_NO_COPY_CLASS(wxIDropSource
) 
  74 // ============================================================================ 
  76 // ============================================================================ 
  78 // ---------------------------------------------------------------------------- 
  79 // wxIDropSource implementation 
  80 // ---------------------------------------------------------------------------- 
  81 BEGIN_IID_TABLE(wxIDropSource
) 
  86 IMPLEMENT_IUNKNOWN_METHODS(wxIDropSource
) 
  88 wxIDropSource::wxIDropSource(wxDropSource 
*pDropSource
) 
  90   wxASSERT( pDropSource 
!= NULL 
); 
  92   m_pDropSource 
= pDropSource
; 
  93   m_grfInitKeyState 
= 0; 
  96 // Name    : wxIDropSource::QueryContinueDrag 
  97 // Purpose : decide if drag operation must be continued or not 
  98 // Returns : HRESULT: S_OK              if we should continue 
  99 //                    DRAGDROP_S_DROP   to drop right now 
 100 //                    DRAGDROP_S_CANCEL to cancel everything 
 101 // Params  : [in] BOOL  fEscapePressed  <Esc> pressed since last call? 
 102 //           [in] DWORD grfKeyState     mask containing state of kbd keys 
 103 // Notes   : as there is no reasonably simple portable way to implement this 
 104 //           function, we currently don't give the possibility to override the 
 105 //           default behaviour implemented here 
 106 STDMETHODIMP 
wxIDropSource::QueryContinueDrag(BOOL fEscapePressed
, 
 109   if ( fEscapePressed 
) 
 110     return DRAGDROP_S_CANCEL
; 
 112   // initialize ourself with the drag begin button 
 113   if ( m_grfInitKeyState 
== 0 ) { 
 114     m_grfInitKeyState 
= grfKeyState 
& (MK_LBUTTON 
| MK_RBUTTON 
| MK_MBUTTON
); 
 117   if ( !(grfKeyState 
& m_grfInitKeyState
) ) { 
 118     // button which started d&d released, go! 
 119     return DRAGDROP_S_DROP
; 
 125 // Name    : wxIDropSource::GiveFeedback 
 126 // Purpose : give UI feedback according to current state of operation 
 127 // Returns : STDMETHODIMP 
 128 // Params  : [in] DWORD dwEffect - what would happen if we dropped now 
 129 // Notes   : default implementation is ok in more than 99% of cases 
 130 STDMETHODIMP 
wxIDropSource::GiveFeedback(DWORD dwEffect
) 
 133   if ( dwEffect 
& DROPEFFECT_COPY 
) 
 135   else if ( dwEffect 
& DROPEFFECT_MOVE 
) 
 140   if ( m_pDropSource
->GiveFeedback(effect
) ) 
 143   return DRAGDROP_S_USEDEFAULTCURSORS
; 
 146 // ---------------------------------------------------------------------------- 
 147 // wxDropSource implementation 
 148 // ---------------------------------------------------------------------------- 
 152 // common part of all ctors 
 153 void wxDropSource::Init() 
 155     m_pIDropSource 
= new wxIDropSource(this); 
 156     m_pIDropSource
->AddRef(); 
 159 wxDropSource::wxDropSource(wxWindow
* WXUNUSED(win
), 
 160                            const wxCursor 
&cursorCopy
, 
 161                            const wxCursor 
&cursorMove
, 
 162                            const wxCursor 
&cursorStop
) 
 163             : wxDropSourceBase(cursorCopy
, cursorMove
, cursorStop
) 
 168 wxDropSource::wxDropSource(wxDataObject
& data
, 
 169                            wxWindow
* WXUNUSED(win
), 
 170                            const wxCursor 
&cursorCopy
, 
 171                            const wxCursor 
&cursorMove
, 
 172                            const wxCursor 
&cursorStop
) 
 173             : wxDropSourceBase(cursorCopy
, cursorMove
, cursorStop
) 
 179 wxDropSource::~wxDropSource() 
 181     m_pIDropSource
->Release(); 
 185 // Purpose : start drag and drop operation 
 186 // Returns : wxDragResult - the code of performed operation 
 187 // Params  : [in] int flags: specifies if moving is allowe (or only copying) 
 188 // Notes   : you must call SetData() before if you had used def ctor 
 189 wxDragResult 
wxDropSource::DoDragDrop(int flags
) 
 191   wxCHECK_MSG( m_data 
!= NULL
, wxDragNone
, wxT("No data in wxDropSource!") ); 
 194   HRESULT hr 
= ::DoDragDrop(m_data
->GetInterface(), 
 196                             (flags 
& wxDrag_AllowMove
) 
 197                                 ? DROPEFFECT_COPY 
| DROPEFFECT_MOVE
 
 201   if ( hr 
== DRAGDROP_S_CANCEL 
) { 
 204   else if ( hr 
== DRAGDROP_S_DROP 
) { 
 205     if ( dwEffect 
& DROPEFFECT_COPY 
) { 
 208     else if ( dwEffect 
& DROPEFFECT_MOVE 
) { 
 209       // consistency check: normally, we shouldn't get "move" at all 
 210       // here if we don't allow it, but in practice it does happen quite often 
 211       return (flags 
& wxDrag_AllowMove
) ? wxDragMove 
: wxDragCopy
; 
 220       wxLogApiError(wxT("DoDragDrop"), hr
); 
 221       wxLogError(wxT("Drag & drop operation failed.")); 
 224       wxLogDebug(wxT("Unexpected success return code %08lx from DoDragDrop."), 
 232 // Name    : wxDropSource::GiveFeedback 
 233 // Purpose : visually inform the user about d&d operation state 
 234 // Returns : bool: true if we do all ourselves or false for default feedback 
 235 // Params  : [in] DragResult effect - what would happen if we dropped now 
 236 // Notes   : here we just leave this stuff for default implementation 
 237 bool wxDropSource::GiveFeedback(wxDragResult effect
) 
 239     const wxCursor
& cursor 
= GetCursor(effect
); 
 242         ::SetCursor((HCURSOR
)cursor
.GetHCURSOR()); 
 252 #endif  //USE_DRAG_AND_DROP