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