]> git.saurik.com Git - wxWidgets.git/blame - src/msw/ole/dataobj.cpp
wxMenu and wxMenuBar modifications: now works much better with owner-drawn
[wxWidgets.git] / src / msw / ole / dataobj.cpp
CommitLineData
269a5a34
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/ole/dataobj.cpp
3// Purpose: implementation of wx[I]DataObject class
4// Author: Vadim Zeitlin
3f4a0c5b 5// Modified by:
269a5a34
VZ
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 "dataobj.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
5260b1c5
JS
31#include <wx/defs.h>
32
cfe780fb 33#if defined(__WIN32__) && !defined(__GNUWIN32__)
5260b1c5 34
17b74d79
JS
35#include <wx/log.h>
36#include <wx/msw/ole/dataobj.h>
37
38#include <windows.h>
39#include <oleauto.h>
269a5a34
VZ
40
41#ifndef __WIN32__
42 #include <ole2.h>
43 #include <olestd.h>
44#endif
45
17b74d79
JS
46#include <wx/msw/ole/oleutils.h>
47
269a5a34
VZ
48// ----------------------------------------------------------------------------
49// functions
50// ----------------------------------------------------------------------------
51
40e1a9c0 52static const char *GetTymedName(DWORD tymed);
269a5a34
VZ
53
54// ----------------------------------------------------------------------------
55// wxIEnumFORMATETC interface implementation
56// ----------------------------------------------------------------------------
57class wxIEnumFORMATETC : public IEnumFORMATETC
58{
59public:
60 wxIEnumFORMATETC(CLIPFORMAT cf);
61
62 DECLARE_IUNKNOWN_METHODS;
63
64 // IEnumFORMATETC
65 STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
66 STDMETHODIMP Skip(ULONG celt);
67 STDMETHODIMP Reset();
68 STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
69
70private:
71 FORMATETC m_format; // (unique @@@) format we can provide data in
72 ULONG m_nCurrent; // current enum position (currently either 0 or 1)
73};
74
75// ----------------------------------------------------------------------------
76// wxIDataObject implementation of IDataObject interface
77// ----------------------------------------------------------------------------
78class wxIDataObject : public IDataObject
79{
80public:
81 wxIDataObject(wxDataObject *pDataObject);
82
83 DECLARE_IUNKNOWN_METHODS;
84
85 // IDataObject
86 STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
87 STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
88 STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
89 STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
90 STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
91 STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
92 STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
93 STDMETHODIMP DUnadvise(DWORD dwConnection);
94 STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
95
96private:
97 wxDataObject *m_pDataObject; // pointer to C++ class we belong to
98};
99
100// ============================================================================
101// implementation
102// ============================================================================
103
104// ----------------------------------------------------------------------------
105// wxIEnumFORMATETC
106// ----------------------------------------------------------------------------
107
108BEGIN_IID_TABLE(wxIEnumFORMATETC)
109 ADD_IID(Unknown)
110 ADD_IID(EnumFORMATETC)
111END_IID_TABLE;
112
113IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
114
115wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf)
116{
117 m_format.cfFormat = cf;
118 m_format.ptd = NULL;
119 m_format.dwAspect = DVASPECT_CONTENT;
120 m_format.lindex = -1;
121 m_format.tymed = TYMED_HGLOBAL;
122 m_cRef = 0;
123 m_nCurrent = 0;
124}
125
126STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
127 FORMATETC *rgelt,
128 ULONG *pceltFetched)
129{
130 wxLogTrace("wxIEnumFORMATETC::Next");
131
132 if ( celt > 1 )
133 return S_FALSE;
134
135 if ( m_nCurrent == 0 ) {
136 *rgelt = m_format;
137 m_nCurrent++;
138
139 return S_OK;
140 }
141 else
142 return S_FALSE;
143}
144
145STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
146{
147 wxLogTrace("wxIEnumFORMATETC::Skip");
148
149 if ( m_nCurrent == 0 )
150 m_nCurrent++;
151
152 return S_FALSE;
153}
154
155STDMETHODIMP wxIEnumFORMATETC::Reset()
156{
157 wxLogTrace("wxIEnumFORMATETC::Reset");
158
159 m_nCurrent = 0;
160
161 return S_OK;
162}
163
164STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
165{
166 wxLogTrace("wxIEnumFORMATETC::Clone");
167
168 wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat);
169 pNew->AddRef();
170 *ppenum = pNew;
171
172 return S_OK;
173}
174
175// ----------------------------------------------------------------------------
176// wxIDataObject
177// ----------------------------------------------------------------------------
178
179BEGIN_IID_TABLE(wxIDataObject)
180 ADD_IID(Unknown)
181 ADD_IID(DataObject)
182END_IID_TABLE;
183
184IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
185
186wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
187{
188 m_cRef = 0;
189 m_pDataObject = pDataObject;
190}
191
192// get data functions
193STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
194{
195 wxLogTrace("wxIDataObject::GetData");
196
197 // is data is in our format?
198 HRESULT hr = QueryGetData(pformatetcIn);
199 if ( FAILED(hr) )
200 return hr;
201
202 // alloc memory
203 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
204 m_pDataObject->GetDataSize());
205 if ( hGlobal == NULL ) {
206 wxLogLastError("GlobalAlloc");
207 return E_OUTOFMEMORY;
208 }
209
210 // copy data
211 pmedium->tymed = TYMED_HGLOBAL;
212 pmedium->hGlobal = hGlobal;
213 pmedium->pUnkForRelease = NULL;
214
215 hr = GetDataHere(pformatetcIn, pmedium);
216 if ( FAILED(hr) ) {
217 GlobalFree(hGlobal);
218 return hr;
219 }
220
221 return S_OK;
222}
223
224STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
225 STGMEDIUM *pmedium)
226{
227 wxLogTrace("wxIDataObject::GetDataHere");
228
229 // put data in caller provided medium
230 if ( pmedium->tymed != TYMED_HGLOBAL )
231 return DV_E_TYMED;
232
233 // copy data
234 void *pBuf = GlobalLock(pmedium->hGlobal);
235 if ( pBuf == NULL ) {
236 wxLogLastError("GlobalLock");
237 return E_OUTOFMEMORY;
238 }
239
240 m_pDataObject->GetDataHere(pBuf);
241
242 GlobalUnlock(pmedium->hGlobal);
243
244 return S_OK;
245}
246
247// set data functions (not implemented)
248STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
249 STGMEDIUM *pmedium,
250 BOOL fRelease)
251{
252 wxLogTrace("wxIDataObject::SetData");
253 return E_NOTIMPL;
254}
255
256// information functions
257STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
258{
259 // do we accept data in this format?
260 if ( pformatetc == NULL ) {
261 wxLogTrace("wxIDataObject::QueryGetData: invalid ptr.");
262 return E_INVALIDARG;
263 }
264
265 // the only one allowed by current COM implementation
266 if ( pformatetc->lindex != -1 ) {
267 wxLogTrace("wxIDataObject::QueryGetData: bad lindex %d",
268 pformatetc->lindex);
269 return DV_E_LINDEX;
270 }
271
272 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
273 if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
274 wxLogTrace("wxIDataObject::QueryGetData: bad dwAspect %d",
275 pformatetc->dwAspect);
276 return DV_E_DVASPECT;
277 }
278
279 // @@ we only transfer data by global memory (bad for large amounts of it!)
280 if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) {
281 wxLogTrace("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL.",
282 GetTymedName(pformatetc->tymed));
283 return DV_E_TYMED;
284 }
285
286 // and now check the type of data requested
b3324be2 287 if ( m_pDataObject->IsSupportedFormat((wxDataFormat) pformatetc->cfFormat) ) {
269a5a34 288 wxLogTrace("wxIDataObject::QueryGetData: %s ok",
b3324be2 289 wxDataObject::GetFormatName((wxDataFormat) pformatetc->cfFormat));
269a5a34
VZ
290 return S_OK;
291 }
292 else {
293 wxLogTrace("wxIDataObject::QueryGetData: %s unsupported",
b3324be2 294 wxDataObject::GetFormatName((wxDataFormat) pformatetc->cfFormat));
269a5a34
VZ
295 return DV_E_FORMATETC;
296 }
297}
298
299STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
300 FORMATETC *pFormatetcOut)
301{
302 wxLogTrace("wxIDataObject::GetCanonicalFormatEtc");
303
304 // @@ implementation is trivial, we might want something better here
305 if ( pFormatetcOut != NULL )
306 pFormatetcOut->ptd = NULL;
307 return DATA_S_SAMEFORMATETC;
308}
309
310STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
311 IEnumFORMATETC **ppenumFormatEtc)
312{
313 wxLogTrace("wxIDataObject::EnumFormatEtc");
314
315 if ( dwDirection == DATADIR_SET ) {
316 // we don't allow setting of data anyhow
317 return E_NOTIMPL;
318 }
319
3f4a0c5b 320 wxIEnumFORMATETC *pEnum =
269a5a34
VZ
321 new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat());
322 pEnum->AddRef();
323 *ppenumFormatEtc = pEnum;
324
325 return S_OK;
326}
327
328// advise sink functions (not implemented)
329STDMETHODIMP wxIDataObject::DAdvise(FORMATETC *pformatetc,
330 DWORD advf,
331 IAdviseSink *pAdvSink,
332 DWORD *pdwConnection)
333{
334 return OLE_E_ADVISENOTSUPPORTED;
335}
336
337STDMETHODIMP wxIDataObject::DUnadvise(DWORD dwConnection)
338{
339 return OLE_E_ADVISENOTSUPPORTED;
340}
341
342STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
343{
344 return OLE_E_ADVISENOTSUPPORTED;
345}
346
347// ----------------------------------------------------------------------------
348// wxDataObject
349// ----------------------------------------------------------------------------
350
351wxDataObject::wxDataObject()
352{
353 m_pIDataObject = new wxIDataObject(this);
354 m_pIDataObject->AddRef();
355}
356
357wxDataObject::~wxDataObject()
358{
359 m_pIDataObject->Release();
360}
361
269a5a34
VZ
362const char *wxDataObject::GetFormatName(wxDataFormat format)
363{
b2aef89b 364#ifdef __WXDEBUG__
fd3f686c 365 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
3f4a0c5b 366 #ifdef __VISUALC__
fd3f686c
VZ
367 #pragma warning(disable:4063)
368 #endif // VC++
369
269a5a34
VZ
370 static char s_szBuf[128];
371 switch ( format ) {
372 case CF_TEXT: return "CF_TEXT";
373 case CF_BITMAP: return "CF_BITMAP";
374 case CF_METAFILEPICT: return "CF_METAFILEPICT";
375 case CF_SYLK: return "CF_SYLK";
376 case CF_DIF: return "CF_DIF";
377 case CF_TIFF: return "CF_TIFF";
378 case CF_OEMTEXT: return "CF_OEMTEXT";
379 case CF_DIB: return "CF_DIB";
380 case CF_PALETTE: return "CF_PALETTE";
381 case CF_PENDATA: return "CF_PENDATA";
382 case CF_RIFF: return "CF_RIFF";
383 case CF_WAVE: return "CF_WAVE";
384 case CF_UNICODETEXT: return "CF_UNICODETEXT";
385 case CF_ENHMETAFILE: return "CF_ENHMETAFILE";
386 case CF_HDROP: return "CF_HDROP";
387 case CF_LOCALE: return "CF_LOCALE";
388 default:
389 sprintf(s_szBuf, "clipboard format %d (unknown)", format);
390 return s_szBuf;
391 }
fd3f686c 392
3f4a0c5b 393 #ifdef __VISUALC__
fd3f686c
VZ
394 #pragma warning(default:4063)
395 #endif // VC++
396
397#else // !Debug
40e1a9c0 398 return "";
fd3f686c 399#endif // Debug
269a5a34
VZ
400}
401
402// ----------------------------------------------------------------------------
403// private functions
404// ----------------------------------------------------------------------------
405static const char *GetTymedName(DWORD tymed)
406{
407 static char s_szBuf[128];
408 switch ( tymed ) {
409 case TYMED_HGLOBAL: return "TYMED_HGLOBAL";
410 case TYMED_FILE: return "TYMED_FILE";
411 case TYMED_ISTREAM: return "TYMED_ISTREAM";
412 case TYMED_ISTORAGE: return "TYMED_ISTORAGE";
413 case TYMED_GDI: return "TYMED_GDI";
414 case TYMED_MFPICT: return "TYMED_MFPICT";
415 case TYMED_ENHMF: return "TYMED_ENHMF";
416 default:
417 sprintf(s_szBuf, "type of media format %d (unknown)", tymed);
418 return s_szBuf;
419 }
420}
5260b1c5 421
2845ddc2
JS
422// TODO: OLE parts of wxBitmap/File/MetafileDataObject
423
5260b1c5
JS
424#endif
425