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