]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
3831f98b1a266b1de2a0129efadee21dd8986fa5
   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 licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  23 #if defined(__BORLANDC__) 
  31     #include "wx/wxcrtvararg.h" 
  34 #include "wx/dataobj.h" 
  36 #if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__) 
  38 #include "wx/msw/private.h"         // includes <windows.h> 
  44 // for some compilers, the entire ole2.h must be included, not only oleauto.h 
  45 #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__) 
  52 #include "wx/msw/ole/oleutils.h" 
  54 #include "wx/msw/dib.h" 
  56 #ifndef CFSTR_SHELLURL 
  57 #define CFSTR_SHELLURL _T("UniformResourceLocator") 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  65     static const wxChar 
*GetTymedName(DWORD tymed
); 
  67     #define GetTymedName(tymed) wxEmptyString 
  68 #endif // Debug/!Debug 
  70 // ---------------------------------------------------------------------------- 
  71 // wxIEnumFORMATETC interface implementation 
  72 // ---------------------------------------------------------------------------- 
  74 class wxIEnumFORMATETC 
: public IEnumFORMATETC
 
  77     wxIEnumFORMATETC(const wxDataFormat
* formats
, ULONG nCount
); 
  78     virtual ~wxIEnumFORMATETC() { delete [] m_formats
; } 
  81     STDMETHODIMP 
Next(ULONG celt
, FORMATETC 
*rgelt
, ULONG 
*pceltFetched
); 
  82     STDMETHODIMP 
Skip(ULONG celt
); 
  84     STDMETHODIMP 
Clone(IEnumFORMATETC 
**ppenum
); 
  86     DECLARE_IUNKNOWN_METHODS
; 
  89     CLIPFORMAT 
*m_formats
;  // formats we can provide data in 
  90     ULONG       m_nCount
,   // number of formats we support 
  91                 m_nCurrent
; // current enum position 
  93     DECLARE_NO_COPY_CLASS(wxIEnumFORMATETC
) 
  96 // ---------------------------------------------------------------------------- 
  97 // wxIDataObject implementation of IDataObject interface 
  98 // ---------------------------------------------------------------------------- 
 100 class wxIDataObject 
: public IDataObject
 
 103     wxIDataObject(wxDataObject 
*pDataObject
); 
 104     virtual ~wxIDataObject(); 
 106     // normally, wxDataObject controls our lifetime (i.e. we're deleted when it 
 107     // is), but in some cases, the situation is reversed, that is we delete it 
 108     // when this object is deleted - setting this flag enables such logic 
 109     void SetDeleteFlag() { m_mustDelete 
= true; } 
 112     STDMETHODIMP 
GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
); 
 113     STDMETHODIMP 
GetDataHere(FORMATETC 
*pformatetc
, STGMEDIUM 
*pmedium
); 
 114     STDMETHODIMP 
QueryGetData(FORMATETC 
*pformatetc
); 
 115     STDMETHODIMP 
GetCanonicalFormatEtc(FORMATETC 
*In
, FORMATETC 
*pOut
); 
 116     STDMETHODIMP 
SetData(FORMATETC 
*pfetc
, STGMEDIUM 
*pmedium
, BOOL fRelease
); 
 117     STDMETHODIMP 
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC 
**ppenumFEtc
); 
 118     STDMETHODIMP 
DAdvise(FORMATETC 
*pfetc
, DWORD ad
, IAdviseSink 
*p
, DWORD 
*pdw
); 
 119     STDMETHODIMP 
DUnadvise(DWORD dwConnection
); 
 120     STDMETHODIMP 
EnumDAdvise(IEnumSTATDATA 
**ppenumAdvise
); 
 122     DECLARE_IUNKNOWN_METHODS
; 
 125     wxDataObject 
*m_pDataObject
;      // pointer to C++ class we belong to 
 129     DECLARE_NO_COPY_CLASS(wxIDataObject
) 
 132 // ============================================================================ 
 134 // ============================================================================ 
 136 // ---------------------------------------------------------------------------- 
 138 // ---------------------------------------------------------------------------- 
 140 void wxDataFormat::SetId(const wxString
& format
) 
 142     m_format 
= (wxDataFormat::NativeFormat
)::RegisterClipboardFormat(format
.wx_str()); 
 145         wxLogError(_("Couldn't register clipboard format '%s'."), format
); 
 149 wxString 
wxDataFormat::GetId() const 
 151     static const int max 
= 256; 
 155     wxCHECK_MSG( !IsStandard(), s
, 
 156                  wxT("name of predefined format cannot be retrieved") ); 
 158     int len 
= ::GetClipboardFormatName(m_format
, wxStringBuffer(s
, max
), max
); 
 162         wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
); 
 163         return wxEmptyString
; 
 169 // ---------------------------------------------------------------------------- 
 171 // ---------------------------------------------------------------------------- 
 173 BEGIN_IID_TABLE(wxIEnumFORMATETC
) 
 175     ADD_IID(EnumFORMATETC
) 
 178 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
) 
 180 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat 
