]>
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 licence 
  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__) 
  36 #include "wx/dataobj.h" 
  38 #if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__) 
  40 #include "wx/msw/private.h"         // includes <windows.h> 
  46 // for some compilers, the entire ole2.h must be included, not only oleauto.h 
  47 #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) || defined(__WXWINCE__) 
  54 #include "wx/msw/ole/oleutils.h" 
  56 #include "wx/msw/dib.h" 
  58 #ifndef CFSTR_SHELLURL 
  59 #define CFSTR_SHELLURL _T("UniformResourceLocator") 
  62 // ---------------------------------------------------------------------------- 
  64 // ---------------------------------------------------------------------------- 
  67     static const wxChar 
*GetTymedName(DWORD tymed
); 
  69     #define GetTymedName(tymed) wxEmptyString 
  70 #endif // Debug/!Debug 
  72 // ---------------------------------------------------------------------------- 
  73 // wxIEnumFORMATETC interface implementation 
  74 // ---------------------------------------------------------------------------- 
  76 class wxIEnumFORMATETC 
: public IEnumFORMATETC
 
  79     wxIEnumFORMATETC(const wxDataFormat
* formats
, ULONG nCount
); 
  80     virtual ~wxIEnumFORMATETC() { delete [] m_formats
; } 
  82     DECLARE_IUNKNOWN_METHODS
; 
  85     STDMETHODIMP 
Next(ULONG celt
, FORMATETC 
*rgelt
, ULONG 
*pceltFetched
); 
  86     STDMETHODIMP 
Skip(ULONG celt
); 
  88     STDMETHODIMP 
Clone(IEnumFORMATETC 
**ppenum
); 
  91     CLIPFORMAT 
*m_formats
;  // formats we can provide data in 
  92     ULONG       m_nCount
,   // number of formats we support 
  93                 m_nCurrent
; // current enum position 
  95     DECLARE_NO_COPY_CLASS(wxIEnumFORMATETC
) 
  98 // ---------------------------------------------------------------------------- 
  99 // wxIDataObject implementation of IDataObject interface 
 100 // ---------------------------------------------------------------------------- 
 102 class wxIDataObject 
: public IDataObject
 
 105     wxIDataObject(wxDataObject 
*pDataObject
); 
 106     virtual ~wxIDataObject(); 
 108     // normally, wxDataObject controls our lifetime (i.e. we're deleted when it 
 109     // is), but in some cases, the situation is inversed, that is we delete it 
 110     // when this object is deleted - setting this flag enables such logic 
 111     void SetDeleteFlag() { m_mustDelete 
= TRUE
; } 
 113     DECLARE_IUNKNOWN_METHODS
; 
 116     STDMETHODIMP 
GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
); 
 117     STDMETHODIMP 
GetDataHere(FORMATETC 
*pformatetc
, STGMEDIUM 
*pmedium
); 
 118     STDMETHODIMP 
QueryGetData(FORMATETC 
*pformatetc
); 
 119     STDMETHODIMP 
GetCanonicalFormatEtc(FORMATETC 
*In
, FORMATETC 
*pOut
); 
 120     STDMETHODIMP 
SetData(FORMATETC 
*pfetc
, STGMEDIUM 
*pmedium
, BOOL fRelease
); 
 121     STDMETHODIMP 
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC 
**ppenumFEtc
); 
 122     STDMETHODIMP 
DAdvise(FORMATETC 
*pfetc
, DWORD ad
, IAdviseSink 
*p
, DWORD 
*pdw
); 
 123     STDMETHODIMP 
DUnadvise(DWORD dwConnection
); 
 124     STDMETHODIMP 
EnumDAdvise(IEnumSTATDATA 
**ppenumAdvise
); 
 127     wxDataObject 
*m_pDataObject
;      // pointer to C++ class we belong to 
 131     DECLARE_NO_COPY_CLASS(wxIDataObject
) 
 134 // ============================================================================ 
 136 // ============================================================================ 
 138 // ---------------------------------------------------------------------------- 
 140 // ---------------------------------------------------------------------------- 
 142 void wxDataFormat::SetId(const wxChar 
*format
) 
 144     m_format 
= (wxDataFormat::NativeFormat
)::RegisterClipboardFormat(format
); 
 147         wxLogError(_("Couldn't register clipboard format '%s'."), format
); 
 151 wxString 
wxDataFormat::GetId() const 
 153     static const int max 
= 256; 
 157     wxCHECK_MSG( !IsStandard(), s
, 
 158                  wxT("name of predefined format cannot be retrieved") ); 
 160     int len 
