]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/ole/dataobj.cpp
3 // Purpose: implementation of wx[I]DataObject class
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #if defined(__BORLANDC__)
30 #include "wx/wxcrtvararg.h"
33 #include "wx/dataobj.h"
35 #if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__)
37 #include "wx/scopedarray.h"
38 #include "wx/vector.h"
39 #include "wx/msw/private.h" // includes <windows.h>
45 // for some compilers, the entire ole2.h must be included, not only oleauto.h
46 #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__)
53 #include "wx/msw/ole/oleutils.h"
55 #include "wx/msw/dib.h"
57 #ifndef CFSTR_SHELLURL
58 #define CFSTR_SHELLURL wxT("UniformResourceLocator")
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
66 static const wxChar
*GetTymedName(DWORD tymed
);
67 #else // !wxDEBUG_LEVEL
68 #define GetTymedName(tymed) wxEmptyString
69 #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
74 wxDataFormat
HtmlFormatFixup(wxDataFormat format
)
76 // Since the HTML format is dynamically registered, the wxDF_HTML
77 // format does not match the native constant in the way other formats do,
78 // so for the format checks below to work, we must change the native
79 // id to the wxDF_HTML constant.
81 if (::GetClipboardFormatName(format
, s_szBuf
, WXSIZEOF(s_szBuf
)))
83 if (s_szBuf
== wxString("HTML Format"))
89 // helper function for wxCopyStgMedium()
90 HGLOBAL
wxGlobalClone(HGLOBAL hglobIn
)
92 HGLOBAL hglobOut
= NULL
;
94 LPVOID pvIn
= GlobalLock(hglobIn
);
97 SIZE_T cb
= GlobalSize(hglobIn
);
98 hglobOut
= GlobalAlloc(GMEM_FIXED
, cb
);
101 CopyMemory(hglobOut
, pvIn
, cb
);
103 GlobalUnlock(hglobIn
);
109 // Copies the given STGMEDIUM structure.
111 // This is an local implementation of the function with the same name in
112 // urlmon.lib but to use that function would require linking with urlmon.lib
113 // and we don't want to require it, so simple reimplement it here.
114 HRESULT
wxCopyStgMedium(const STGMEDIUM
*pmediumIn
, STGMEDIUM
*pmediumOut
)
117 STGMEDIUM stgmOut
= *pmediumIn
;
119 if (pmediumIn
->pUnkForRelease
== NULL
&&
120 !(pmediumIn
->tymed
& (TYMED_ISTREAM
| TYMED_ISTORAGE
)))
122 // Object needs to be cloned.
123 if (pmediumIn
->tymed
== TYMED_HGLOBAL
)
125 stgmOut
.hGlobal
= wxGlobalClone(pmediumIn
->hGlobal
);
126 if (!stgmOut
.hGlobal
)
128 hres
= E_OUTOFMEMORY
;
133 hres
= DV_E_TYMED
; // Don't know how to clone GDI objects.
137 if ( SUCCEEDED(hres
) )
139 switch ( stgmOut
.tymed
)
142 stgmOut
.pstm
->AddRef();
146 stgmOut
.pstg
->AddRef();
150 if ( stgmOut
.pUnkForRelease
)
151 stgmOut
.pUnkForRelease
->AddRef();
153 *pmediumOut
= stgmOut
;
159 } // anonymous namespace
161 // ----------------------------------------------------------------------------
162 // wxIEnumFORMATETC interface implementation
163 // ----------------------------------------------------------------------------
165 class wxIEnumFORMATETC
: public IEnumFORMATETC
168 wxIEnumFORMATETC(const wxDataFormat
* formats
, ULONG nCount
);
169 virtual ~wxIEnumFORMATETC() { delete [] m_formats
; }
172 STDMETHODIMP
Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFetched
);
173 STDMETHODIMP
Skip(ULONG celt
);
174 STDMETHODIMP
Reset();
175 STDMETHODIMP
Clone(IEnumFORMATETC
**ppenum
);
177 DECLARE_IUNKNOWN_METHODS
;
180 CLIPFORMAT
*m_formats
; // formats we can provide data in
181 ULONG m_nCount
, // number of formats we support
182 m_nCurrent
; // current enum position
184 wxDECLARE_NO_COPY_CLASS(wxIEnumFORMATETC
);
187 // ----------------------------------------------------------------------------
188 // wxIDataObject implementation of IDataObject interface
189 // ----------------------------------------------------------------------------
191 class wxIDataObject
: public IDataObject
194 wxIDataObject(wxDataObject
*pDataObject
);
195 virtual ~wxIDataObject();
197 // normally, wxDataObject controls our lifetime (i.e. we're deleted when it
198 // is), but in some cases, the situation is reversed, that is we delete it
199 // when this object is deleted - setting this flag enables such logic
200 void SetDeleteFlag() { m_mustDelete
= true; }
203 STDMETHODIMP
GetData(FORMATETC
*pformatetcIn
, STGMEDIUM
*pmedium
);
204 STDMETHODIMP
GetDataHere(FORMATETC
*pformatetc
, STGMEDIUM
*pmedium
);
205 STDMETHODIMP
QueryGetData(FORMATETC
*pformatetc
);
206 STDMETHODIMP
GetCanonicalFormatEtc(FORMATETC
*In
, FORMATETC
*pOut
);
207 STDMETHODIMP
SetData(FORMATETC
*pfetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
208 STDMETHODIMP
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFEtc
);
209 STDMETHODIMP
DAdvise(FORMATETC
*pfetc
, DWORD ad
, IAdviseSink
*p
, DWORD
*pdw
);
210 STDMETHODIMP
DUnadvise(DWORD dwConnection
);
211 STDMETHODIMP
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
213 DECLARE_IUNKNOWN_METHODS
;
216 wxDataObject
*m_pDataObject
; // pointer to C++ class we belong to
220 wxDECLARE_NO_COPY_CLASS(wxIDataObject
);
222 // The following code is need to be able to store system data the operating
223 // system is using for it own purposes, e.g. drag images.
225 class SystemDataEntry
228 // Ctor takes ownership of the pointers.
229 SystemDataEntry(FORMATETC
*pformatetc
, STGMEDIUM
*pmedium
)
230 : pformatetc(pformatetc
), pmedium(pmedium
)
240 FORMATETC
*pformatetc
;
243 typedef wxVector
<SystemDataEntry
*> SystemData
;
245 // get system data specified by the given format
246 bool GetSystemData(wxDataFormat format
, STGMEDIUM
*) const;
248 // determines if the data object contains system data specified by the given format.
249 bool HasSystemData(wxDataFormat format
) const;
252 HRESULT
SaveSystemData(FORMATETC
*, STGMEDIUM
*, BOOL fRelease
);
254 // container for system data
255 SystemData m_systemData
;
259 wxIDataObject::GetSystemData(wxDataFormat format
, STGMEDIUM
*pmedium
) const
261 for ( SystemData::const_iterator it
= m_systemData
.begin();
262 it
!= m_systemData
.end();
265 FORMATETC
* formatEtc
= (*it
)->pformatetc
;
266 if ( formatEtc
->cfFormat
== format
)
268 wxCopyStgMedium((*it
)->pmedium
, pmedium
);
277 wxIDataObject::HasSystemData(wxDataFormat format
) const
279 for ( SystemData::const_iterator it
= m_systemData
.begin();
280 it
!= m_systemData
.end();
283 FORMATETC
* formatEtc
= (*it
)->pformatetc
;
284 if ( formatEtc
->cfFormat
== format
)
293 wxIDataObject::SaveSystemData(FORMATETC
*pformatetc
,
297 if ( pformatetc
== NULL
|| pmedium
== NULL
)
300 // remove entry if already available
301 for ( SystemData::iterator it
= m_systemData
.begin();
302 it
!= m_systemData
.end();
305 if ( pformatetc
->tymed
& (*it
)->pformatetc
->tymed
&&
306 pformatetc
->dwAspect
== (*it
)->pformatetc
->dwAspect
&&
307 pformatetc
->cfFormat
== (*it
)->pformatetc
->cfFormat
)
310 m_systemData
.erase(it
);
315 // create new format/medium
316 FORMATETC
* pnewformatEtc
= new FORMATETC
;
317 STGMEDIUM
* pnewmedium
= new STGMEDIUM
;
319 wxZeroMemory(*pnewformatEtc
);
320 wxZeroMemory(*pnewmedium
);
323 *pnewformatEtc
= *pformatetc
;
325 // copy or take ownerschip of medium
327 *pnewmedium
= *pmedium
;
329 wxCopyStgMedium(pmedium
, pnewmedium
);
332 m_systemData
.push_back(new SystemDataEntry(pnewformatEtc
, pnewmedium
));
337 // ============================================================================
339 // ============================================================================
341 // ----------------------------------------------------------------------------
343 // ----------------------------------------------------------------------------
345 void wxDataFormat::SetId(const wxString
& format
)
347 m_format
= (wxDataFormat::NativeFormat
)::RegisterClipboardFormat(format
.t_str());
350 wxLogError(_("Couldn't register clipboard format '%s'."), format
);
354 wxString
wxDataFormat::GetId() const
356 static const int max
= 256;
360 wxCHECK_MSG( !IsStandard(), s
,
361 wxT("name of predefined format cannot be retrieved") );
363 int len
= ::GetClipboardFormatName(m_format
, wxStringBuffer(s
, max
), max
);
367 wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
);
368 return wxEmptyString
;
374 // ----------------------------------------------------------------------------
376 // ----------------------------------------------------------------------------
378 BEGIN_IID_TABLE(wxIEnumFORMATETC
)
380 ADD_IID(EnumFORMATETC
)
383 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
)
385 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat
*formats
, ULONG nCount
)
389 m_formats
= new CLIPFORMAT
[nCount
];
390 for ( ULONG n
= 0; n
< nCount
; n
++ ) {
391 if (formats
[n
].GetFormatId() != wxDF_HTML
)
392 m_formats
[n
] = formats
[n
].GetFormatId();
394 m_formats
[n
] = ::RegisterClipboardFormat(wxT("HTML Format"));
398 STDMETHODIMP
wxIEnumFORMATETC::Next(ULONG celt
,
402 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Next"));
404 ULONG numFetched
= 0;
405 while (m_nCurrent
< m_nCount
&& numFetched
< celt
) {
407 format
.cfFormat
= m_formats
[m_nCurrent
++];
409 format
.dwAspect
= DVASPECT_CONTENT
;
411 format
.tymed
= TYMED_HGLOBAL
;
418 *pceltFetched
= numFetched
;
420 return numFetched
== celt
? S_OK
: S_FALSE
;
423 STDMETHODIMP
wxIEnumFORMATETC::Skip(ULONG celt
)
425 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Skip"));
428 if ( m_nCurrent
< m_nCount
)
431 // no, can't skip this many elements
437 STDMETHODIMP
wxIEnumFORMATETC::Reset()
439 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Reset"));
446 STDMETHODIMP
wxIEnumFORMATETC::Clone(IEnumFORMATETC
**ppenum
)
448 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Clone"));
450 // unfortunately, we can't reuse the code in ctor - types are different
451 wxIEnumFORMATETC
*pNew
= new wxIEnumFORMATETC(NULL
, 0);
452 pNew
->m_nCount
= m_nCount
;
453 pNew
->m_formats
= new CLIPFORMAT
[m_nCount
];
454 for ( ULONG n
= 0; n
< m_nCount
; n
++ ) {
455 pNew
->m_formats
[n
] = m_formats
[n
];
463 // ----------------------------------------------------------------------------
465 // ----------------------------------------------------------------------------
467 BEGIN_IID_TABLE(wxIDataObject
)
472 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
)
474 wxIDataObject::wxIDataObject(wxDataObject
*pDataObject
)
476 m_pDataObject
= pDataObject
;
477 m_mustDelete
= false;
480 wxIDataObject::~wxIDataObject()
482 // delete system data
483 for ( SystemData::iterator it
= m_systemData
.begin();
484 it
!= m_systemData
.end();
492 delete m_pDataObject
;
496 // get data functions
497 STDMETHODIMP
wxIDataObject::GetData(FORMATETC
*pformatetcIn
, STGMEDIUM
*pmedium
)
499 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetData"));
501 // is data is in our format?
502 HRESULT hr
= QueryGetData(pformatetcIn
);
506 // for the bitmaps and metafiles we use the handles instead of global memory
508 wxDataFormat format
= (wxDataFormat::NativeFormat
)pformatetcIn
->cfFormat
;
509 format
= HtmlFormatFixup(format
);
511 // is this system data?
512 if ( GetSystemData(format
, pmedium
) )
514 // pmedium is already filled with corresponding data, so we're ready.
521 pmedium
->tymed
= TYMED_GDI
;
524 case wxDF_ENHMETAFILE
:
525 pmedium
->tymed
= TYMED_ENHMF
;
530 pmedium
->hGlobal
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
,
531 sizeof(METAFILEPICT
));
532 if ( !pmedium
->hGlobal
) {
533 wxLogLastError(wxT("GlobalAlloc"));
534 return E_OUTOFMEMORY
;
536 pmedium
->tymed
= TYMED_MFPICT
;
541 size_t size
= m_pDataObject
->GetDataSize(format
);
543 // it probably means that the method is just not implemented
544 wxLogDebug(wxT("Invalid data size - can't be 0"));
546 return DV_E_FORMATETC
;
549 // we may need extra space for the buffer size
550 size
+= m_pDataObject
->GetBufferOffset( format
);
552 HGLOBAL hGlobal
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
, size
);
553 if ( hGlobal
== NULL
) {
554 wxLogLastError(wxT("GlobalAlloc"));
555 return E_OUTOFMEMORY
;
559 pmedium
->tymed
= TYMED_HGLOBAL
;
560 pmedium
->hGlobal
= hGlobal
;
563 pmedium
->pUnkForRelease
= NULL
;
566 hr
= GetDataHere(pformatetcIn
, pmedium
);
568 // free resources we allocated
569 if ( pmedium
->tymed
& (TYMED_HGLOBAL
| TYMED_MFPICT
) ) {
570 GlobalFree(pmedium
->hGlobal
);
579 STDMETHODIMP
wxIDataObject::GetDataHere(FORMATETC
*pformatetc
,
582 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetDataHere"));
584 // put data in caller provided medium
585 switch ( pmedium
->tymed
)
588 if ( !m_pDataObject
->GetDataHere(wxDF_BITMAP
, &pmedium
->hBitmap
) )
593 if ( !m_pDataObject
->GetDataHere(wxDF_ENHMETAFILE
,
594 &pmedium
->hEnhMetaFile
) )
599 // fall through - we pass METAFILEPICT through HGLOBAL
604 HGLOBAL hGlobal
= pmedium
->hGlobal
;
605 void *pBuf
= GlobalLock(hGlobal
);
606 if ( pBuf
== NULL
) {
607 wxLogLastError(wxT("GlobalLock"));
608 return E_OUTOFMEMORY
;
611 wxDataFormat format
= pformatetc
->cfFormat
;
613 // possibly put the size in the beginning of the buffer
614 pBuf
= m_pDataObject
->SetSizeInBuffer
617 ::GlobalSize(hGlobal
),
621 if ( !m_pDataObject
->GetDataHere(format
, pBuf
) )
624 GlobalUnlock(hGlobal
);
636 // set data functions
637 STDMETHODIMP
wxIDataObject::SetData(FORMATETC
*pformatetc
,
641 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::SetData"));
643 switch ( pmedium
->tymed
)
646 m_pDataObject
->SetData(wxDF_BITMAP
, 0, &pmedium
->hBitmap
);
650 m_pDataObject
->SetData(wxDF_ENHMETAFILE
, 0, &pmedium
->hEnhMetaFile
);
654 // check if this format is supported
655 if ( !m_pDataObject
->IsSupported(pformatetc
->cfFormat
,
658 // As this is not a supported format (content data), assume it
659 // is system data and save it.
660 return SaveSystemData(pformatetc
, pmedium
, fRelease
);
665 // fall through - we pass METAFILEPICT through HGLOBAL
668 wxDataFormat format
= pformatetc
->cfFormat
;
670 format
= HtmlFormatFixup(format
);
672 // check if this format is supported
673 if ( !m_pDataObject
->IsSupported(format
, wxDataObject::Set
) ) {
674 // As above, assume that unsupported format must be system
675 // data and just save it.
676 return SaveSystemData(pformatetc
, pmedium
, fRelease
);
680 const void *pBuf
= GlobalLock(pmedium
->hGlobal
);
681 if ( pBuf
== NULL
) {
682 wxLogLastError(wxT("GlobalLock"));
684 return E_OUTOFMEMORY
;
687 // we've got a problem with SetData() here because the base
688 // class version requires the size parameter which we don't
689 // have anywhere in OLE data transfer - so we need to
690 // synthetise it for known formats and we suppose that all data
691 // in custom formats starts with a DWORD containing the size
698 size
= strlen((const char *)pBuf
);
700 #if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500))
702 #if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) )
703 size
= std::wcslen((const wchar_t *)pBuf
) * sizeof(wchar_t);
705 size
= wxWcslen((const wchar_t *)pBuf
) * sizeof(wchar_t);
712 // these formats don't use size at all, anyhow (but
713 // pass data by handle, which is always a single DWORD)
719 // the handler will calculate size itself (it's too
720 // complicated to do it here)
725 case CF_METAFILEPICT
:
726 size
= sizeof(METAFILEPICT
);
730 pBuf
= m_pDataObject
->
731 GetSizeFromBuffer(pBuf
, &size
, format
);
732 size
-= m_pDataObject
->GetBufferOffset(format
);
735 bool ok
= m_pDataObject
->SetData(format
, size
, pBuf
);
737 GlobalUnlock(pmedium
->hGlobal
);
750 // we own the medium, so we must release it - but do *not* free any
751 // data we pass by handle because we have copied it elsewhere
752 switch ( pmedium
->tymed
)
755 pmedium
->hBitmap
= 0;
759 pmedium
->hMetaFilePict
= 0;
763 pmedium
->hEnhMetaFile
= 0;
767 ReleaseStgMedium(pmedium
);
773 // information functions
774 STDMETHODIMP
wxIDataObject::QueryGetData(FORMATETC
*pformatetc
)
776 // do we accept data in this format?
777 if ( pformatetc
== NULL
) {
778 wxLogTrace(wxTRACE_OleCalls
,
779 wxT("wxIDataObject::QueryGetData: invalid ptr."));
784 // the only one allowed by current COM implementation
785 if ( pformatetc
->lindex
!= -1 ) {
786 wxLogTrace(wxTRACE_OleCalls
,
787 wxT("wxIDataObject::QueryGetData: bad lindex %ld"),
793 // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
794 if ( pformatetc
->dwAspect
!= DVASPECT_CONTENT
) {
795 wxLogTrace(wxTRACE_OleCalls
,
796 wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"),
797 pformatetc
->dwAspect
);
799 return DV_E_DVASPECT
;
802 // and now check the type of data requested
803 wxDataFormat format
= pformatetc
->cfFormat
;
804 format
= HtmlFormatFixup(format
);
806 if ( m_pDataObject
->IsSupportedFormat(format
) ) {
807 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok"),
808 wxGetFormatName(format
));
810 else if ( HasSystemData(format
) )
812 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok (system data)"),
813 wxGetFormatName(format
));
814 // this is system data, so no further checks needed.
818 wxLogTrace(wxTRACE_OleCalls
,
819 wxT("wxIDataObject::QueryGetData: %s unsupported"),
820 wxGetFormatName(format
));
822 return DV_E_FORMATETC
;
825 // we only transfer data by global memory, except for some particular cases
826 DWORD tymed
= pformatetc
->tymed
;
827 if ( (format
== wxDF_BITMAP
&& !(tymed
& TYMED_GDI
)) &&
828 !(tymed
& TYMED_HGLOBAL
) ) {
829 // it's not what we're waiting for
830 wxLogTrace(wxTRACE_OleCalls
,
831 wxT("wxIDataObject::QueryGetData: %s != %s"),
833 GetTymedName(format
== wxDF_BITMAP
? TYMED_GDI
842 STDMETHODIMP
wxIDataObject::GetCanonicalFormatEtc(FORMATETC
*WXUNUSED(pFormatetcIn
),
843 FORMATETC
*pFormatetcOut
)
845 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetCanonicalFormatEtc"));
847 // TODO we might want something better than this trivial implementation here
848 if ( pFormatetcOut
!= NULL
)
849 pFormatetcOut
->ptd
= NULL
;
851 return DATA_S_SAMEFORMATETC
;
854 STDMETHODIMP
wxIDataObject::EnumFormatEtc(DWORD dwDir
,
855 IEnumFORMATETC
**ppenumFormatEtc
)
857 wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::EnumFormatEtc"));
859 wxDataObject::Direction dir
= dwDir
== DATADIR_GET
? wxDataObject::Get
862 // format count is total of user specified and system formats.
863 const size_t ourFormatCount
= m_pDataObject
->GetFormatCount(dir
);
864 const size_t sysFormatCount
= m_systemData
.size();
867 nFormatCount
= wx_truncate_cast(ULONG
, ourFormatCount
+ sysFormatCount
);
869 // fill format array with formats ...
870 wxScopedArray
<wxDataFormat
> formats(new wxDataFormat
[nFormatCount
]);
872 // ... from content data (supported formats)
873 m_pDataObject
->GetAllFormats(formats
.get(), dir
);
875 // ... from system data
876 for ( size_t j
= 0; j
< sysFormatCount
; j
++ )
878 SystemDataEntry
* entry
= m_systemData
[j
];
879 wxDataFormat
& format
= formats
[ourFormatCount
+ j
];
880 format
= entry
->pformatetc
->cfFormat
;
883 wxIEnumFORMATETC
*pEnum
= new wxIEnumFORMATETC(formats
.get(), nFormatCount
);
885 *ppenumFormatEtc
= pEnum
;
890 // ----------------------------------------------------------------------------
891 // advise sink functions (not implemented)
892 // ----------------------------------------------------------------------------
894 STDMETHODIMP
wxIDataObject::DAdvise(FORMATETC
*WXUNUSED(pformatetc
),
895 DWORD
WXUNUSED(advf
),
896 IAdviseSink
*WXUNUSED(pAdvSink
),
897 DWORD
*WXUNUSED(pdwConnection
))
899 return OLE_E_ADVISENOTSUPPORTED
;
902 STDMETHODIMP
wxIDataObject::DUnadvise(DWORD
WXUNUSED(dwConnection
))
904 return OLE_E_ADVISENOTSUPPORTED
;
907 STDMETHODIMP
wxIDataObject::EnumDAdvise(IEnumSTATDATA
**WXUNUSED(ppenumAdvise
))
909 return OLE_E_ADVISENOTSUPPORTED
;
912 // ----------------------------------------------------------------------------
914 // ----------------------------------------------------------------------------
916 wxDataObject::wxDataObject()
918 m_pIDataObject
= new wxIDataObject(this);
919 m_pIDataObject
->AddRef();
922 wxDataObject::~wxDataObject()
924 ReleaseInterface(m_pIDataObject
);
927 void wxDataObject::SetAutoDelete()
929 ((wxIDataObject
*)m_pIDataObject
)->SetDeleteFlag();
930 m_pIDataObject
->Release();
932 // so that the dtor doesn't crash
933 m_pIDataObject
= NULL
;
936 size_t wxDataObject::GetBufferOffset(const wxDataFormat
& format
)
938 // if we prepend the size of the data to the buffer itself, account for it
939 return NeedsVerbatimData(format
) ? 0 : sizeof(size_t);
942 const void *wxDataObject::GetSizeFromBuffer(const void *buffer
,
944 const wxDataFormat
& WXUNUSED(format
))
946 // hack: the third parameter is declared non-const in Wine's headers so
947 // cast away the const
948 const size_t realsz
= ::HeapSize(::GetProcessHeap(), 0,
949 const_cast<void*>(buffer
));
950 if ( realsz
== (size_t)-1 )
952 // note that HeapSize() does not set last error
953 wxLogApiError(wxT("HeapSize"), 0);
962 void* wxDataObject::SetSizeInBuffer( void* buffer
, size_t size
,
963 const wxDataFormat
& format
)
965 size_t* p
= (size_t *)buffer
;
966 if ( !NeedsVerbatimData(format
) )
968 // prepend the size to the data and skip it
977 const wxChar
*wxDataObject::GetFormatName(wxDataFormat format
)
979 // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
981 #pragma warning(disable:4063)
984 static wxChar s_szBuf
[256];
986 case CF_TEXT
: return wxT("CF_TEXT");
987 case CF_BITMAP
: return wxT("CF_BITMAP");
988 case CF_SYLK
: return wxT("CF_SYLK");
989 case CF_DIF
: return wxT("CF_DIF");
990 case CF_TIFF
: return wxT("CF_TIFF");
991 case CF_OEMTEXT
: return wxT("CF_OEMTEXT");
992 case CF_DIB
: return wxT("CF_DIB");
993 case CF_PALETTE
: return wxT("CF_PALETTE");
994 case CF_PENDATA
: return wxT("CF_PENDATA");
995 case CF_RIFF
: return wxT("CF_RIFF");
996 case CF_WAVE
: return wxT("CF_WAVE");
997 case CF_UNICODETEXT
: return wxT("CF_UNICODETEXT");
999 case CF_METAFILEPICT
: return wxT("CF_METAFILEPICT");
1000 case CF_ENHMETAFILE
: return wxT("CF_ENHMETAFILE");
1001 case CF_LOCALE
: return wxT("CF_LOCALE");
1002 case CF_HDROP
: return wxT("CF_HDROP");
1006 if ( !::GetClipboardFormatName(format
, s_szBuf
, WXSIZEOF(s_szBuf
)) )
1008 // it must be a new predefined format we don't know the name of
1009 wxSprintf(s_szBuf
, wxT("unknown CF (0x%04x)"), format
.GetFormatId());
1016 #pragma warning(default:4063)
1020 #endif // wxDEBUG_LEVEL
1022 // ----------------------------------------------------------------------------
1023 // wxBitmapDataObject supports CF_DIB format
1024 // ----------------------------------------------------------------------------
1026 // TODO: support CF_DIB under Windows CE as well
1028 size_t wxBitmapDataObject::GetDataSize() const
1030 #if wxUSE_WXDIB && !defined(__WXWINCE__)
1031 return wxDIB::ConvertFromBitmap(NULL
, GetHbitmapOf(GetBitmap()));
1037 bool wxBitmapDataObject::GetDataHere(void *buf
) const
1039 #if wxUSE_WXDIB && !defined(__WXWINCE__)
1040 BITMAPINFO
* const pbi
= (BITMAPINFO
*)buf
;
1042 return wxDIB::ConvertFromBitmap(pbi
, GetHbitmapOf(GetBitmap())) != 0;
1049 bool wxBitmapDataObject::SetData(size_t WXUNUSED(len
), const void *buf
)
1051 #if wxUSE_WXDIB && !defined(__WXWINCE__)
1052 const BITMAPINFO
* const pbmi
= (const BITMAPINFO
*)buf
;
1054 HBITMAP hbmp
= wxDIB::ConvertToBitmap(pbmi
);
1056 wxCHECK_MSG( hbmp
, FALSE
, wxT("pasting/dropping invalid bitmap") );
1058 const BITMAPINFOHEADER
* const pbmih
= &pbmi
->bmiHeader
;
1059 wxBitmap
bitmap(pbmih
->biWidth
, pbmih
->biHeight
, pbmih
->biBitCount
);
1060 bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
);
1062 // TODO: create wxPalette if the bitmap has any
1073 // ----------------------------------------------------------------------------
1074 // wxBitmapDataObject2 supports CF_BITMAP format
1075 // ----------------------------------------------------------------------------
1077 // the bitmaps aren't passed by value as other types of data (i.e. by copying
1078 // the data into a global memory chunk and passing it to the clipboard or
1079 // another application or whatever), but by handle, so these generic functions
1080 // don't make much sense to them.
1082 size_t wxBitmapDataObject2::GetDataSize() const
1087 bool wxBitmapDataObject2::GetDataHere(void *pBuf
) const
1089 // we put a bitmap handle into pBuf
1090 *(WXHBITMAP
*)pBuf
= GetBitmap().GetHBITMAP();
1095 bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len
), const void *pBuf
)
1097 HBITMAP hbmp
= *(HBITMAP
*)pBuf
;
1100 if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) )
1102 wxLogLastError(wxT("GetObject(HBITMAP)"));
1105 wxBitmap
bitmap(bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
);
1106 bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
);
1108 if ( !bitmap
.IsOk() ) {
1109 wxFAIL_MSG(wxT("pasting/dropping invalid bitmap"));
1121 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat
& format
) const
1123 if ( format
.GetFormatId() == CF_DIB
)
1128 // shouldn't be selected into a DC or GetDIBits() would fail
1129 wxASSERT_MSG( !m_bitmap
.GetSelectedInto(),
1130 wxT("can't copy bitmap selected into wxMemoryDC") );
1132 // first get the info
1134 if ( !GetDIBits(hdc
, (HBITMAP
)m_bitmap
.GetHBITMAP(), 0, 0,
1135 NULL
, &bi
, DIB_RGB_COLORS
) )
1137 wxLogLastError(wxT("GetDIBits(NULL)"));
1142 return sizeof(BITMAPINFO
) + bi
.bmiHeader
.biSizeImage
;
1146 // no data to copy - we don't pass HBITMAP via global memory
1151 bool wxBitmapDataObject::GetDataHere(const wxDataFormat
& format
,
1154 wxASSERT_MSG( m_bitmap
.IsOk(), wxT("copying invalid bitmap") );
1156 HBITMAP hbmp
= (HBITMAP
)m_bitmap
.GetHBITMAP();
1157 if ( format
.GetFormatId() == CF_DIB
)
1162 // shouldn't be selected into a DC or GetDIBits() would fail
1163 wxASSERT_MSG( !m_bitmap
.GetSelectedInto(),
1164 wxT("can't copy bitmap selected into wxMemoryDC") );
1166 // first get the info
1167 BITMAPINFO
*pbi
= (BITMAPINFO
*)pBuf
;
1168 if ( !GetDIBits(hdc
, hbmp
, 0, 0, NULL
, pbi
, DIB_RGB_COLORS
) )
1170 wxLogLastError(wxT("GetDIBits(NULL)"));
1175 // and now copy the bits
1176 if ( !GetDIBits(hdc
, hbmp
, 0, pbi
->bmiHeader
.biHeight
, pbi
+ 1,
1177 pbi
, DIB_RGB_COLORS
) )
1179 wxLogLastError(wxT("GetDIBits"));
1186 // we put a bitmap handle into pBuf
1187 *(HBITMAP
*)pBuf
= hbmp
;
1193 bool wxBitmapDataObject::SetData(const wxDataFormat
& format
,
1194 size_t size
, const void *pBuf
)
1197 if ( format
.GetFormatId() == CF_DIB
)
1199 // here we get BITMAPINFO struct followed by the actual bitmap bits and
1200 // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
1203 BITMAPINFO
*pbmi
= (BITMAPINFO
*)pBuf
;
1204 BITMAPINFOHEADER
*pbmih
= &pbmi
->bmiHeader
;
1205 hbmp
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
,
1206 pbmi
+ 1, pbmi
, DIB_RGB_COLORS
);
1209 wxLogLastError(wxT("CreateDIBitmap"));
1212 m_bitmap
.SetWidth(pbmih
->biWidth
);
1213 m_bitmap
.SetHeight(pbmih
->biHeight
);
1217 // it's easy with bitmaps: we pass them by handle
1218 hbmp
= *(HBITMAP
*)pBuf
;
1221 if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) )
1223 wxLogLastError(wxT("GetObject(HBITMAP)"));
1226 m_bitmap
.SetWidth(bmp
.bmWidth
);
1227 m_bitmap
.SetHeight(bmp
.bmHeight
);
1228 m_bitmap
.SetDepth(bmp
.bmPlanes
);
1231 m_bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
);
1233 wxASSERT_MSG( m_bitmap
.IsOk(), wxT("pasting invalid bitmap") );
1240 // ----------------------------------------------------------------------------
1242 // ----------------------------------------------------------------------------
1244 bool wxFileDataObject::SetData(size_t WXUNUSED(size
),
1245 const void *WXUNUSED_IN_WINCE(pData
))
1248 m_filenames
.Empty();
1250 // the documentation states that the first member of DROPFILES structure is
1251 // a "DWORD offset of double NUL terminated file list". What they mean by
1252 // this (I wonder if you see it immediately) is that the list starts at
1253 // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised
1254 // to use DragQueryFile to work with this structure, but not told where and
1255 // how to get HDROP.
1256 HDROP hdrop
= (HDROP
)pData
; // NB: it works, but I'm not sure about it
1258 // get number of files (magic value -1)
1259 UINT nFiles
= ::DragQueryFile(hdrop
, (unsigned)-1, NULL
, 0u);
1261 wxCHECK_MSG ( nFiles
!= (UINT
)-1, FALSE
, wxT("wrong HDROP handle") );
1263 // for each file get the length, allocate memory and then get the name
1266 for ( n
= 0; n
< nFiles
; n
++ ) {
1267 // +1 for terminating NUL
1268 len
= ::DragQueryFile(hdrop
, n
, NULL
, 0) + 1;
1270 UINT len2
= ::DragQueryFile(hdrop
, n
, wxStringBuffer(str
, len
), len
);
1271 m_filenames
.Add(str
);
1273 if ( len2
!= len
- 1 ) {
1274 wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\
1275 %d characters, %d expected."), len2
, len
- 1);
1285 void wxFileDataObject::AddFile(const wxString
& file
)
1287 // just add file to filenames array
1288 // all useful data (such as DROPFILES struct) will be
1289 // created later as necessary
1290 m_filenames
.Add(file
);
1293 size_t wxFileDataObject::GetDataSize() const
1296 // size returned will be the size of the DROPFILES structure, plus the list
1297 // of filesnames (null byte separated), plus a double null at the end
1299 // if no filenames in list, size is 0
1300 if ( m_filenames
.empty() )
1303 #if wxUSE_UNICODE_MSLU
1305 if ( wxGetOsVersion() == wxOS_WINDOWS_9X
)
1307 // Win9x always uses ANSI file names and MSLU doesn't help with this
1312 sizeOfChar
= sizeof(wxChar
);
1314 #else // !wxUSE_UNICODE_MSLU
1315 static const size_t sizeOfChar
= sizeof(wxChar
);
1316 #endif // wxUSE_UNICODE_MSLU/!wxUSE_UNICODE_MSLU
1318 // initial size of DROPFILES struct + null byte
1319 size_t sz
= sizeof(DROPFILES
) + sizeOfChar
;
1321 const size_t count
= m_filenames
.size();
1322 for ( size_t i
= 0; i
< count
; i
++ )
1324 // add filename length plus null byte
1326 #if wxUSE_UNICODE_MSLU
1327 if ( sizeOfChar
== 1 )
1328 len
= strlen(m_filenames
[i
].mb_str(*wxConvFileName
));
1330 #endif // wxUSE_UNICODE_MSLU
1331 len
= m_filenames
[i
].length();
1333 sz
+= (len
+ 1) * sizeOfChar
;
1342 bool wxFileDataObject::GetDataHere(void *WXUNUSED_IN_WINCE(pData
)) const
1345 // pData points to an externally allocated memory block
1346 // created using the size returned by GetDataSize()
1348 // if pData is NULL, or there are no files, return
1349 if ( !pData
|| m_filenames
.empty() )
1352 // convert data pointer to a DROPFILES struct pointer
1353 LPDROPFILES pDrop
= (LPDROPFILES
) pData
;
1355 // initialize DROPFILES struct
1356 pDrop
->pFiles
= sizeof(DROPFILES
);
1357 pDrop
->fNC
= FALSE
; // not non-client coords
1358 #if wxUSE_UNICODE_MSLU
1359 pDrop
->fWide
= wxGetOsVersion() != wxOS_WINDOWS_9X
? TRUE
: FALSE
;
1361 pDrop
->fWide
= wxUSE_UNICODE
;
1364 const size_t sizeOfChar
= pDrop
->fWide
? sizeof(wchar_t) : 1;
1366 // set start of filenames list (null separated)
1367 BYTE
*pbuf
= (BYTE
*)(pDrop
+ 1);
1369 const size_t count
= m_filenames
.size();
1370 for ( size_t i
= 0; i
< count
; i
++ )
1372 // copy filename to pbuf and add null terminator
1374 #if wxUSE_UNICODE_MSLU
1375 if ( sizeOfChar
== 1 )
1377 wxCharBuffer
buf(m_filenames
[i
].mb_str(*wxConvFileName
));
1379 memcpy(pbuf
, buf
, len
*sizeOfChar
);
1382 #endif // wxUSE_UNICODE_MSLU
1384 len
= m_filenames
[i
].length();
1385 memcpy(pbuf
, m_filenames
[i
].t_str(), len
*sizeOfChar
);
1388 pbuf
+= len
*sizeOfChar
;
1390 memset(pbuf
, 0, sizeOfChar
);
1394 // add final null terminator
1395 memset(pbuf
, 0, sizeOfChar
);
1403 // ----------------------------------------------------------------------------
1405 // ----------------------------------------------------------------------------
1407 // Work around bug in Wine headers
1408 #if defined(__WINE__) && defined(CFSTR_SHELLURL) && wxUSE_UNICODE
1409 #undef CFSTR_SHELLURL
1410 #define CFSTR_SHELLURL wxT("CFSTR_SHELLURL")
1413 class CFSTR_SHELLURLDataObject
: public wxCustomDataObject
1416 CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL
) {}
1418 virtual size_t GetBufferOffset( const wxDataFormat
& WXUNUSED(format
) )
1423 virtual const void* GetSizeFromBuffer( const void* buffer
, size_t* size
,
1424 const wxDataFormat
& WXUNUSED(format
) )
1426 // CFSTR_SHELLURL is _always_ ANSI text
1427 *size
= strlen( (const char*)buffer
);
1432 virtual void* SetSizeInBuffer( void* buffer
, size_t WXUNUSED(size
),
1433 const wxDataFormat
& WXUNUSED(format
) )
1438 wxDECLARE_NO_COPY_CLASS(CFSTR_SHELLURLDataObject
);
1443 wxURLDataObject::wxURLDataObject(const wxString
& url
)
1445 // we support CF_TEXT and CFSTR_SHELLURL formats which are basically the
1446 // same but it seems that some browsers only provide one of them so we have
1448 Add(new wxTextDataObject
);
1449 Add(new CFSTR_SHELLURLDataObject());
1451 // we don't have any data yet
1452 m_dataObjectLast
= NULL
;
1458 bool wxURLDataObject::SetData(const wxDataFormat
& format
,
1462 m_dataObjectLast
= GetObject(format
);
1464 wxCHECK_MSG( m_dataObjectLast
, FALSE
,
1465 wxT("unsupported format in wxURLDataObject"));
1467 return m_dataObjectLast
->SetData(len
, buf
);
1470 wxString
wxURLDataObject::GetURL() const
1473 wxCHECK_MSG( m_dataObjectLast
, url
, wxT("no data in wxURLDataObject") );
1475 if ( m_dataObjectLast
->GetPreferredFormat() == CFSTR_SHELLURL
)
1477 const size_t len
= m_dataObjectLast
->GetDataSize();
1481 // CFSTR_SHELLURL is always ANSI so we need to convert it from it in
1484 wxCharBuffer
buf(len
);
1486 if ( m_dataObjectLast
->GetDataHere(buf
.data()) )
1488 #else // !wxUSE_UNICODE
1489 // in ANSI build no conversion is necessary
1490 m_dataObjectLast
->GetDataHere(wxStringBuffer(url
, len
));
1491 #endif // wxUSE_UNICODE/!wxUSE_UNICODE
1493 else // must be wxTextDataObject
1495 url
= static_cast<wxTextDataObject
*>(m_dataObjectLast
)->GetText();
1501 void wxURLDataObject::SetURL(const wxString
& url
)
1503 wxCharBuffer
urlMB(url
.mb_str());
1506 const size_t len
= strlen(urlMB
);
1509 // wxTextDataObject takes the number of characters in the string, not
1510 // the size of the buffer (which would be len+1)
1511 SetData(wxDF_TEXT
, len
, urlMB
);
1512 #endif // !wxUSE_UNICODE
1514 // however CFSTR_SHELLURLDataObject doesn't append NUL automatically
1515 // but we probably still want to have it on the clipboard (just to be
1516 // safe), so do append it
1517 SetData(wxDataFormat(CFSTR_SHELLURL
), len
+ 1, urlMB
);
1521 SetData(wxDF_UNICODETEXT
, url
.length()*sizeof(wxChar
), url
.wc_str());
1525 // ----------------------------------------------------------------------------
1526 // private functions
1527 // ----------------------------------------------------------------------------
1531 static const wxChar
*GetTymedName(DWORD tymed
)
1533 static wxChar s_szBuf
[128];
1535 case TYMED_HGLOBAL
: return wxT("TYMED_HGLOBAL");
1536 case TYMED_FILE
: return wxT("TYMED_FILE");
1537 case TYMED_ISTREAM
: return wxT("TYMED_ISTREAM");
1538 case TYMED_ISTORAGE
: return wxT("TYMED_ISTORAGE");
1539 case TYMED_GDI
: return wxT("TYMED_GDI");
1540 case TYMED_MFPICT
: return wxT("TYMED_MFPICT");
1541 case TYMED_ENHMF
: return wxT("TYMED_ENHMF");
1543 wxSprintf(s_szBuf
, wxT("type of media format %ld (unknown)"), tymed
);
1550 #else // not using OLE at all
1552 // ----------------------------------------------------------------------------
1554 // ----------------------------------------------------------------------------
1558 wxDataObject::wxDataObject()
1562 wxDataObject::~wxDataObject()
1566 void wxDataObject::SetAutoDelete()
1570 const wxChar
*wxDataObject::GetFormatName(wxDataFormat
WXUNUSED(format
))
1575 #endif // wxUSE_DATAOBJ
1577 #endif // wxUSE_OLE/!wxUSE_OLE