*formats
, ULONG nCount
) 
 184     m_formats 
= new CLIPFORMAT
[nCount
]; 
 185     for ( ULONG n 
= 0; n 
< nCount
; n
++ ) { 
 186         m_formats
[n
] = formats
[n
].GetFormatId(); 
 190 STDMETHODIMP 
wxIEnumFORMATETC::Next(ULONG      celt
, 
 194     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Next")); 
 196     ULONG numFetched 
= 0; 
 197     while (m_nCurrent 
< m_nCount 
&& numFetched 
< celt
) { 
 199         format
.cfFormat 
= m_formats
[m_nCurrent
++]; 
 201         format
.dwAspect 
= DVASPECT_CONTENT
; 
 203         format
.tymed    
= TYMED_HGLOBAL
; 
 210         *pceltFetched 
= numFetched
; 
 212     return numFetched 
== celt 
? S_OK 
: S_FALSE
; 
 215 STDMETHODIMP 
wxIEnumFORMATETC::Skip(ULONG celt
) 
 217     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Skip")); 
 220     if ( m_nCurrent 
< m_nCount 
) 
 223     // no, can't skip this many elements 
 229 STDMETHODIMP 
wxIEnumFORMATETC::Reset() 
 231     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Reset")); 
 238 STDMETHODIMP 
wxIEnumFORMATETC::Clone(IEnumFORMATETC 
**ppenum
) 
 240     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Clone")); 
 242     // unfortunately, we can't reuse the code in ctor - types are different 
 243     wxIEnumFORMATETC 
*pNew 
= new wxIEnumFORMATETC(NULL
, 0); 
 244     pNew
->m_nCount 
= m_nCount
; 
 245     pNew
->m_formats 
= new CLIPFORMAT
[m_nCount
]; 
 246     for ( ULONG n 
= 0; n 
< m_nCount
; n
++ ) { 
 247         pNew
->m_formats
[n
] = m_formats
[n
]; 
 255 // ---------------------------------------------------------------------------- 
 257 // ---------------------------------------------------------------------------- 
 259 BEGIN_IID_TABLE(wxIDataObject
) 
 264 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
) 
 266 wxIDataObject::wxIDataObject(wxDataObject 
*pDataObject
) 
 268     m_pDataObject 
= pDataObject
; 
 269     m_mustDelete 
= false; 
 272 wxIDataObject::~wxIDataObject() 
 276         delete m_pDataObject
; 
 280 // get data functions 
 281 STDMETHODIMP 
wxIDataObject::GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
) 
 283     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetData")); 
 285     // is data is in our format? 
 286     HRESULT hr 
= QueryGetData(pformatetcIn
); 
 290     // for the bitmaps and metafiles we use the handles instead of global memory 
 292     wxDataFormat format 
= (wxDataFormat::NativeFormat
)pformatetcIn
->cfFormat
; 
 297             pmedium
->tymed 
= TYMED_GDI
; 
 300         case wxDF_ENHMETAFILE
: 
 301             pmedium
->tymed 
= TYMED_ENHMF
; 
 306             pmedium
->hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, 
 307                                            sizeof(METAFILEPICT
)); 
 308             if ( !pmedium
->hGlobal 
) { 
 309                 wxLogLastError(wxT("GlobalAlloc")); 
 310                 return E_OUTOFMEMORY
; 
 312             pmedium
->tymed 
= TYMED_MFPICT
; 
 317             size_t size 
= m_pDataObject
->GetDataSize(format
); 
 319                 // it probably means that the method is just not implemented 
 320                 wxLogDebug(wxT("Invalid data size - can't be 0")); 
 322                 return DV_E_FORMATETC
; 
 325             // we may need extra space for the buffer size 
 326             size 
+= m_pDataObject
->GetBufferOffset( format 
); 
 328             HGLOBAL hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, size
); 
 329             if ( hGlobal 
== NULL 
) { 
 330                 wxLogLastError(wxT("GlobalAlloc")); 
 331                 return E_OUTOFMEMORY
; 
 335             pmedium
->tymed   
= TYMED_HGLOBAL
; 
 336             pmedium
->hGlobal 
= hGlobal
; 
 339     pmedium
->pUnkForRelease 
= NULL
; 
 342     hr 
= GetDataHere(pformatetcIn
, pmedium
); 
 344         // free resources we allocated 
 345         if ( pmedium
->tymed 
& (TYMED_HGLOBAL 
| TYMED_MFPICT
) ) { 
 346             GlobalFree(pmedium
->hGlobal
); 
 355 STDMETHODIMP 
wxIDataObject::GetDataHere(FORMATETC 
*pformatetc
, 
 358     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetDataHere")); 
 360     // put data in caller provided medium 
 361     switch ( pmedium
->tymed 
) 
 364             if ( !m_pDataObject
->GetDataHere(wxDF_BITMAP
, &pmedium
->hBitmap
) ) 
 369             if ( !m_pDataObject
->GetDataHere(wxDF_ENHMETAFILE
, 
 370                                              &pmedium
->hEnhMetaFile
) ) 
 375             // fall through - we pass METAFILEPICT through HGLOBAL 
 380                 HGLOBAL hGlobal 
= pmedium
->hGlobal
; 
 381                 void *pBuf 
= GlobalLock(hGlobal
); 
 382                 if ( pBuf 
== NULL 
) { 
 383                     wxLogLastError(wxT("GlobalLock")); 
 384                     return E_OUTOFMEMORY
; 
 387                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 389                 // possibly put the size in the beginning of the buffer 
 390                 pBuf 
= m_pDataObject
->SetSizeInBuffer
 
 393                                         ::GlobalSize(hGlobal
), 
 397                 if ( !m_pDataObject
->GetDataHere(format
, pBuf
) ) 
 400                 GlobalUnlock(hGlobal
); 
 412 // set data functions 
 413 STDMETHODIMP 
wxIDataObject::SetData(FORMATETC 
*pformatetc
, 
 417     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::SetData")); 
 419     switch ( pmedium
->tymed 
) 
 422             m_pDataObject
->SetData(wxDF_BITMAP
, 0, &pmedium
->hBitmap
); 
 426             m_pDataObject
->SetData(wxDF_ENHMETAFILE
, 0, &pmedium
->hEnhMetaFile
); 
 430             // fall through - we pass METAFILEPICT through HGLOBAL 
 433                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 435                 // this is quite weird, but for file drag and drop, explorer 
 436                 // calls our SetData() with the formats we do *not* support! 
 438                 // as we can't fix this bug in explorer (it's a bug because it 
 439                 // should only use formats returned by EnumFormatEtc), do the 
 441                 if ( !m_pDataObject
->IsSupported(format
, wxDataObject::Set
) ) { 
 443                     return DV_E_FORMATETC
; 
 447                 const void *pBuf 
= GlobalLock(pmedium
->hGlobal
); 
 448                 if ( pBuf 
== NULL 
) { 
 449                     wxLogLastError(wxT("GlobalLock")); 
 451                     return E_OUTOFMEMORY
; 
 454                 // we've got a problem with SetData() here because the base 
 455                 // class version requires the size parameter which we don't 
 456                 // have anywhere in OLE data transfer - so we need to 
 457                 // synthetise it for known formats and we suppose that all data 
 458                 // in custom formats starts with a DWORD containing the size 
 464                         size 
= strlen((const char *)pBuf
); 
 466 #if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500)) 
 468 #if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \ 
 469     || ( defined(__MWERKS__) && defined(__WXMSW__) ) 
 470                         size 
= std::wcslen((const wchar_t *)pBuf
) * sizeof(wchar_t); 
 472                         size 
= wxWcslen((const wchar_t *)pBuf
) * sizeof(wchar_t); 
 479                         // these formats don't use size at all, anyhow (but 
 480                         // pass data by handle, which is always a single DWORD) 
 486                         // the handler will calculate size itself (it's too 
 487                         // complicated to do it here) 
 492                     case CF_METAFILEPICT
: 
 493                         size 
= sizeof(METAFILEPICT
); 
 497                         pBuf 
= m_pDataObject
-> 
 498                                     GetSizeFromBuffer(pBuf
, &size
, format
); 
 499                         size 
-= m_pDataObject
->GetBufferOffset(format
); 
 502                 bool ok 
= m_pDataObject
->SetData(format
, size
, pBuf
); 
 504                 GlobalUnlock(pmedium
->hGlobal
); 
 517         // we own the medium, so we must release it - but do *not* free any 
 518         // data we pass by handle because we have copied it elsewhere 
 519         switch ( pmedium
->tymed 
) 
 522                 pmedium
->hBitmap 
= 0; 
 526                 pmedium
->hMetaFilePict 
= 0; 
 530                 pmedium
->hEnhMetaFile 
= 0; 
 534         ReleaseStgMedium(pmedium
); 
 540 // information functions 
 541 STDMETHODIMP 
wxIDataObject::QueryGetData(FORMATETC 
*pformatetc
) 
 543     // do we accept data in this format? 
 544     if ( pformatetc 
== NULL 
) { 
 545         wxLogTrace(wxTRACE_OleCalls
, 
 546                    wxT("wxIDataObject::QueryGetData: invalid ptr.")); 
 551     // the only one allowed by current COM implementation 
 552     if ( pformatetc
->lindex 
!= -1 ) { 
 553         wxLogTrace(wxTRACE_OleCalls
, 
 554                    wxT("wxIDataObject::QueryGetData: bad lindex %ld"), 
 560     // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...) 
 561     if ( pformatetc
->dwAspect 
!= DVASPECT_CONTENT 
) { 
 562         wxLogTrace(wxTRACE_OleCalls
, 
 563                    wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"), 
 564                    pformatetc
->dwAspect
); 
 566         return DV_E_DVASPECT
; 
 569     // and now check the type of data requested 
 570     wxDataFormat format 
= pformatetc
->cfFormat
; 
 571     if ( m_pDataObject
->IsSupportedFormat(format
) ) { 
 572         wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok"), 
 573                    wxGetFormatName(format
)); 
 576         wxLogTrace(wxTRACE_OleCalls
, 
 577                    wxT("wxIDataObject::QueryGetData: %s unsupported"), 
 578                    wxGetFormatName(format
)); 
 580         return DV_E_FORMATETC
; 
 583     // we only transfer data by global memory, except for some particular cases 
 584     DWORD tymed 
= pformatetc
->tymed
; 
 585     if ( (format 
== wxDF_BITMAP 
&& !(tymed 
& TYMED_GDI
)) && 
 586          !(tymed 
& TYMED_HGLOBAL
) ) { 
 587         // it's not what we're waiting for 
 588         wxLogTrace(wxTRACE_OleCalls
, 
 589                    wxT("wxIDataObject::QueryGetData: %s != %s"), 
 591                    GetTymedName(format 
== wxDF_BITMAP 
? TYMED_GDI
 
 600 STDMETHODIMP 
wxIDataObject::GetCanonicalFormatEtc(FORMATETC 
*WXUNUSED(pFormatetcIn
), 
 601                                                   FORMATETC 
*pFormatetcOut
) 
 603     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetCanonicalFormatEtc")); 
 605     // TODO we might want something better than this trivial implementation here 
 606     if ( pFormatetcOut 
!= NULL 
) 
 607         pFormatetcOut
->ptd 
= NULL
; 
 609     return DATA_S_SAMEFORMATETC
; 
 612 STDMETHODIMP 
wxIDataObject::EnumFormatEtc(DWORD dwDir
, 
 613                                           IEnumFORMATETC 
**ppenumFormatEtc
) 
 615     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::EnumFormatEtc")); 
 617     wxDataObject::Direction dir 
= dwDir 
== DATADIR_GET 
? wxDataObject::Get
 
 620     ULONG nFormatCount 
= wx_truncate_cast(ULONG
, m_pDataObject
->GetFormatCount(dir
)); 
 622     wxDataFormat 
*formats
; 
 623     formats 
= nFormatCount 
== 1 ? &format 
: new wxDataFormat
[nFormatCount
]; 
 624     m_pDataObject
->GetAllFormats(formats
, dir
); 
 626     wxIEnumFORMATETC 
*pEnum 
= new wxIEnumFORMATETC(formats
, nFormatCount
); 
 628     *ppenumFormatEtc 
= pEnum
; 
 630     if ( formats 
!= &format 
) { 
 637 // ---------------------------------------------------------------------------- 
 638 // advise sink functions (not implemented) 
 639 // ---------------------------------------------------------------------------- 
 641 STDMETHODIMP 
wxIDataObject::DAdvise(FORMATETC   
*WXUNUSED(pformatetc
), 
 642                                     DWORD        
WXUNUSED(advf
), 
 643                                     IAdviseSink 
*WXUNUSED(pAdvSink
), 
 644                                     DWORD       
*WXUNUSED(pdwConnection
)) 
 646   return OLE_E_ADVISENOTSUPPORTED
; 
 649 STDMETHODIMP 
wxIDataObject::DUnadvise(DWORD 
WXUNUSED(dwConnection
)) 
 651   return OLE_E_ADVISENOTSUPPORTED
; 
 654 STDMETHODIMP 
wxIDataObject::EnumDAdvise(IEnumSTATDATA 
**WXUNUSED(ppenumAdvise
)) 
 656   return OLE_E_ADVISENOTSUPPORTED
; 
 659 // ---------------------------------------------------------------------------- 
 661 // ---------------------------------------------------------------------------- 
 663 wxDataObject::wxDataObject() 
 665     m_pIDataObject 
= new wxIDataObject(this); 
 666     m_pIDataObject
->AddRef(); 
 669 wxDataObject::~wxDataObject() 
 671     ReleaseInterface(m_pIDataObject
); 
 674 void wxDataObject::SetAutoDelete() 
 676     ((wxIDataObject 
*)m_pIDataObject
)->SetDeleteFlag(); 
 677     m_pIDataObject
->Release(); 
 679     // so that the dtor doesnt' crash 
 680     m_pIDataObject 
= NULL
; 
 683 size_t wxDataObject::GetBufferOffset(const wxDataFormat
& format 
) 
 685     // if we prepend the size of the data to the buffer itself, account for it 
 686     return NeedsVerbatimData(format
) ? 0 : sizeof(size_t); 
 689 const void* wxDataObject::GetSizeFromBuffer( const void* buffer
, size_t* size
, 
 690                                                const wxDataFormat
& format 
) 
 692     // hack: the third parameter is declared non-const in Wine's headers so 
 693     // cast away the const 
 694     size_t realsz 
= ::HeapSize(::GetProcessHeap(), 0, 
 695                                wx_const_cast(void*, buffer
)); 
 696     if ( realsz 
== (size_t)-1 ) 
 698         // note that HeapSize() does not set last error 
 699         wxLogApiError(wxT("HeapSize"), 0); 
 705     // check if this data has its size prepended (as it was by default for wx 
 706     // programs prior 2.6.3): 
 707     size_t *p 
= (size_t *)buffer
; 
 710         if ( NeedsVerbatimData(format
) ) 
 711             wxLogDebug(wxT("Apparent data format mismatch: size not needed")); 
 713         p
++; // this data has its size prepended; skip first DWORD 
 719 void* wxDataObject::SetSizeInBuffer( void* buffer
, size_t size
, 
 720                                       const wxDataFormat
& format 
) 
 722     size_t* p 
= (size_t *)buffer
; 
 723     if ( !NeedsVerbatimData(format
) ) 
 725         // prepend the size to the data and skip it 
 734 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat format
) 
 736     // case 'xxx' is not a valid value for switch of enum 'wxDataFormat' 
 738         #pragma warning(disable:4063) 
 741     static wxChar s_szBuf
[256]; 
 743         case CF_TEXT
:         return wxT("CF_TEXT"); 
 744         case CF_BITMAP
:       return wxT("CF_BITMAP"); 
 745         case CF_SYLK
:         return wxT("CF_SYLK"); 
 746         case CF_DIF
:          return wxT("CF_DIF"); 
 747         case CF_TIFF
:         return wxT("CF_TIFF"); 
 748         case CF_OEMTEXT
:      return wxT("CF_OEMTEXT"); 
 749         case CF_DIB
:          return wxT("CF_DIB"); 
 750         case CF_PALETTE
:      return wxT("CF_PALETTE"); 
 751         case CF_PENDATA
:      return wxT("CF_PENDATA"); 
 752         case CF_RIFF
:         return wxT("CF_RIFF"); 
 753         case CF_WAVE
:         return wxT("CF_WAVE"); 
 754         case CF_UNICODETEXT
:  return wxT("CF_UNICODETEXT"); 
 756         case CF_METAFILEPICT
: return wxT("CF_METAFILEPICT"); 
 757         case CF_ENHMETAFILE
:  return wxT("CF_ENHMETAFILE"); 
 758         case CF_LOCALE
:       return wxT("CF_LOCALE"); 
 759         case CF_HDROP
:        return wxT("CF_HDROP"); 
 763             if ( !::GetClipboardFormatName(format
, s_szBuf
, WXSIZEOF(s_szBuf
)) ) 
 765                 // it must be a new predefined format we don't know the name of 
 766                 wxSprintf(s_szBuf
, wxT("unknown CF (0x%04x)"), format
.GetFormatId()); 
 773         #pragma warning(default:4063) 
 779 // ---------------------------------------------------------------------------- 
 780 // wxBitmapDataObject supports CF_DIB format 
 781 // ---------------------------------------------------------------------------- 
 783 // TODO: support CF_DIB under Windows CE as well 
 785 size_t wxBitmapDataObject::GetDataSize() const 
 787 #if wxUSE_WXDIB && !defined(__WXWINCE__) 
 788     return wxDIB::ConvertFromBitmap(NULL
, GetHbitmapOf(GetBitmap())); 
 794 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 796 #if wxUSE_WXDIB && !defined(__WXWINCE__) 
 797     BITMAPINFO 
* const pbi 
= (BITMAPINFO 
*)buf
; 
 799     return wxDIB::ConvertFromBitmap(pbi
, GetHbitmapOf(GetBitmap())) != 0; 
 806 bool wxBitmapDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 808 #if wxUSE_WXDIB && !defined(__WXWINCE__) 
 809     const BITMAPINFO 
* const pbmi 
= (const BITMAPINFO 
*)buf
; 
 811     HBITMAP hbmp 
= wxDIB::ConvertToBitmap(pbmi
); 
 813     wxCHECK_MSG( hbmp
, FALSE
, wxT("pasting/dropping invalid bitmap") ); 
 815     const BITMAPINFOHEADER 
* const pbmih 
= &pbmi
->bmiHeader
; 
 816     wxBitmap 
bitmap(pbmih
->biWidth
, pbmih
->biHeight
, pbmih
->biBitCount
); 
 817     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 819     // TODO: create wxPalette if the bitmap has any 
 830 // ---------------------------------------------------------------------------- 
 831 // wxBitmapDataObject2 supports CF_BITMAP format 
 832 // ---------------------------------------------------------------------------- 
 834 // the bitmaps aren't passed by value as other types of data (i.e. by copying 
 835 // the data into a global memory chunk and passing it to the clipboard or 
 836 // another application or whatever), but by handle, so these generic functions 
 837 // don't make much sense to them. 
 839 size_t wxBitmapDataObject2::GetDataSize() const 
 844 bool wxBitmapDataObject2::GetDataHere(void *pBuf
) const 
 846     // we put a bitmap handle into pBuf 
 847     *(WXHBITMAP 
*)pBuf 
= GetBitmap().GetHBITMAP(); 
 852 bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len
), const void *pBuf
) 
 854     HBITMAP hbmp 
= *(HBITMAP 
*)pBuf
; 
 857     if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 859         wxLogLastError(wxT("GetObject(HBITMAP)")); 
 862     wxBitmap 
bitmap(bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
); 
 863     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 865     if ( !bitmap
.Ok() ) { 
 866         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 878 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat
& format
) const 
 880     if ( format
.GetFormatId() == CF_DIB 
) 
 885         // shouldn't be selected into a DC or GetDIBits() would fail 
 886         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 887                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 889         // first get the info 
 891         if ( !GetDIBits(hdc
, (HBITMAP
)m_bitmap
.GetHBITMAP(), 0, 0, 
 892                         NULL
, &bi
, DIB_RGB_COLORS
) ) 
 894             wxLogLastError(wxT("GetDIBits(NULL)")); 
 899         return sizeof(BITMAPINFO
) + bi
.bmiHeader
.biSizeImage
; 
 903         // no data to copy - we don't pass HBITMAP via global memory 
 908 bool wxBitmapDataObject::GetDataHere(const wxDataFormat
& format
, 
 911     wxASSERT_MSG( m_bitmap
.Ok(), wxT("copying invalid bitmap") ); 
 913     HBITMAP hbmp 
= (HBITMAP
)m_bitmap
.GetHBITMAP(); 
 914     if ( format
.GetFormatId() == CF_DIB 
) 
 919         // shouldn't be selected into a DC or GetDIBits() would fail 
 920         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 921                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 923         // first get the info 
 924         BITMAPINFO 
*pbi 
= (BITMAPINFO 
*)pBuf
; 
 925         if ( !GetDIBits(hdc
, hbmp
, 0, 0, NULL
, pbi
, DIB_RGB_COLORS
) ) 
 927             wxLogLastError(wxT("GetDIBits(NULL)")); 
 932         // and now copy the bits 
 933         if ( !GetDIBits(hdc
, hbmp
, 0, pbi
->bmiHeader
.biHeight
, pbi 
+ 1, 
 934                         pbi
, DIB_RGB_COLORS
) ) 
 936             wxLogLastError(wxT("GetDIBits")); 
 943         // we put a bitmap handle into pBuf 
 944         *(HBITMAP 
*)pBuf 
= hbmp
; 
 950 bool wxBitmapDataObject::SetData(const wxDataFormat
& format
, 
 951                                  size_t size
, const void *pBuf
) 
 954     if ( format
.GetFormatId() == CF_DIB 
) 
 956         // here we get BITMAPINFO struct followed by the actual bitmap bits and 
 957         // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
 960         BITMAPINFO 
*pbmi 
= (BITMAPINFO 
*)pBuf
; 
 961         BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
 962         hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
 963                               pbmi 
+ 1, pbmi
, DIB_RGB_COLORS
); 
 966             wxLogLastError(wxT("CreateDIBitmap")); 
 969         m_bitmap
.SetWidth(pbmih
->biWidth
); 
 970         m_bitmap
.SetHeight(pbmih
->biHeight
); 
 974         // it's easy with bitmaps: we pass them by handle 
 975         hbmp 
= *(HBITMAP 
*)pBuf
; 
 978         if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 980             wxLogLastError(wxT("GetObject(HBITMAP)")); 
 983         m_bitmap
.SetWidth(bmp
.bmWidth
); 
 984         m_bitmap
.SetHeight(bmp
.bmHeight
); 
 985         m_bitmap
.SetDepth(bmp
.bmPlanes
); 
 988     m_bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 990     wxASSERT_MSG( m_bitmap
.Ok(), wxT("pasting invalid bitmap") ); 
 997 // ---------------------------------------------------------------------------- 
 999 // ---------------------------------------------------------------------------- 
1001 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), 
1002                                const void *WXUNUSED_IN_WINCE(pData
)) 
1005     m_filenames
.Empty(); 
1007     // the documentation states that the first member of DROPFILES structure is 
1008     // a "DWORD offset of double NUL terminated file list". What they mean by 
1009     // this (I wonder if you see it immediately) is that the list starts at 
1010     // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised 
1011     // to use DragQueryFile to work with this structure, but not told where and 
1012     // how to get HDROP. 
1013     HDROP hdrop 
= (HDROP
)pData
;   // NB: it works, but I'm not sure about it 
1015     // get number of files (magic value -1) 
1016     UINT nFiles 
= ::DragQueryFile(hdrop
, (unsigned)-1, NULL
, 0u); 
1018     wxCHECK_MSG ( nFiles 
!= (UINT
)-1, FALSE
, wxT("wrong HDROP handle") ); 
1020     // for each file get the length, allocate memory and then get the name 
1023     for ( n 
= 0; n 
< nFiles
; n
++ ) { 
1024         // +1 for terminating NUL 
1025         len 
= ::DragQueryFile(hdrop
, n
, NULL
, 0) + 1; 
1027         UINT len2 
= ::DragQueryFile(hdrop
, n
, wxStringBuffer(str
, len
), len
); 
1028         m_filenames
.Add(str
); 
1030         if ( len2 
!= len 
- 1 ) { 
1031             wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\ 
1032  %d characters, %d expected."), len2
, len 
- 1); 
1042 void wxFileDataObject::AddFile(const wxString
& file
) 
1044     // just add file to filenames array 
1045     // all useful data (such as DROPFILES struct) will be 
1046     // created later as necessary 
1047     m_filenames
.Add(file
); 
1050 size_t wxFileDataObject::GetDataSize() const 
1053     // size returned will be the size of the DROPFILES structure, plus the list 
1054     // of filesnames (null byte separated), plus a double null at the end 
1056     // if no filenames in list, size is 0 
1057     if ( m_filenames
.empty() ) 
1060 #if wxUSE_UNICODE_MSLU 
1062     if ( wxGetOsVersion() == wxOS_WINDOWS_9X 
) 
1064         // Win9x always uses ANSI file names and MSLU doesn't help with this 
1065         sizeOfChar 
= sizeof(char); 
1069         sizeOfChar 
= sizeof(wxChar
); 
1071 #else // !wxUSE_UNICODE_MSLU 
1072     static const size_t sizeOfChar 
= sizeof(wxChar
); 
1073 #endif // wxUSE_UNICODE_MSLU/!wxUSE_UNICODE_MSLU 
1075     // inital size of DROPFILES struct + null byte 
1076     size_t sz 
= sizeof(DROPFILES
) + sizeOfChar
; 
1078     const size_t count 
= m_filenames
.size(); 
1079     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1081         // add filename length plus null byte 
1083 #if wxUSE_UNICODE_MSLU 
1084         if ( sizeOfChar 
== sizeof(char) ) 
1085             len 
= strlen(m_filenames
[i
].mb_str(*wxConvFileName
)); 
1087 #endif // wxUSE_UNICODE_MSLU 
1088             len 
= m_filenames
[i
].length(); 
1090         sz 
+= (len 
+ 1) * sizeOfChar
; 
1099 bool wxFileDataObject::GetDataHere(void *WXUNUSED_IN_WINCE(pData
)) const 
1102     // pData points to an externally allocated memory block 
1103     // created using the size returned by GetDataSize() 
1105     // if pData is NULL, or there are no files, return 
1106     if ( !pData 
|| m_filenames
.empty() ) 
1109     // convert data pointer to a DROPFILES struct pointer 
1110     LPDROPFILES pDrop 
= (LPDROPFILES
) pData
; 
1112     // initialize DROPFILES struct 
1113     pDrop
->pFiles 
= sizeof(DROPFILES
); 
1114     pDrop
->fNC 
= FALSE
;                 // not non-client coords 
1115 #if wxUSE_UNICODE_MSLU 
1116     pDrop
->fWide 
= wxGetOsVersion() != wxOS_WINDOWS_9X 
? TRUE 
: FALSE
; 
1118     pDrop
->fWide 
= wxUSE_UNICODE
; 
1121     const size_t sizeOfChar 
= pDrop
->fWide 
? sizeof(wchar_t) : sizeof(char); 
1123     // set start of filenames list (null separated) 
1124     BYTE 
*pbuf 
= (BYTE 
*)(pDrop 
+ 1); 
1126     const size_t count 
= m_filenames
.size(); 
1127     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1129         // copy filename to pbuf and add null terminator 
1131 #if wxUSE_UNICODE_MSLU 
1132         if ( sizeOfChar 
== sizeof(char) ) 
1134             wxCharBuffer 
buf(m_filenames
[i
].mb_str(*wxConvFileName
)); 
1136             memcpy(pbuf
, buf
, len
*sizeOfChar
); 
1139 #endif // wxUSE_UNICODE_MSLU 
1141             len 
= m_filenames
[i
].length(); 
1142             memcpy(pbuf
, m_filenames
[i
].c_str(), len
*sizeOfChar
); 
1145         pbuf 
+= len
*sizeOfChar
; 
1147         memset(pbuf
, 0, sizeOfChar
); 
1151     // add final null terminator 
1152     memset(pbuf
, 0, sizeOfChar
); 
1160 // ---------------------------------------------------------------------------- 
1162 // ---------------------------------------------------------------------------- 
1164 // Work around bug in Wine headers 
1165 #if defined(__WINE__) && defined(CFSTR_SHELLURL) && wxUSE_UNICODE 
1166 #undef CFSTR_SHELLURL 
1167 #define CFSTR_SHELLURL _T("CFSTR_SHELLURL") 
1170 class CFSTR_SHELLURLDataObject 
: public wxCustomDataObject
 
1173     CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL
) {} 
1175     virtual size_t GetBufferOffset( const wxDataFormat
& WXUNUSED(format
) ) 
1180     virtual const void* GetSizeFromBuffer( const void* buffer
, size_t* size
, 
1181                                            const wxDataFormat
& WXUNUSED(format
) ) 
1183         // CFSTR_SHELLURL is _always_ ANSI text 
1184         *size 
= strlen( (const char*)buffer 
); 
1189     virtual void* SetSizeInBuffer( void* buffer
, size_t WXUNUSED(size
), 
1190                                    const wxDataFormat
& WXUNUSED(format
) ) 
1196     virtual bool GetDataHere( void* buffer 
) const 
1198         // CFSTR_SHELLURL is _always_ ANSI! 
1199         wxCharBuffer 
char_buffer( GetDataSize() ); 
1200         wxCustomDataObject::GetDataHere( (void*)char_buffer
.data() ); 
1201         wxString 
unicode_buffer( char_buffer
, wxConvLibc 
); 
1202         memcpy( buffer
, unicode_buffer
.c_str(), 
1203                 ( unicode_buffer
.length() + 1 ) * sizeof(wxChar
) ); 
1207     virtual bool GetDataHere(const wxDataFormat
& WXUNUSED(format
), 
1209         { return GetDataHere(buf
); } 
1212     DECLARE_NO_COPY_CLASS(CFSTR_SHELLURLDataObject
) 
1217 wxURLDataObject::wxURLDataObject(const wxString
& url
) 
1219     // we support CF_TEXT and CFSTR_SHELLURL formats which are basicly the same 
1220     // but it seems that some browsers only provide one of them so we have to 
1222     Add(new wxTextDataObject
); 
1223     Add(new CFSTR_SHELLURLDataObject()); 
1225     // we don't have any data yet 
1226     m_dataObjectLast 
= NULL
; 
1232 bool wxURLDataObject::SetData(const wxDataFormat
& format
, 
1236     m_dataObjectLast 
= GetObject(format
); 
1238     wxCHECK_MSG( m_dataObjectLast
, FALSE
, 
1239                  wxT("unsupported format in wxURLDataObject")); 
1241     return m_dataObjectLast
->SetData(len
, buf
); 
1244 wxString 
wxURLDataObject::GetURL() const 
1247     wxCHECK_MSG( m_dataObjectLast
, url
, _T("no data in wxURLDataObject") ); 
1249     size_t len 
= m_dataObjectLast
->GetDataSize(); 
1251     m_dataObjectLast
->GetDataHere(wxStringBuffer(url
, len
)); 
1256 void wxURLDataObject::SetURL(const wxString
& url
) 
1258     SetData(wxDataFormat(wxUSE_UNICODE 
? wxDF_UNICODETEXT 
: wxDF_TEXT
), 
1259             url
.Length()+1, url
.c_str()); 
1261     // CFSTR_SHELLURL is always supposed to be ANSI... 
1262     wxWX2MBbuf urlA 
= (wxWX2MBbuf
)url
.mbc_str(); 
1263     size_t len 
= strlen(urlA
); 
1264     SetData(wxDataFormat(CFSTR_SHELLURL
), len
+1, (const char*)urlA
); 
1267 // ---------------------------------------------------------------------------- 
1268 // private functions 
1269 // ---------------------------------------------------------------------------- 
1273 static const wxChar 
*GetTymedName(DWORD tymed
) 
1275     static wxChar s_szBuf
[128]; 
1277         case TYMED_HGLOBAL
:   return wxT("TYMED_HGLOBAL"); 
1278         case TYMED_FILE
:      return wxT("TYMED_FILE"); 
1279         case TYMED_ISTREAM
:   return wxT("TYMED_ISTREAM"); 
1280         case TYMED_ISTORAGE
:  return wxT("TYMED_ISTORAGE"); 
1281         case TYMED_GDI
:       return wxT("TYMED_GDI"); 
1282         case TYMED_MFPICT
:    return wxT("TYMED_MFPICT"); 
1283         case TYMED_ENHMF
:     return wxT("TYMED_ENHMF"); 
1285             wxSprintf(s_szBuf
, wxT("type of media format %ld (unknown)"), tymed
); 
1292 #else // not using OLE at all 
1294 // ---------------------------------------------------------------------------- 
1296 // ---------------------------------------------------------------------------- 
1300 wxDataObject::wxDataObject() 
1304 wxDataObject::~wxDataObject() 
1308 void wxDataObject::SetAutoDelete() 
1313 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat 
WXUNUSED(format
)) 
1317 #endif // __WXDEBUG__ 
1319 #endif // wxUSE_DATAOBJ 
1321 #endif // wxUSE_OLE/!wxUSE_OLE