]>
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__)
35 #if defined(__WIN32__) && !defined(__GNUWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
38 #include "wx/dataobj.h"
41 #ifdef wxUSE_NORLANDER_HEADERS
51 #include "wx/msw/ole/oleutils.h"
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
57 static const char *GetTymedName(DWORD tymed
);
59 // ----------------------------------------------------------------------------
60 // wxIEnumFORMATETC interface implementation
61 // ----------------------------------------------------------------------------
62 class wxIEnumFORMATETC
: public IEnumFORMATETC
65 wxIEnumFORMATETC(CLIPFORMAT cf
);
67 DECLARE_IUNKNOWN_METHODS
;
70 STDMETHODIMP
Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFetched
);
71 STDMETHODIMP
Skip(ULONG celt
);
73 STDMETHODIMP
Clone(IEnumFORMATETC
**ppenum
);
76 FORMATETC m_format
; // (unique @@@) format we can provide data in
77 ULONG m_nCurrent
; // current enum position (currently either 0 or 1)
80 // ----------------------------------------------------------------------------
81 // wxIDataObject implementation of IDataObject interface
82 // ----------------------------------------------------------------------------
83 class wxIDataObject
: public IDataObject
86 wxIDataObject(wxDataObject
*pDataObject
);
88 DECLARE_IUNKNOWN_METHODS
;
91 STDMETHODIMP
GetData(FORMATETC
*pformatetcIn
, STGMEDIUM
*pmedium
);
92 STDMETHODIMP
GetDataHere(FORMATETC
*pformatetc
, STGMEDIUM
*pmedium
);
93 STDMETHODIMP
QueryGetData(FORMATETC
*pformatetc
);
94 STDMETHODIMP
GetCanonicalFormatEtc(FORMATETC
*In
, FORMATETC
*pOut
);
95 STDMETHODIMP
SetData(FORMATETC
*pfetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
96 STDMETHODIMP
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFEtc
);
97 STDMETHODIMP
DAdvise(FORMATETC
*pfetc
, DWORD ad
, IAdviseSink
*p
, DWORD
*pdw
);
98 STDMETHODIMP
DUnadvise(DWORD dwConnection
);
99 STDMETHODIMP
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
102 wxDataObject
*m_pDataObject
; // pointer to C++ class we belong to
105 // ============================================================================
107 // ============================================================================
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
113 void wxDataFormat::SetId(const wxChar
*format
)
115 m_format
= ::RegisterClipboardFormat(format
);
118 wxLogError(_("Couldn't register clipboard format '%s'."), format
);
122 wxString
wxDataFormat::GetId() const
124 static const int max
= 256;
128 wxCHECK_MSG( !IsStandard(), s
,
129 wxT("name of predefined format cannot be retrieved") );
131 int len
= ::GetClipboardFormatName(m_format
, s
.GetWriteBuf(max
), max
);
136 wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
);
142 // ----------------------------------------------------------------------------
144 // ----------------------------------------------------------------------------
146 BEGIN_IID_TABLE(wxIEnumFORMATETC
)
148 ADD_IID(EnumFORMATETC
)
151 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
)
153 wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf
)
155 m_format
.cfFormat
= cf
;
157 m_format
.dwAspect
= DVASPECT_CONTENT
;
158 m_format
.lindex
= -1;
159 m_format
.tymed
= TYMED_HGLOBAL
;
164 STDMETHODIMP
wxIEnumFORMATETC::Next(ULONG celt
,
168 wxLogTrace(wxT("wxIEnumFORMATETC::Next"));
173 if ( m_nCurrent
== 0 ) {
183 STDMETHODIMP
wxIEnumFORMATETC::Skip(ULONG celt
)
185 wxLogTrace(wxT("wxIEnumFORMATETC::Skip"));
187 if ( m_nCurrent
== 0 )
193 STDMETHODIMP
wxIEnumFORMATETC::Reset()
195 wxLogTrace(wxT("wxIEnumFORMATETC::Reset"));
202 STDMETHODIMP
wxIEnumFORMATETC::Clone(IEnumFORMATETC
**ppenum
)
204 wxLogTrace(wxT("wxIEnumFORMATETC::Clone"));
206 wxIEnumFORMATETC
*pNew
= new wxIEnumFORMATETC(m_format
.cfFormat
);
213 // ----------------------------------------------------------------------------
215 // ----------------------------------------------------------------------------
217 BEGIN_IID_TABLE(wxIDataObject
)
222 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
)
224 wxIDataObject::wxIDataObject(wxDataObject
*pDataObject
)
227 m_pDataObject
= pDataObject
;
230 // get data functions
231 STDMETHODIMP
wxIDataObject::GetData(FORMATETC
*pformatetcIn
, STGMEDIUM
*pmedium
)
233 wxLogTrace(wxT("wxIDataObject::GetData"));
235 // is data is in our format?
236 HRESULT hr
= QueryGetData(pformatetcIn
);
241 HGLOBAL hGlobal
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
,
242 m_pDataObject
->GetDataSize());
243 if ( hGlobal
== NULL
) {
244 wxLogLastError("GlobalAlloc");
245 return E_OUTOFMEMORY
;
249 pmedium
->tymed
= TYMED_HGLOBAL
;
250 pmedium
->hGlobal
= hGlobal
;
251 pmedium
->pUnkForRelease
= NULL
;
253 hr
= GetDataHere(pformatetcIn
, pmedium
);
262 STDMETHODIMP
wxIDataObject::GetDataHere(FORMATETC
*pformatetc
,
265 wxLogTrace(wxT("wxIDataObject::GetDataHere"));
267 // put data in caller provided medium
268 if ( pmedium
->tymed
!= TYMED_HGLOBAL
)
272 void *pBuf
= GlobalLock(pmedium
->hGlobal
);
273 if ( pBuf
== NULL
) {
274 wxLogLastError(wxT("GlobalLock"));
275 return E_OUTOFMEMORY
;
278 m_pDataObject
->GetDataHere(pBuf
);
280 GlobalUnlock(pmedium
->hGlobal
);
285 // set data functions (not implemented)
286 STDMETHODIMP
wxIDataObject::SetData(FORMATETC
*pformatetc
,
290 wxLogTrace(wxT("wxIDataObject::SetData"));
294 // information functions
295 STDMETHODIMP
wxIDataObject::QueryGetData(FORMATETC
*pformatetc
)
297 // do we accept data in this format?
298 if ( pformatetc
== NULL
) {
299 wxLogTrace(wxT("wxIDataObject::QueryGetData: invalid ptr."));
303 // the only one allowed by current COM implementation
304 if ( pformatetc
->lindex
!= -1 ) {
305 wxLogTrace(wxT("wxIDataObject::QueryGetData: bad lindex %d"),
310 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
311 if ( pformatetc
->dwAspect
!= DVASPECT_CONTENT
) {
312 wxLogTrace(wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
313 pformatetc
->dwAspect
);
314 return DV_E_DVASPECT
;
317 // @@ we only transfer data by global memory (bad for large amounts of it!)
318 if ( !(pformatetc
->tymed
& TYMED_HGLOBAL
) ) {
319 wxLogTrace(wxT("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL."),
320 GetTymedName(pformatetc
->tymed
));
324 // and now check the type of data requested
325 if ( m_pDataObject
->IsSupportedFormat((wxDataFormatId
)pformatetc
->cfFormat
) ) {
326 wxLogTrace(wxT("wxIDataObject::QueryGetData: %s ok"),
327 wxDataObject::GetFormatName((wxDataFormatId
)pformatetc
->cfFormat
));
331 wxLogTrace(wxT("wxIDataObject::QueryGetData: %s unsupported"),
332 wxDataObject::GetFormatName((wxDataFormatId
)pformatetc
->cfFormat
));
333 return DV_E_FORMATETC
;
337 STDMETHODIMP
wxIDataObject::GetCanonicalFormatEtc(FORMATETC
*pFormatetcIn
,
338 FORMATETC
*pFormatetcOut
)
340 wxLogTrace(wxT("wxIDataObject::GetCanonicalFormatEtc"));
342 // @@ implementation is trivial, we might want something better here
343 if ( pFormatetcOut
!= NULL
)
344 pFormatetcOut
->ptd
= NULL
;
345 return DATA_S_SAMEFORMATETC
;
348 STDMETHODIMP
wxIDataObject::EnumFormatEtc(DWORD dwDirection
,
349 IEnumFORMATETC
**ppenumFormatEtc
)
351 wxLogTrace(wxT("wxIDataObject::EnumFormatEtc"));
353 if ( dwDirection
== DATADIR_SET
) {
354 // we don't allow setting of data anyhow
358 wxIEnumFORMATETC
*pEnum
=
359 new wxIEnumFORMATETC(m_pDataObject
->GetPreferredFormat());
361 *ppenumFormatEtc
= pEnum
;
366 // advise sink functions (not implemented)
367 STDMETHODIMP
wxIDataObject::DAdvise(FORMATETC
*pformatetc
,
369 IAdviseSink
*pAdvSink
,
370 DWORD
*pdwConnection
)
372 return OLE_E_ADVISENOTSUPPORTED
;
375 STDMETHODIMP
wxIDataObject::DUnadvise(DWORD dwConnection
)
377 return OLE_E_ADVISENOTSUPPORTED
;
380 STDMETHODIMP
wxIDataObject::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
382 return OLE_E_ADVISENOTSUPPORTED
;
385 // ----------------------------------------------------------------------------
387 // ----------------------------------------------------------------------------
389 wxDataObject::wxDataObject()
391 m_pIDataObject
= new wxIDataObject(this);
392 m_pIDataObject
->AddRef();
395 wxDataObject::~wxDataObject()
397 m_pIDataObject
->Release();
400 const char *wxDataObject::GetFormatName(wxDataFormat format
)
403 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
405 #pragma warning(disable:4063)
408 static char s_szBuf
[128];
410 case CF_TEXT
: return "CF_TEXT";
411 case CF_BITMAP
: return "CF_BITMAP";
412 case CF_METAFILEPICT
: return "CF_METAFILEPICT";
413 case CF_SYLK
: return "CF_SYLK";
414 case CF_DIF
: return "CF_DIF";
415 case CF_TIFF
: return "CF_TIFF";
416 case CF_OEMTEXT
: return "CF_OEMTEXT";
417 case CF_DIB
: return "CF_DIB";
418 case CF_PALETTE
: return "CF_PALETTE";
419 case CF_PENDATA
: return "CF_PENDATA";
420 case CF_RIFF
: return "CF_RIFF";
421 case CF_WAVE
: return "CF_WAVE";
422 case CF_UNICODETEXT
: return "CF_UNICODETEXT";
423 case CF_ENHMETAFILE
: return "CF_ENHMETAFILE";
424 case CF_HDROP
: return "CF_HDROP";
425 case CF_LOCALE
: return "CF_LOCALE";
427 sprintf(s_szBuf
, "clipboard format %d (unknown)", format
);
432 #pragma warning(default:4063)
440 // ----------------------------------------------------------------------------
441 // wxPrivateDataObject
442 // ----------------------------------------------------------------------------
444 wxPrivateDataObject::wxPrivateDataObject()
450 void wxPrivateDataObject::Free()
456 void wxPrivateDataObject::SetData( const void *data
, size_t size
)
461 m_data
= malloc(size
);
463 memcpy( m_data
, data
, size
);
466 void wxPrivateDataObject::WriteData( void *dest
) const
468 WriteData( m_data
, dest
);
471 size_t wxPrivateDataObject::GetSize() const
476 void wxPrivateDataObject::WriteData( const void *data
, void *dest
) const
478 memcpy( dest
, data
, GetSize() );
481 // ----------------------------------------------------------------------------
483 // ----------------------------------------------------------------------------
484 static const char *GetTymedName(DWORD tymed
)
486 static char s_szBuf
[128];
488 case TYMED_HGLOBAL
: return "TYMED_HGLOBAL";
489 case TYMED_FILE
: return "TYMED_FILE";
490 case TYMED_ISTREAM
: return "TYMED_ISTREAM";
491 case TYMED_ISTORAGE
: return "TYMED_ISTORAGE";
492 case TYMED_GDI
: return "TYMED_GDI";
493 case TYMED_MFPICT
: return "TYMED_MFPICT";
494 case TYMED_ENHMF
: return "TYMED_ENHMF";
496 sprintf(s_szBuf
, "type of media format %d (unknown)", tymed
);
501 // TODO: OLE parts of wxBitmap/File/MetafileDataObject