]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dropsrc.cpp
"continue;" restored to prevent the app from going into infinite loop
[wxWidgets.git] / src / msw / ole / dropsrc.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ole/dropsrc.cpp
3 // Purpose: implementation of wxIDropSource and wxDropSource
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 10.05.98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "dropsrc.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #if defined(__BORLANDC__)
28 #pragma hdrstop
29 #endif
30
31 #include <wx/setup.h>
32
33 #if wxUSE_DRAG_AND_DROP
34
35 #include <wx/log.h>
36 #include <wx/msw/ole/dataobj.h>
37 #include <wx/msw/ole/dropsrc.h>
38
39 #include <windows.h>
40
41 #ifndef __WIN32__
42 #include <ole2.h>
43 #include <olestd.h>
44 #endif
45
46 #include <oleauto.h>
47
48 #include <wx/msw/ole/oleutils.h>
49
50 // ----------------------------------------------------------------------------
51 // wxIDropSource implementation of IDropSource interface
52 // ----------------------------------------------------------------------------
53
54 class wxIDropSource : public IDropSource
55 {
56 public:
57 wxIDropSource(wxDropSource *pDropSource);
58
59 DECLARE_IUNKNOWN_METHODS;
60
61 // IDropSource
62 STDMETHODIMP QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
63 STDMETHODIMP GiveFeedback(DWORD dwEffect);
64
65 private:
66 DWORD m_grfInitKeyState; // button which started the d&d operation
67 wxDropSource *m_pDropSource; // pointer to C++ class we belong to
68 };
69
70 // ============================================================================
71 // Implementation
72 // ============================================================================
73
74 // ----------------------------------------------------------------------------
75 // wxIDropSource implementation
76 // ----------------------------------------------------------------------------
77 BEGIN_IID_TABLE(wxIDropSource)
78 ADD_IID(Unknown)
79 ADD_IID(DropSource)
80 END_IID_TABLE;
81
82 IMPLEMENT_IUNKNOWN_METHODS(wxIDropSource)
83
84 wxIDropSource::wxIDropSource(wxDropSource *pDropSource)
85 {
86 wxASSERT( pDropSource != NULL );
87
88 m_pDropSource = pDropSource;
89 m_grfInitKeyState = 0;
90 m_cRef = 0;
91 }
92
93 // Name : wxIDropSource::QueryContinueDrag
94 // Purpose : decide if drag operation must be continued or not
95 // Returns : HRESULT: S_OK if we should continue
96 // DRAGDROP_S_DROP to drop right now
97 // DRAGDROP_S_CANCEL to cancel everything
98 // Params : [in] BOOL fEscapePressed <Esc> pressed since last call?
99 // [in] DWORD grfKeyState mask containing state of kbd keys
100 // Notes : as there is no reasonably simple portable way to implement this
101 // function, we currently don't give the possibility to override the
102 // default behaviour implemented here
103 STDMETHODIMP wxIDropSource::QueryContinueDrag(BOOL fEscapePressed,
104 DWORD grfKeyState)
105 {
106 if ( fEscapePressed )
107 return DRAGDROP_S_CANCEL;
108
109 // initialize ourself with the drag begin button
110 if ( m_grfInitKeyState == 0 ) {
111 m_grfInitKeyState = grfKeyState & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON);
112 }
113
114 if ( !(grfKeyState & m_grfInitKeyState) ) {
115 // button which started d&d released, go!
116 return DRAGDROP_S_DROP;
117 }
118
119 return S_OK;
120 }
121
122 // Name : wxIDropSource::GiveFeedback
123 // Purpose : give UI feedback according to current state of operation
124 // Returns : STDMETHODIMP
125 // Params : [in] DWORD dwEffect - what would happen if we dropped now
126 // Notes : default implementation is ok in more than 99% of cases
127 STDMETHODIMP wxIDropSource::GiveFeedback(DWORD dwEffect)
128 {
129 wxDragResult effect;
130 if ( dwEffect & DROPEFFECT_COPY )
131 effect = wxDragCopy;
132 else if ( dwEffect & DROPEFFECT_MOVE )
133 effect = wxDragMove;
134 else
135 effect = wxDragNone;
136
137 if ( m_pDropSource->GiveFeedback(effect,
138 (dwEffect & DROPEFFECT_SCROLL) != 0 ) )
139 return S_OK;
140
141 return DRAGDROP_S_USEDEFAULTCURSORS;
142 }
143
144 // ----------------------------------------------------------------------------
145 // wxDropSource implementation
146 // ----------------------------------------------------------------------------
147
148 // ctors
149
150 // common part of all ctors
151 void wxDropSource::Init()
152 {
153 m_pIDropSource = new wxIDropSource(this);
154 m_pIDropSource->AddRef();
155 }
156
157 wxDropSource::wxDropSource(wxWindow* WXUNUSED(win))
158 {
159 Init();
160 m_pData = NULL;
161 }
162
163 wxDropSource::wxDropSource(wxDataObject& data, wxWindow* WXUNUSED(win))
164 {
165 Init();
166 SetData(data);
167 }
168
169 void wxDropSource::SetData(wxDataObject& data)
170 {
171 m_pData = &data;
172 }
173
174 wxDropSource::~wxDropSource()
175 {
176 m_pIDropSource->Release();
177 }
178
179 // Name : DoDragDrop
180 // Purpose : start drag and drop operation
181 // Returns : wxDragResult - the code of performed operation
182 // Params : [in] bool bAllowMove: if false, only copy is allowed
183 // Notes : you must call SetData() before if you had used def ctor
184 wxDragResult wxDropSource::DoDragDrop(bool bAllowMove)
185 {
186 wxCHECK_MSG( m_pData != NULL, wxDragNone, "No data in wxDropSource!" );
187
188 DWORD dwEffect;
189 HRESULT hr = ::DoDragDrop(m_pData->GetInterface(),
190 m_pIDropSource,
191 bAllowMove ? DROPEFFECT_COPY | DROPEFFECT_MOVE
192 : DROPEFFECT_COPY,
193 &dwEffect);
194
195 if ( hr == DRAGDROP_S_CANCEL ) {
196 return wxDragCancel;
197 }
198 else if ( hr == DRAGDROP_S_DROP ) {
199 if ( dwEffect & DROPEFFECT_COPY ) {
200 return wxDragCopy;
201 }
202 else if ( dwEffect & DROPEFFECT_MOVE ) {
203 // consistency check: normally, we shouldn't get "move" at all
204 // here if !bAllowMove, but in practice it does happen quite often
205 if ( bAllowMove )
206 return wxDragMove;
207 else
208 return wxDragCopy;
209 }
210 else {
211 // not copy or move
212 return wxDragNone;
213 }
214 }
215 else {
216 if ( FAILED(hr) ) {
217 wxLogApiError("DoDragDrop", hr);
218 wxLogError("Drag & drop operation failed.");
219 }
220 else {
221 wxLogDebug("Unexpected success return code %08lx from DoDragDrop.", hr);
222 }
223
224 return wxDragError;
225 }
226 }
227
228 // Name : wxDropSource::GiveFeedback
229 // Purpose : visually inform the user about d&d operation state
230 // Returns : bool: true if we do all ourselves or false for default feedback
231 // Params : [in] DragResult effect - what would happen if we dropped now
232 // [in] bool bScrolling - true if target is scrolling
233 // Notes : here we just leave this stuff for default implementation
234 bool wxDropSource::GiveFeedback(wxDragResult effect, bool bScrolling)
235 {
236 return FALSE;
237 }
238
239 #endif //USE_DRAG_AND_DROP