]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ole/dataobj.cpp
3 // Purpose: implementation of wx[I]DataObject class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "dataobj.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
27 #if defined(__BORLANDC__)
33 #if defined(__WIN32__) && !defined(__GNUWIN32__)
36 #include <wx/msw/ole/oleutils.h>
37 #include <wx/msw/ole/dataobj.h>
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 static const char *GetTymedName(DWORD tymed
);
50 // ----------------------------------------------------------------------------
51 // wxIEnumFORMATETC interface implementation
52 // ----------------------------------------------------------------------------
53 class wxIEnumFORMATETC
: public IEnumFORMATETC
56 wxIEnumFORMATETC(CLIPFORMAT cf
);
58 DECLARE_IUNKNOWN_METHODS
;
61 STDMETHODIMP
Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFetched
);
62 STDMETHODIMP
Skip(ULONG celt
);
64 STDMETHODIMP
Clone(IEnumFORMATETC
**ppenum
);
67 FORMATETC m_format
; // (unique @@@) format we can provide data in
68 ULONG m_nCurrent
; // current enum position (currently either 0 or 1)
71 // ----------------------------------------------------------------------------
72 // wxIDataObject implementation of IDataObject interface
73 // ----------------------------------------------------------------------------
74 class wxIDataObject
: public IDataObject
77 wxIDataObject(wxDataObject
*pDataObject
);
79 DECLARE_IUNKNOWN_METHODS
;
82 STDMETHODIMP
GetData(FORMATETC
*pformatetcIn
, STGMEDIUM
*pmedium
);
83 STDMETHODIMP
GetDataHere(FORMATETC
*pformatetc
, STGMEDIUM
*pmedium
);
84 STDMETHODIMP
QueryGetData(FORMATETC
*pformatetc
);
85 STDMETHODIMP
GetCanonicalFormatEtc(FORMATETC
*In
, FORMATETC
*pOut
);
86 STDMETHODIMP
SetData(FORMATETC
*pfetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
87 STDMETHODIMP
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFEtc
);
88 STDMETHODIMP
DAdvise(FORMATETC
*pfetc
, DWORD ad
, IAdviseSink
*p
, DWORD
*pdw
);
89 STDMETHODIMP
DUnadvise(DWORD dwConnection
);
90 STDMETHODIMP
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
93 wxDataObject
*m_pDataObject
; // pointer to C++ class we belong to
96 // ============================================================================
98 // ============================================================================
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 BEGIN_IID_TABLE(wxIEnumFORMATETC
)
106 ADD_IID(EnumFORMATETC
)
109 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
)
111 wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf
)
113 m_format
.cfFormat
= cf
;
115 m_format
.dwAspect
= DVASPECT_CONTENT
;
116 m_format
.lindex
= -1;
117 m_format
.tymed
= TYMED_HGLOBAL
;
122 STDMETHODIMP
wxIEnumFORMATETC::Next(ULONG celt
,
126 wxLogTrace("wxIEnumFORMATETC::Next");
131 if ( m_nCurrent
== 0 ) {
141 STDMETHODIMP
wxIEnumFORMATETC::Skip(ULONG celt
)
143 wxLogTrace("wxIEnumFORMATETC::Skip");
145 if ( m_nCurrent
== 0 )
151 STDMETHODIMP
wxIEnumFORMATETC::Reset()
153 wxLogTrace("wxIEnumFORMATETC::Reset");
160 STDMETHODIMP
wxIEnumFORMATETC::Clone(IEnumFORMATETC
**ppenum
)
162 wxLogTrace("wxIEnumFORMATETC::Clone");
164 wxIEnumFORMATETC
*pNew
= new wxIEnumFORMATETC(m_format
.cfFormat
);
171 // ----------------------------------------------------------------------------
173 // ----------------------------------------------------------------------------
175 BEGIN_IID_TABLE(wxIDataObject
)
180 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
)
182 wxIDataObject::wxIDataObject(wxDataObject
*pDataObject
)
185 m_pDataObject
= pDataObject
;
188 // get data functions
189 STDMETHODIMP
wxIDataObject::GetData(FORMATETC
*pformatetcIn
, STGMEDIUM
*pmedium
)
191 wxLogTrace("wxIDataObject::GetData");
193 // is data is in our format?
194 HRESULT hr
= QueryGetData(pformatetcIn
);
199 HGLOBAL hGlobal
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
,
200 m_pDataObject
->GetDataSize());
201 if ( hGlobal
== NULL
) {
202 wxLogLastError("GlobalAlloc");
203 return E_OUTOFMEMORY
;
207 pmedium
->tymed
= TYMED_HGLOBAL
;
208 pmedium
->hGlobal
= hGlobal
;
209 pmedium
->pUnkForRelease
= NULL
;
211 hr
= GetDataHere(pformatetcIn
, pmedium
);
220 STDMETHODIMP
wxIDataObject::GetDataHere(FORMATETC
*pformatetc
,
223 wxLogTrace("wxIDataObject::GetDataHere");
225 // put data in caller provided medium
226 if ( pmedium
->tymed
!= TYMED_HGLOBAL
)
230 void *pBuf
= GlobalLock(pmedium
->hGlobal
);
231 if ( pBuf
== NULL
) {
232 wxLogLastError("GlobalLock");
233 return E_OUTOFMEMORY
;
236 m_pDataObject
->GetDataHere(pBuf
);
238 GlobalUnlock(pmedium
->hGlobal
);
243 // set data functions (not implemented)
244 STDMETHODIMP
wxIDataObject::SetData(FORMATETC
*pformatetc
,
248 wxLogTrace("wxIDataObject::SetData");
252 // information functions
253 STDMETHODIMP
wxIDataObject::QueryGetData(FORMATETC
*pformatetc
)
255 // do we accept data in this format?
256 if ( pformatetc
== NULL
) {
257 wxLogTrace("wxIDataObject::QueryGetData: invalid ptr.");
261 // the only one allowed by current COM implementation
262 if ( pformatetc
->lindex
!= -1 ) {
263 wxLogTrace("wxIDataObject::QueryGetData: bad lindex %d",
268 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
269 if ( pformatetc
->dwAspect
!= DVASPECT_CONTENT
) {
270 wxLogTrace("wxIDataObject::QueryGetData: bad dwAspect %d",
271 pformatetc
->dwAspect
);
272 return DV_E_DVASPECT
;
275 // @@ we only transfer data by global memory (bad for large amounts of it!)
276 if ( !(pformatetc
->tymed
& TYMED_HGLOBAL
) ) {
277 wxLogTrace("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL.",
278 GetTymedName(pformatetc
->tymed
));
282 // and now check the type of data requested
283 if ( m_pDataObject
->IsSupportedFormat((wxDataFormat
) pformatetc
->cfFormat
) ) {
284 wxLogTrace("wxIDataObject::QueryGetData: %s ok",
285 wxDataObject::GetFormatName((wxDataFormat
) pformatetc
->cfFormat
));
289 wxLogTrace("wxIDataObject::QueryGetData: %s unsupported",
290 wxDataObject::GetFormatName((wxDataFormat
) pformatetc
->cfFormat
));
291 return DV_E_FORMATETC
;
295 STDMETHODIMP
wxIDataObject::GetCanonicalFormatEtc(FORMATETC
*pFormatetcIn
,
296 FORMATETC
*pFormatetcOut
)
298 wxLogTrace("wxIDataObject::GetCanonicalFormatEtc");
300 // @@ implementation is trivial, we might want something better here
301 if ( pFormatetcOut
!= NULL
)
302 pFormatetcOut
->ptd
= NULL
;
303 return DATA_S_SAMEFORMATETC
;
306 STDMETHODIMP
wxIDataObject::EnumFormatEtc(DWORD dwDirection
,
307 IEnumFORMATETC
**ppenumFormatEtc
)
309 wxLogTrace("wxIDataObject::EnumFormatEtc");
311 if ( dwDirection
== DATADIR_SET
) {
312 // we don't allow setting of data anyhow
316 wxIEnumFORMATETC
*pEnum
=
317 new wxIEnumFORMATETC(m_pDataObject
->GetPreferredFormat());
319 *ppenumFormatEtc
= pEnum
;
324 // advise sink functions (not implemented)
325 STDMETHODIMP
wxIDataObject::DAdvise(FORMATETC
*pformatetc
,
327 IAdviseSink
*pAdvSink
,
328 DWORD
*pdwConnection
)
330 return OLE_E_ADVISENOTSUPPORTED
;
333 STDMETHODIMP
wxIDataObject::DUnadvise(DWORD dwConnection
)
335 return OLE_E_ADVISENOTSUPPORTED
;
338 STDMETHODIMP
wxIDataObject::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
340 return OLE_E_ADVISENOTSUPPORTED
;
343 // ----------------------------------------------------------------------------
345 // ----------------------------------------------------------------------------
347 wxDataObject::wxDataObject()
349 m_pIDataObject
= new wxIDataObject(this);
350 m_pIDataObject
->AddRef();
353 wxDataObject::~wxDataObject()
355 m_pIDataObject
->Release();
358 const char *wxDataObject::GetFormatName(wxDataFormat format
)
361 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
363 #pragma warning(disable:4063)
366 static char s_szBuf
[128];
368 case CF_TEXT
: return "CF_TEXT";
369 case CF_BITMAP
: return "CF_BITMAP";
370 case CF_METAFILEPICT
: return "CF_METAFILEPICT";
371 case CF_SYLK
: return "CF_SYLK";
372 case CF_DIF
: return "CF_DIF";
373 case CF_TIFF
: return "CF_TIFF";
374 case CF_OEMTEXT
: return "CF_OEMTEXT";
375 case CF_DIB
: return "CF_DIB";
376 case CF_PALETTE
: return "CF_PALETTE";
377 case CF_PENDATA
: return "CF_PENDATA";
378 case CF_RIFF
: return "CF_RIFF";
379 case CF_WAVE
: return "CF_WAVE";
380 case CF_UNICODETEXT
: return "CF_UNICODETEXT";
381 case CF_ENHMETAFILE
: return "CF_ENHMETAFILE";
382 case CF_HDROP
: return "CF_HDROP";
383 case CF_LOCALE
: return "CF_LOCALE";
385 sprintf(s_szBuf
, "clipboard format %d (unknown)", format
);
390 #pragma warning(default:4063)
398 // ----------------------------------------------------------------------------
400 // ----------------------------------------------------------------------------
401 static const char *GetTymedName(DWORD tymed
)
403 static char s_szBuf
[128];
405 case TYMED_HGLOBAL
: return "TYMED_HGLOBAL";
406 case TYMED_FILE
: return "TYMED_FILE";
407 case TYMED_ISTREAM
: return "TYMED_ISTREAM";
408 case TYMED_ISTORAGE
: return "TYMED_ISTORAGE";
409 case TYMED_GDI
: return "TYMED_GDI";
410 case TYMED_MFPICT
: return "TYMED_MFPICT";
411 case TYMED_ENHMF
: return "TYMED_ENHMF";
413 sprintf(s_szBuf
, "type of media format %d (unknown)", tymed
);
418 // TODO: OLE parts of wxBitmap/File/MetafileDataObject