= ::GetClipboardFormatName(m_format
, s
.GetWriteBuf(max
), max
); 
 165         wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
); 
 171 // ---------------------------------------------------------------------------- 
 173 // ---------------------------------------------------------------------------- 
 175 BEGIN_IID_TABLE(wxIEnumFORMATETC
) 
 177     ADD_IID(EnumFORMATETC
) 
 180 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
) 
 182 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat 
*formats
, ULONG nCount
) 
 186     m_formats 
= new CLIPFORMAT
[nCount
]; 
 187     for ( ULONG n 
= 0; n 
< nCount
; n
++ ) { 
 188         m_formats
[n
] = formats
[n
].GetFormatId(); 
 192 STDMETHODIMP 
wxIEnumFORMATETC::Next(ULONG      celt
, 
 196     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Next")); 
 198     ULONG numFetched 
= 0; 
 199     while (m_nCurrent 
< m_nCount 
&& numFetched 
< celt
) { 
 201         format
.cfFormat 
= m_formats
[m_nCurrent
++]; 
 203         format
.dwAspect 
= DVASPECT_CONTENT
; 
 205         format
.tymed    
= TYMED_HGLOBAL
; 
 212         *pceltFetched 
= numFetched
; 
 214     return numFetched 
== celt 
? S_OK 
: S_FALSE
; 
 217 STDMETHODIMP 
wxIEnumFORMATETC::Skip(ULONG celt
) 
 219     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Skip")); 
 222     if ( m_nCurrent 
< m_nCount 
) 
 225     // no, can't skip this many elements 
 231 STDMETHODIMP 
wxIEnumFORMATETC::Reset() 
 233     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Reset")); 
 240 STDMETHODIMP 
wxIEnumFORMATETC::Clone(IEnumFORMATETC 
**ppenum
) 
 242     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Clone")); 
 244     // unfortunately, we can't reuse the code in ctor - types are different 
 245     wxIEnumFORMATETC 
*pNew 
= new wxIEnumFORMATETC(NULL
, 0); 
 246     pNew
->m_nCount 
= m_nCount
; 
 247     pNew
->m_formats 
= new CLIPFORMAT
[m_nCount
]; 
 248     for ( ULONG n 
= 0; n 
< m_nCount
; n
++ ) { 
 249         pNew
->m_formats
[n
] = m_formats
[n
]; 
 257 // ---------------------------------------------------------------------------- 
 259 // ---------------------------------------------------------------------------- 
 261 BEGIN_IID_TABLE(wxIDataObject
) 
 266 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
) 
 268 wxIDataObject::wxIDataObject(wxDataObject 
*pDataObject
) 
 270     m_pDataObject 
= pDataObject
; 
 271     m_mustDelete 
= FALSE
; 
 274 wxIDataObject::~wxIDataObject() 
 278         delete m_pDataObject
; 
 282 // get data functions 
 283 STDMETHODIMP 
wxIDataObject::GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
) 
 285     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetData")); 
 287     // is data is in our format? 
 288     HRESULT hr 
= QueryGetData(pformatetcIn
); 
 292     // for the bitmaps and metafiles we use the handles instead of global memory 
 294     wxDataFormat format 
= (wxDataFormat::NativeFormat
)pformatetcIn
->cfFormat
; 
 299             pmedium
->tymed 
= TYMED_GDI
; 
 302         case wxDF_ENHMETAFILE
: 
 303             pmedium
->tymed 
= TYMED_ENHMF
; 
 308             pmedium
->hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, 
 309                                            sizeof(METAFILEPICT
)); 
 310             if ( !pmedium
->hGlobal 
) { 
 311                 wxLogLastError(wxT("GlobalAlloc")); 
 312                 return E_OUTOFMEMORY
; 
 314             pmedium
->tymed 
= TYMED_MFPICT
; 
 319             size_t size 
= m_pDataObject
->GetDataSize(format
); 
 321                 // it probably means that the method is just not implemented 
 322                 wxLogDebug(wxT("Invalid data size - can't be 0")); 
 324                 return DV_E_FORMATETC
; 
 327             if ( !format
.IsStandard() ) { 
 328                 // for custom formats, put the size with the data - alloc the 
 330                 // MB: not completely sure this is correct, 
 331                 //     even if I can't figure out what's wrong 
 332                 size 
+= m_pDataObject
->GetBufferOffset( format 
); 
 335             HGLOBAL hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, size
); 
 336             if ( hGlobal 
== NULL 
) { 
 337                 wxLogLastError(wxT("GlobalAlloc")); 
 338                 return E_OUTOFMEMORY
; 
 342             pmedium
->tymed   
= TYMED_HGLOBAL
; 
 343             pmedium
->hGlobal 
= hGlobal
; 
 346     pmedium
->pUnkForRelease 
= NULL
; 
 349     hr 
= GetDataHere(pformatetcIn
, pmedium
); 
 351         // free resources we allocated 
 352         if ( pmedium
->tymed 
& (TYMED_HGLOBAL 
| TYMED_MFPICT
) ) { 
 353             GlobalFree(pmedium
->hGlobal
); 
 362 STDMETHODIMP 
wxIDataObject::GetDataHere(FORMATETC 
*pformatetc
, 
 365     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetDataHere")); 
 367     // put data in caller provided medium 
 368     switch ( pmedium
->tymed 
) 
 371             if ( !m_pDataObject
->GetDataHere(wxDF_BITMAP
, &pmedium
->hBitmap
) ) 
 376             if ( !m_pDataObject
->GetDataHere(wxDF_ENHMETAFILE
, 
 377                                              &pmedium
->hEnhMetaFile
) ) 
 382             // fall through - we pass METAFILEPICT through HGLOBAL 
 387                 HGLOBAL hGlobal 
= pmedium
->hGlobal
; 
 388                 void *pBuf 
= GlobalLock(hGlobal
); 
 389                 if ( pBuf 
== NULL 
) { 
 390                     wxLogLastError(wxT("GlobalLock")); 
 391                     return E_OUTOFMEMORY
; 
 394                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 395                 if ( !format
.IsStandard() ) { 
 396                     // for custom formats, put the size with the data 
 397                     pBuf 
= m_pDataObject
->SetSizeInBuffer( pBuf
, GlobalSize(hGlobal
), format 
); 
 400                 if ( !m_pDataObject
->GetDataHere(format
, pBuf
) ) 
 403                 GlobalUnlock(hGlobal
); 
 415 // set data functions 
 416 STDMETHODIMP 
wxIDataObject::SetData(FORMATETC 
*pformatetc
, 
 420     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::SetData")); 
 422     switch ( pmedium
->tymed 
) 
 425             m_pDataObject
->SetData(wxDF_BITMAP
, 0, &pmedium
->hBitmap
); 
 429             m_pDataObject
->SetData(wxDF_ENHMETAFILE
, 0, &pmedium
->hEnhMetaFile
); 
 433             // fall through - we pass METAFILEPICT through HGLOBAL 
 436                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 438                 // this is quite weird, but for file drag and drop, explorer 
 439                 // calls our SetData() with the formats we do *not* support! 
 441                 // as we can't fix this bug in explorer (it's a bug because it 
 442                 // should only use formats returned by EnumFormatEtc), do the 
 444                 if ( !m_pDataObject
->IsSupported(format
, wxDataObject::Set
) ) { 
 446                     return DV_E_FORMATETC
; 
 450                 const void *pBuf 
= GlobalLock(pmedium
->hGlobal
); 
 451                 if ( pBuf 
== NULL 
) { 
 452                     wxLogLastError(wxT("GlobalLock")); 
 454                     return E_OUTOFMEMORY
; 
 457                 // we've got a problem with SetData() here because the base 
 458                 // class version requires the size parameter which we don't 
 459                 // have anywhere in OLE data transfer - so we need to 
 460                 // synthetise it for known formats and we suppose that all data 
 461                 // in custom formats starts with a DWORD containing the size 
 467                         size 
= strlen((const char *)pBuf
); 
 469 #if !defined(__WATCOMC__) && ! (defined(__BORLANDC__) && (__BORLANDC__ < 0x500)) 
 471 #if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \ 
 472     || ( defined(__MWERKS__) && defined(__WXMSW__) ) 
 473                         size 
= std::wcslen((const wchar_t *)pBuf
) * sizeof(wchar_t); 
 475                         size 
= wxWcslen((const wchar_t *)pBuf
) * sizeof(wchar_t); 
 482                         // these formats don't use size at all, anyhow (but 
 483                         // pass data by handle, which is always a single DWORD) 
 489                         // the handler will calculate size itself (it's too 
 490                         // complicated to do it here) 
 495                     case CF_METAFILEPICT
: 
 496                         size 
= sizeof(METAFILEPICT
); 
 501                             // we suppose that the size precedes the data 
 502                             pBuf 
= m_pDataObject
->GetSizeFromBuffer( pBuf
, &size
, format 
); 
 503                             if (! format
.IsStandard() ) { 
 504                                 // see GetData for coresponding increment 
 505                                 size 
-= m_pDataObject
->GetBufferOffset( format  
); 
 510                 bool ok 
= m_pDataObject
->SetData(format
, size
, pBuf
); 
 512                 GlobalUnlock(pmedium
->hGlobal
); 
 525         // we own the medium, so we must release it - but do *not* free any 
 526         // data we pass by handle because we have copied it elsewhere 
 527         switch ( pmedium
->tymed 
) 
 530                 pmedium
->hBitmap 
= 0; 
 534                 pmedium
->hMetaFilePict 
= 0; 
 538                 pmedium
->hEnhMetaFile 
= 0; 
 542         ReleaseStgMedium(pmedium
); 
 548 // information functions 
 549 STDMETHODIMP 
wxIDataObject::QueryGetData(FORMATETC 
*pformatetc
) 
 551     // do we accept data in this format? 
 552     if ( pformatetc 
== NULL 
) { 
 553         wxLogTrace(wxTRACE_OleCalls
, 
 554                    wxT("wxIDataObject::QueryGetData: invalid ptr.")); 
 559     // the only one allowed by current COM implementation 
 560     if ( pformatetc
->lindex 
!= -1 ) { 
 561         wxLogTrace(wxTRACE_OleCalls
, 
 562                    wxT("wxIDataObject::QueryGetData: bad lindex %ld"), 
 568     // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...) 
 569     if ( pformatetc
->dwAspect 
!= DVASPECT_CONTENT 
) { 
 570         wxLogTrace(wxTRACE_OleCalls
, 
 571                    wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"), 
 572                    pformatetc
->dwAspect
); 
 574         return DV_E_DVASPECT
; 
 577     // and now check the type of data requested 
 578     wxDataFormat format 
= pformatetc
->cfFormat
; 
 579     if ( m_pDataObject
->IsSupportedFormat(format
) ) { 
 580         wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok"), 
 581                    wxGetFormatName(format
)); 
 584         wxLogTrace(wxTRACE_OleCalls
, 
 585                    wxT("wxIDataObject::QueryGetData: %s unsupported"), 
 586                    wxGetFormatName(format
)); 
 588         return DV_E_FORMATETC
; 
 591     // we only transfer data by global memory, except for some particular cases 
 592     DWORD tymed 
= pformatetc
->tymed
; 
 593     if ( (format 
== wxDF_BITMAP 
&& !(tymed 
& TYMED_GDI
)) && 
 594          !(tymed 
& TYMED_HGLOBAL
) ) { 
 595         // it's not what we're waiting for 
 596         wxLogTrace(wxTRACE_OleCalls
, 
 597                    wxT("wxIDataObject::QueryGetData: %s != %s"), 
 599                    GetTymedName(format 
== wxDF_BITMAP 
? TYMED_GDI
 
 608 STDMETHODIMP 
wxIDataObject::GetCanonicalFormatEtc(FORMATETC 
*WXUNUSED(pFormatetcIn
), 
 609                                                   FORMATETC 
*pFormatetcOut
) 
 611     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetCanonicalFormatEtc")); 
 613     // TODO we might want something better than this trivial implementation here 
 614     if ( pFormatetcOut 
!= NULL 
) 
 615         pFormatetcOut
->ptd 
= NULL
; 
 617     return DATA_S_SAMEFORMATETC
; 
 620 STDMETHODIMP 
wxIDataObject::EnumFormatEtc(DWORD dwDir
, 
 621                                           IEnumFORMATETC 
**ppenumFormatEtc
) 
 623     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::EnumFormatEtc")); 
 625     wxDataObject::Direction dir 
= dwDir 
== DATADIR_GET 
? wxDataObject::Get
 
 628     size_t nFormatCount 
= m_pDataObject
->GetFormatCount(dir
); 
 630     wxDataFormat 
*formats
; 
 631     formats 
= nFormatCount 
== 1 ? &format 
: new wxDataFormat
[nFormatCount
]; 
 632     m_pDataObject
->GetAllFormats(formats
, dir
); 
 634     wxIEnumFORMATETC 
*pEnum 
= new wxIEnumFORMATETC(formats
, nFormatCount
); 
 636     *ppenumFormatEtc 
= pEnum
; 
 638     if ( formats 
!= &format 
) { 
 645 // ---------------------------------------------------------------------------- 
 646 // advise sink functions (not implemented) 
 647 // ---------------------------------------------------------------------------- 
 649 STDMETHODIMP 
wxIDataObject::DAdvise(FORMATETC   
*WXUNUSED(pformatetc
), 
 650                                     DWORD        
WXUNUSED(advf
), 
 651                                     IAdviseSink 
*WXUNUSED(pAdvSink
), 
 652                                     DWORD       
*WXUNUSED(pdwConnection
)) 
 654   return OLE_E_ADVISENOTSUPPORTED
; 
 657 STDMETHODIMP 
wxIDataObject::DUnadvise(DWORD 
WXUNUSED(dwConnection
)) 
 659   return OLE_E_ADVISENOTSUPPORTED
; 
 662 STDMETHODIMP 
wxIDataObject::EnumDAdvise(IEnumSTATDATA 
**WXUNUSED(ppenumAdvise
)) 
 664   return OLE_E_ADVISENOTSUPPORTED
; 
 667 // ---------------------------------------------------------------------------- 
 669 // ---------------------------------------------------------------------------- 
 671 wxDataObject::wxDataObject() 
 673     m_pIDataObject 
= new wxIDataObject(this); 
 674     m_pIDataObject
->AddRef(); 
 677 wxDataObject::~wxDataObject() 
 679     ReleaseInterface(m_pIDataObject
); 
 682 void wxDataObject::SetAutoDelete() 
 684     ((wxIDataObject 
*)m_pIDataObject
)->SetDeleteFlag(); 
 685     m_pIDataObject
->Release(); 
 687     // so that the dtor doesnt' crash 
 688     m_pIDataObject 
= NULL
; 
 691 size_t wxDataObject::GetBufferOffset( const wxDataFormat
& WXUNUSED(format
) ) 
 693     return sizeof(size_t); 
 696 const void* wxDataObject::GetSizeFromBuffer( const void* buffer
, size_t* size
, 
 697                                              const wxDataFormat
& WXUNUSED(format
) ) 
 699     size_t* p 
= (size_t*)buffer
; 
 705 void* wxDataObject::SetSizeInBuffer( void* buffer
, size_t size
, 
 706                                        const wxDataFormat
& WXUNUSED(format
) ) 
 708     size_t* p 
= (size_t*)buffer
; 
 716 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat format
) 
 718     // case 'xxx' is not a valid value for switch of enum 'wxDataFormat' 
 720         #pragma warning(disable:4063) 
 723     static wxChar s_szBuf
[256]; 
 725         case CF_TEXT
:         return wxT("CF_TEXT"); 
 726         case CF_BITMAP
:       return wxT("CF_BITMAP"); 
 727         case CF_METAFILEPICT
: return wxT("CF_METAFILEPICT"); 
 728         case CF_SYLK
:         return wxT("CF_SYLK"); 
 729         case CF_DIF
:          return wxT("CF_DIF"); 
 730         case CF_TIFF
:         return wxT("CF_TIFF"); 
 731         case CF_OEMTEXT
:      return wxT("CF_OEMTEXT"); 
 732         case CF_DIB
:          return wxT("CF_DIB"); 
 733         case CF_PALETTE
:      return wxT("CF_PALETTE"); 
 734         case CF_PENDATA
:      return wxT("CF_PENDATA"); 
 735         case CF_RIFF
:         return wxT("CF_RIFF"); 
 736         case CF_WAVE
:         return wxT("CF_WAVE"); 
 737         case CF_UNICODETEXT
:  return wxT("CF_UNICODETEXT"); 
 738         case CF_ENHMETAFILE
:  return wxT("CF_ENHMETAFILE"); 
 739         case CF_HDROP
:        return wxT("CF_HDROP"); 
 740         case CF_LOCALE
:       return wxT("CF_LOCALE"); 
 743             if ( !::GetClipboardFormatName(format
, s_szBuf
, WXSIZEOF(s_szBuf
)) ) 
 745                 // it must be a new predefined format we don't know the name of 
 746                 wxSprintf(s_szBuf
, wxT("unknown CF (0x%04x)"), format
.GetFormatId()); 
 753         #pragma warning(default:4063) 
 759 // ---------------------------------------------------------------------------- 
 760 // wxBitmapDataObject supports CF_DIB format 
 761 // ---------------------------------------------------------------------------- 
 763 size_t wxBitmapDataObject::GetDataSize() const 
 766     return wxDIB::ConvertFromBitmap(NULL
, GetHbitmapOf(GetBitmap())); 
 772 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 775     BITMAPINFO 
* const pbi 
= (BITMAPINFO 
*)buf
; 
 777     return wxDIB::ConvertFromBitmap(pbi
, GetHbitmapOf(GetBitmap())) != 0; 
 783 bool wxBitmapDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 786     const BITMAPINFO 
* const pbmi 
= (const BITMAPINFO 
*)buf
; 
 788     HBITMAP hbmp 
= wxDIB::ConvertToBitmap(pbmi
); 
 790     wxCHECK_MSG( hbmp
, FALSE
, wxT("pasting/dropping invalid bitmap") ); 
 792     const BITMAPINFOHEADER 
* const pbmih 
= &pbmi
->bmiHeader
; 
 793     wxBitmap 
bitmap(pbmih
->biWidth
, pbmih
->biHeight
, pbmih
->biBitCount
); 
 794     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 796     // TODO: create wxPalette if the bitmap has any 
 806 // ---------------------------------------------------------------------------- 
 807 // wxBitmapDataObject2 supports CF_BITMAP format 
 808 // ---------------------------------------------------------------------------- 
 810 // the bitmaps aren't passed by value as other types of data (i.e. by copying 
 811 // the data into a global memory chunk and passing it to the clipboard or 
 812 // another application or whatever), but by handle, so these generic functions 
 813 // don't make much sense to them. 
 815 size_t wxBitmapDataObject2::GetDataSize() const 
 820 bool wxBitmapDataObject2::GetDataHere(void *pBuf
) const 
 822     // we put a bitmap handle into pBuf 
 823     *(WXHBITMAP 
*)pBuf 
= GetBitmap().GetHBITMAP(); 
 828 bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len
), const void *pBuf
) 
 830     HBITMAP hbmp 
= *(HBITMAP 
*)pBuf
; 
 833     if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 835         wxLogLastError(wxT("GetObject(HBITMAP)")); 
 838     wxBitmap 
bitmap(bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
); 
 839     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 841     if ( !bitmap
.Ok() ) { 
 842         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 854 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat
& format
) const 
 856     if ( format
.GetFormatId() == CF_DIB 
) 
 861         // shouldn't be selected into a DC or GetDIBits() would fail 
 862         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 863                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 865         // first get the info 
 867         if ( !GetDIBits(hdc
, (HBITMAP
)m_bitmap
.GetHBITMAP(), 0, 0, 
 868                         NULL
, &bi
, DIB_RGB_COLORS
) ) 
 870             wxLogLastError(wxT("GetDIBits(NULL)")); 
 875         return sizeof(BITMAPINFO
) + bi
.bmiHeader
.biSizeImage
; 
 879         // no data to copy - we don't pass HBITMAP via global memory 
 884 bool wxBitmapDataObject::GetDataHere(const wxDataFormat
& format
, 
 887     wxASSERT_MSG( m_bitmap
.Ok(), wxT("copying invalid bitmap") ); 
 889     HBITMAP hbmp 
= (HBITMAP
)m_bitmap
.GetHBITMAP(); 
 890     if ( format
.GetFormatId() == CF_DIB 
) 
 895         // shouldn't be selected into a DC or GetDIBits() would fail 
 896         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 897                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 899         // first get the info 
 900         BITMAPINFO 
*pbi 
= (BITMAPINFO 
*)pBuf
; 
 901         if ( !GetDIBits(hdc
, hbmp
, 0, 0, NULL
, pbi
, DIB_RGB_COLORS
) ) 
 903             wxLogLastError(wxT("GetDIBits(NULL)")); 
 908         // and now copy the bits 
 909         if ( !GetDIBits(hdc
, hbmp
, 0, pbi
->bmiHeader
.biHeight
, pbi 
+ 1, 
 910                         pbi
, DIB_RGB_COLORS
) ) 
 912             wxLogLastError(wxT("GetDIBits")); 
 919         // we put a bitmap handle into pBuf 
 920         *(HBITMAP 
*)pBuf 
= hbmp
; 
 926 bool wxBitmapDataObject::SetData(const wxDataFormat
& format
, 
 927                                  size_t size
, const void *pBuf
) 
 930     if ( format
.GetFormatId() == CF_DIB 
) 
 932         // here we get BITMAPINFO struct followed by the actual bitmap bits and 
 933         // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
 936         BITMAPINFO 
*pbmi 
= (BITMAPINFO 
*)pBuf
; 
 937         BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
 938         hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
 939                               pbmi 
+ 1, pbmi
, DIB_RGB_COLORS
); 
 942             wxLogLastError(wxT("CreateDIBitmap")); 
 945         m_bitmap
.SetWidth(pbmih
->biWidth
); 
 946         m_bitmap
.SetHeight(pbmih
->biHeight
); 
 950         // it's easy with bitmaps: we pass them by handle 
 951         hbmp 
= *(HBITMAP 
*)pBuf
; 
 954         if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 956             wxLogLastError(wxT("GetObject(HBITMAP)")); 
 959         m_bitmap
.SetWidth(bmp
.bmWidth
); 
 960         m_bitmap
.SetHeight(bmp
.bmHeight
); 
 961         m_bitmap
.SetDepth(bmp
.bmPlanes
); 
 964     m_bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 966     wxASSERT_MSG( m_bitmap
.Ok(), wxT("pasting invalid bitmap") ); 
 973 // ---------------------------------------------------------------------------- 
 975 // ---------------------------------------------------------------------------- 
 977 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *pData
) 
 982     // the documentation states that the first member of DROPFILES structure is 
 983     // a "DWORD offset of double NUL terminated file list". What they mean by 
 984     // this (I wonder if you see it immediately) is that the list starts at 
 985     // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised 
 986     // to use DragQueryFile to work with this structure, but not told where and 
 988     HDROP hdrop 
= (HDROP
)pData
;   // NB: it works, but I'm not sure about it 
 990     // get number of files (magic value -1) 
 991     UINT nFiles 
= ::DragQueryFile(hdrop
, (unsigned)-1, NULL
, 0u); 
 993     wxCHECK_MSG ( nFiles 
!= (UINT
)-1, FALSE
, wxT("wrong HDROP handle") ); 
 995     // for each file get the length, allocate memory and then get the name 
 998     for ( n 
= 0; n 
< nFiles
; n
++ ) { 
 999         // +1 for terminating NUL 
1000         len 
= ::DragQueryFile(hdrop
, n
, NULL
, 0) + 1; 
1002         UINT len2 
= ::DragQueryFile(hdrop
, n
, str
.GetWriteBuf(len
), len
); 
1003         str
.UngetWriteBuf(); 
1004         m_filenames
.Add(str
); 
1006         if ( len2 
!= len 
- 1 ) { 
1007             wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\ 
1008  %d characters, %d expected."), len2
, len 
- 1); 
1018 void wxFileDataObject::AddFile(const wxString
& file
) 
1020     // just add file to filenames array 
1021     // all useful data (such as DROPFILES struct) will be 
1022     // created later as necessary 
1023     m_filenames
.Add(file
); 
1026 size_t wxFileDataObject::GetDataSize() const 
1029     // size returned will be the size of the DROPFILES structure, 
1030     // plus the list of filesnames (null byte separated), plus 
1031     // a double null at the end 
1033     // if no filenames in list, size is 0 
1034     if ( m_filenames
.GetCount() == 0 ) 
1037     // inital size of DROPFILES struct + null byte 
1038     size_t sz 
= sizeof(DROPFILES
) + 1; 
1040     size_t count 
= m_filenames
.GetCount(); 
1041     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1043         // add filename length plus null byte 
1044         sz 
+= m_filenames
[i
].Len() + 1; 
1053 bool wxFileDataObject::GetDataHere(void *pData
) const 
1056     // pData points to an externally allocated memory block 
1057     // created using the size returned by GetDataSize() 
1059     // if pData is NULL, or there are no files, return 
1060     if ( !pData 
|| m_filenames
.GetCount() == 0 ) 
1063     // convert data pointer to a DROPFILES struct pointer 
1064     LPDROPFILES pDrop 
= (LPDROPFILES
) pData
; 
1066     // initialize DROPFILES struct 
1067     pDrop
->pFiles 
= sizeof(DROPFILES
); 
1068     pDrop
->fNC 
= FALSE
;                 // not non-client coords 
1070     pDrop
->fWide 
= TRUE
; 
1072     pDrop
->fWide 
= FALSE
; 
1073 #endif // Unicode/Ansi 
1075     // set start of filenames list (null separated) 
1076     wxChar 
*pbuf 
= (wxChar
*) ((BYTE 
*)pDrop 
+ sizeof(DROPFILES
)); 
1078     size_t count 
= m_filenames
.GetCount(); 
1079     for (size_t i 
= 0; i 
< count
; i
++ ) 
1081         // copy filename to pbuf and add null terminator 
1082         size_t len 
= m_filenames
[i
].Len(); 
1083         memcpy(pbuf
, m_filenames
[i
], len
); 
1085         *pbuf
++ = wxT('\0'); 
1088     // add final null terminator 
1097 // ---------------------------------------------------------------------------- 
1099 // ---------------------------------------------------------------------------- 
1101 class CFSTR_SHELLURLDataObject 
: public wxCustomDataObject
 
1104     CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL
) {} 
1106     virtual size_t GetBufferOffset( const wxDataFormat
& WXUNUSED(format
) ) 
1111     virtual const void* GetSizeFromBuffer( const void* buffer
, size_t* size
, 
1112                                            const wxDataFormat
& WXUNUSED(format
) ) 
1114         // CFSTR_SHELLURL is _always_ ANSI text 
1115         *size 
= strlen( (const char*)buffer 
); 
1120     virtual void* SetSizeInBuffer( void* buffer
, size_t WXUNUSED(size
), 
1121                                    const wxDataFormat
& WXUNUSED(format
) ) 
1127     virtual bool GetDataHere( void* buffer 
) const 
1129         // CFSTR_SHELLURL is _always_ ANSI! 
1130         wxCharBuffer 
char_buffer( GetDataSize() ); 
1131         wxCustomDataObject::GetDataHere( (void*)char_buffer
.data() ); 
1132         wxString 
unicode_buffer( char_buffer
, wxConvLibc 
); 
1133         memcpy( buffer
, unicode_buffer
.c_str(), 
1134                 ( unicode_buffer
.length() + 1 ) * sizeof(wxChar
) ); 
1143 wxURLDataObject::wxURLDataObject() 
1145     // we support CF_TEXT and CFSTR_SHELLURL formats which are basicly the same 
1146     // but it seems that some browsers only provide one of them so we have to 
1148     Add(new wxTextDataObject
); 
1149     Add(new CFSTR_SHELLURLDataObject()); 
1151     // we don't have any data yet 
1152     m_dataObjectLast 
= NULL
; 
1155 bool wxURLDataObject::SetData(const wxDataFormat
& format
, 
1159     m_dataObjectLast 
= GetObject(format
); 
1161     wxCHECK_MSG( m_dataObjectLast
, FALSE
, 
1162                  wxT("unsupported format in wxURLDataObject")); 
1164     return m_dataObjectLast
->SetData(len
, buf
); 
1167 wxString 
wxURLDataObject::GetURL() const 
1170     wxCHECK_MSG( m_dataObjectLast
, url
, _T("no data in wxURLDataObject") ); 
1172     size_t len 
= m_dataObjectLast
->GetDataSize(); 
1174     m_dataObjectLast
->GetDataHere(url
.GetWriteBuf(len
)); 
1175     url
.UngetWriteBuf(); 
1180 void wxURLDataObject::SetURL(const wxString
& url
) 
1182     SetData(wxDataFormat(wxUSE_UNICODE 
? wxDF_UNICODETEXT 
: wxDF_TEXT
), 
1183             url
.Length()+1, url
.c_str()); 
1185     // CFSTR_SHELLURL is always supposed to be ANSI... 
1186     wxWX2MBbuf urlA 
= (wxWX2MBbuf
)url
.mbc_str(); 
1187     size_t len 
= strlen(urlA
); 
1188     SetData(wxDataFormat(CFSTR_SHELLURL
), len
+1, (const char*)urlA
); 
1191 // ---------------------------------------------------------------------------- 
1192 // private functions 
1193 // ---------------------------------------------------------------------------- 
1197 static const wxChar 
*GetTymedName(DWORD tymed
) 
1199     static wxChar s_szBuf
[128]; 
1201         case TYMED_HGLOBAL
:   return wxT("TYMED_HGLOBAL"); 
1202         case TYMED_FILE
:      return wxT("TYMED_FILE"); 
1203         case TYMED_ISTREAM
:   return wxT("TYMED_ISTREAM"); 
1204         case TYMED_ISTORAGE
:  return wxT("TYMED_ISTORAGE"); 
1205         case TYMED_GDI
:       return wxT("TYMED_GDI"); 
1206         case TYMED_MFPICT
:    return wxT("TYMED_MFPICT"); 
1207         case TYMED_ENHMF
:     return wxT("TYMED_ENHMF"); 
1209             wxSprintf(s_szBuf
, wxT("type of media format %ld (unknown)"), tymed
); 
1216 #else // not using OLE at all 
1217 // ---------------------------------------------------------------------------- 
1219 // ---------------------------------------------------------------------------- 
1221 wxDataObject::wxDataObject() 
1225 wxDataObject::~wxDataObject() 
1229 void wxDataObject::SetAutoDelete() 
1234 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat format
)