]>
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 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  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
, wxStringBuffer(s
, max
), max
); 
 164         wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
); 
 170 // ---------------------------------------------------------------------------- 
 172 // ---------------------------------------------------------------------------- 
 174 BEGIN_IID_TABLE(wxIEnumFORMATETC
) 
 176     ADD_IID(EnumFORMATETC
) 
 179 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
) 
 181 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat 
*formats
, ULONG nCount
) 
 185     m_formats 
= new CLIPFORMAT
[nCount
]; 
 186     for ( ULONG n 
= 0; n 
< nCount
; n
++ ) { 
 187         m_formats
[n
] = formats
[n
].GetFormatId(); 
 191 STDMETHODIMP 
wxIEnumFORMATETC::Next(ULONG      celt
, 
 195     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Next")); 
 197     ULONG numFetched 
= 0; 
 198     while (m_nCurrent 
< m_nCount 
&& numFetched 
< celt
) { 
 200         format
.cfFormat 
= m_formats
[m_nCurrent
++]; 
 202         format
.dwAspect 
= DVASPECT_CONTENT
; 
 204         format
.tymed    
= TYMED_HGLOBAL
; 
 211         *pceltFetched 
= numFetched
; 
 213     return numFetched 
== celt 
? S_OK 
: S_FALSE
; 
 216 STDMETHODIMP 
wxIEnumFORMATETC::Skip(ULONG celt
) 
 218     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Skip")); 
 221     if ( m_nCurrent 
< m_nCount 
) 
 224     // no, can't skip this many elements 
 230 STDMETHODIMP 
wxIEnumFORMATETC::Reset() 
 232     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Reset")); 
 239 STDMETHODIMP 
wxIEnumFORMATETC::Clone(IEnumFORMATETC 
**ppenum
) 
 241     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Clone")); 
 243     // unfortunately, we can't reuse the code in ctor - types are different 
 244     wxIEnumFORMATETC 
*pNew 
= new wxIEnumFORMATETC(NULL
, 0); 
 245     pNew
->m_nCount 
= m_nCount
; 
 246     pNew
->m_formats 
= new CLIPFORMAT
[m_nCount
]; 
 247     for ( ULONG n 
= 0; n 
< m_nCount
; n
++ ) { 
 248         pNew
->m_formats
[n
] = m_formats
[n
]; 
 256 // ---------------------------------------------------------------------------- 
 258 // ---------------------------------------------------------------------------- 
 260 BEGIN_IID_TABLE(wxIDataObject
) 
 265 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
) 
 267 wxIDataObject::wxIDataObject(wxDataObject 
*pDataObject
) 
 269     m_pDataObject 
= pDataObject
; 
 270     m_mustDelete 
= false; 
 273 wxIDataObject::~wxIDataObject() 
 277         delete m_pDataObject
; 
 281 // get data functions 
 282 STDMETHODIMP 
wxIDataObject::GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
) 
 284     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetData")); 
 286     // is data is in our format? 
 287     HRESULT hr 
= QueryGetData(pformatetcIn
); 
 291     // for the bitmaps and metafiles we use the handles instead of global memory 
 293     wxDataFormat format 
= (wxDataFormat::NativeFormat
)pformatetcIn
->cfFormat
; 
 298             pmedium
->tymed 
= TYMED_GDI
; 
 301         case wxDF_ENHMETAFILE
: 
 302             pmedium
->tymed 
= TYMED_ENHMF
; 
 307             pmedium
->hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, 
 308                                            sizeof(METAFILEPICT
)); 
 309             if ( !pmedium
->hGlobal 
) { 
 310                 wxLogLastError(wxT("GlobalAlloc")); 
 311                 return E_OUTOFMEMORY
; 
 313             pmedium
->tymed 
= TYMED_MFPICT
; 
 318             size_t size 
= m_pDataObject
->GetDataSize(format
); 
 320                 // it probably means that the method is just not implemented 
 321                 wxLogDebug(wxT("Invalid data size - can't be 0")); 
 323                 return DV_E_FORMATETC
; 
 326             if ( !format
.IsStandard() ) { 
 327                 // for custom formats, put the size with the data - alloc the 
 329                 // MB: not completely sure this is correct, 
 330                 //     even if I can't figure out what's wrong 
 331                 size 
+= m_pDataObject
->GetBufferOffset( format 
); 
 334             HGLOBAL hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, size
); 
 335             if ( hGlobal 
== NULL 
) { 
 336                 wxLogLastError(wxT("GlobalAlloc")); 
 337                 return E_OUTOFMEMORY
; 
 341             pmedium
->tymed   
= TYMED_HGLOBAL
; 
 342             pmedium
->hGlobal 
= hGlobal
; 
 345     pmedium
->pUnkForRelease 
= NULL
; 
 348     hr 
= GetDataHere(pformatetcIn
, pmedium
); 
 350         // free resources we allocated 
 351         if ( pmedium
->tymed 
& (TYMED_HGLOBAL 
| TYMED_MFPICT
) ) { 
 352             GlobalFree(pmedium
->hGlobal
); 
 361 STDMETHODIMP 
wxIDataObject::GetDataHere(FORMATETC 
*pformatetc
, 
 364     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetDataHere")); 
 366     // put data in caller provided medium 
 367     switch ( pmedium
->tymed 
) 
 370             if ( !m_pDataObject
->GetDataHere(wxDF_BITMAP
, &pmedium
->hBitmap
) ) 
 375             if ( !m_pDataObject
->GetDataHere(wxDF_ENHMETAFILE
, 
 376                                              &pmedium
->hEnhMetaFile
) ) 
 381             // fall through - we pass METAFILEPICT through HGLOBAL 
 386                 HGLOBAL hGlobal 
= pmedium
->hGlobal
; 
 387                 void *pBuf 
= GlobalLock(hGlobal
); 
 388                 if ( pBuf 
== NULL 
) { 
 389                     wxLogLastError(wxT("GlobalLock")); 
 390                     return E_OUTOFMEMORY
; 
 393                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 394                 if ( !format
.IsStandard() ) { 
 395                     // for custom formats, put the size with the data 
 396                     pBuf 
= m_pDataObject
->SetSizeInBuffer( pBuf
, GlobalSize(hGlobal
), format 
); 
 399                 if ( !m_pDataObject
->GetDataHere(format
, pBuf
) ) 
 402                 GlobalUnlock(hGlobal
); 
 414 // set data functions 
 415 STDMETHODIMP 
wxIDataObject::SetData(FORMATETC 
*pformatetc
, 
 419     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::SetData")); 
 421     switch ( pmedium
->tymed 
) 
 424             m_pDataObject
->SetData(wxDF_BITMAP
, 0, &pmedium
->hBitmap
); 
 428             m_pDataObject
->SetData(wxDF_ENHMETAFILE
, 0, &pmedium
->hEnhMetaFile
); 
 432             // fall through - we pass METAFILEPICT through HGLOBAL 
 435                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 437                 // this is quite weird, but for file drag and drop, explorer 
 438                 // calls our SetData() with the formats we do *not* support! 
 440                 // as we can't fix this bug in explorer (it's a bug because it 
 441                 // should only use formats returned by EnumFormatEtc), do the 
 443                 if ( !m_pDataObject
->IsSupported(format
, wxDataObject::Set
) ) { 
 445                     return DV_E_FORMATETC
; 
 449                 const void *pBuf 
= GlobalLock(pmedium
->hGlobal
); 
 450                 if ( pBuf 
== NULL 
) { 
 451                     wxLogLastError(wxT("GlobalLock")); 
 453                     return E_OUTOFMEMORY
; 
 456                 // we've got a problem with SetData() here because the base 
 457                 // class version requires the size parameter which we don't 
 458                 // have anywhere in OLE data transfer - so we need to 
 459                 // synthetise it for known formats and we suppose that all data 
 460                 // in custom formats starts with a DWORD containing the size 
 466                         size 
= strlen((const char *)pBuf
); 
 468 #if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500)) 
 470 #if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \ 
 471     || ( defined(__MWERKS__) && defined(__WXMSW__) ) 
 472                         size 
= std::wcslen((const wchar_t *)pBuf
) * sizeof(wchar_t); 
 474                         size 
= wxWcslen((const wchar_t *)pBuf
) * sizeof(wchar_t); 
 481                         // these formats don't use size at all, anyhow (but 
 482                         // pass data by handle, which is always a single DWORD) 
 488                         // the handler will calculate size itself (it's too 
 489                         // complicated to do it here) 
 494                     case CF_METAFILEPICT
: 
 495                         size 
= sizeof(METAFILEPICT
); 
 500                             // we suppose that the size precedes the data 
 501                             pBuf 
= m_pDataObject
->GetSizeFromBuffer( pBuf
, &size
, format 
); 
 502                             if (! format
.IsStandard() ) { 
 503                                 // see GetData for coresponding increment 
 504                                 size 
-= m_pDataObject
->GetBufferOffset( format  
); 
 509                 bool ok 
= m_pDataObject
->SetData(format
, size
, pBuf
); 
 511                 GlobalUnlock(pmedium
->hGlobal
); 
 524         // we own the medium, so we must release it - but do *not* free any 
 525         // data we pass by handle because we have copied it elsewhere 
 526         switch ( pmedium
->tymed 
) 
 529                 pmedium
->hBitmap 
= 0; 
 533                 pmedium
->hMetaFilePict 
= 0; 
 537                 pmedium
->hEnhMetaFile 
= 0; 
 541         ReleaseStgMedium(pmedium
); 
 547 // information functions 
 548 STDMETHODIMP 
wxIDataObject::QueryGetData(FORMATETC 
*pformatetc
) 
 550     // do we accept data in this format? 
 551     if ( pformatetc 
== NULL 
) { 
 552         wxLogTrace(wxTRACE_OleCalls
, 
 553                    wxT("wxIDataObject::QueryGetData: invalid ptr.")); 
 558     // the only one allowed by current COM implementation 
 559     if ( pformatetc
->lindex 
!= -1 ) { 
 560         wxLogTrace(wxTRACE_OleCalls
, 
 561                    wxT("wxIDataObject::QueryGetData: bad lindex %ld"), 
 567     // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...) 
 568     if ( pformatetc
->dwAspect 
!= DVASPECT_CONTENT 
) { 
 569         wxLogTrace(wxTRACE_OleCalls
, 
 570                    wxT("wxIDataObject::QueryGetData: bad dwAspect %ld"), 
 571                    pformatetc
->dwAspect
); 
 573         return DV_E_DVASPECT
; 
 576     // and now check the type of data requested 
 577     wxDataFormat format 
= pformatetc
->cfFormat
; 
 578     if ( m_pDataObject
->IsSupportedFormat(format
) ) { 
 579         wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok"), 
 580                    wxGetFormatName(format
)); 
 583         wxLogTrace(wxTRACE_OleCalls
, 
 584                    wxT("wxIDataObject::QueryGetData: %s unsupported"), 
 585                    wxGetFormatName(format
)); 
 587         return DV_E_FORMATETC
; 
 590     // we only transfer data by global memory, except for some particular cases 
 591     DWORD tymed 
= pformatetc
->tymed
; 
 592     if ( (format 
== wxDF_BITMAP 
&& !(tymed 
& TYMED_GDI
)) && 
 593          !(tymed 
& TYMED_HGLOBAL
) ) { 
 594         // it's not what we're waiting for 
 595         wxLogTrace(wxTRACE_OleCalls
, 
 596                    wxT("wxIDataObject::QueryGetData: %s != %s"), 
 598                    GetTymedName(format 
== wxDF_BITMAP 
? TYMED_GDI
 
 607 STDMETHODIMP 
wxIDataObject::GetCanonicalFormatEtc(FORMATETC 
*WXUNUSED(pFormatetcIn
), 
 608                                                   FORMATETC 
*pFormatetcOut
) 
 610     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetCanonicalFormatEtc")); 
 612     // TODO we might want something better than this trivial implementation here 
 613     if ( pFormatetcOut 
!= NULL 
) 
 614         pFormatetcOut
->ptd 
= NULL
; 
 616     return DATA_S_SAMEFORMATETC
; 
 619 STDMETHODIMP 
wxIDataObject::EnumFormatEtc(DWORD dwDir
, 
 620                                           IEnumFORMATETC 
**ppenumFormatEtc
) 
 622     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::EnumFormatEtc")); 
 624     wxDataObject::Direction dir 
= dwDir 
== DATADIR_GET 
? wxDataObject::Get
 
 627     size_t nFormatCount 
= m_pDataObject
->GetFormatCount(dir
); 
 629     wxDataFormat 
*formats
; 
 630     formats 
= nFormatCount 
== 1 ? &format 
: new wxDataFormat
[nFormatCount
]; 
 631     m_pDataObject
->GetAllFormats(formats
, dir
); 
 633     wxIEnumFORMATETC 
*pEnum 
= new wxIEnumFORMATETC(formats
, nFormatCount
); 
 635     *ppenumFormatEtc 
= pEnum
; 
 637     if ( formats 
!= &format 
) { 
 644 // ---------------------------------------------------------------------------- 
 645 // advise sink functions (not implemented) 
 646 // ---------------------------------------------------------------------------- 
 648 STDMETHODIMP 
wxIDataObject::DAdvise(FORMATETC   
*WXUNUSED(pformatetc
), 
 649                                     DWORD        
WXUNUSED(advf
), 
 650                                     IAdviseSink 
*WXUNUSED(pAdvSink
), 
 651                                     DWORD       
*WXUNUSED(pdwConnection
)) 
 653   return OLE_E_ADVISENOTSUPPORTED
; 
 656 STDMETHODIMP 
wxIDataObject::DUnadvise(DWORD 
WXUNUSED(dwConnection
)) 
 658   return OLE_E_ADVISENOTSUPPORTED
; 
 661 STDMETHODIMP 
wxIDataObject::EnumDAdvise(IEnumSTATDATA 
**WXUNUSED(ppenumAdvise
)) 
 663   return OLE_E_ADVISENOTSUPPORTED
; 
 666 // ---------------------------------------------------------------------------- 
 668 // ---------------------------------------------------------------------------- 
 670 wxDataObject::wxDataObject() 
 672     m_pIDataObject 
= new wxIDataObject(this); 
 673     m_pIDataObject
->AddRef(); 
 676 wxDataObject::~wxDataObject() 
 678     ReleaseInterface(m_pIDataObject
); 
 681 void wxDataObject::SetAutoDelete() 
 683     ((wxIDataObject 
*)m_pIDataObject
)->SetDeleteFlag(); 
 684     m_pIDataObject
->Release(); 
 686     // so that the dtor doesnt' crash 
 687     m_pIDataObject 
= NULL
; 
 690 size_t wxDataObject::GetBufferOffset( const wxDataFormat
& WXUNUSED(format
) ) 
 692     return sizeof(size_t); 
 695 const void* wxDataObject::GetSizeFromBuffer( const void* buffer
, size_t* size
, 
 696                                              const wxDataFormat
& WXUNUSED(format
) ) 
 698     size_t* p 
= (size_t*)buffer
; 
 704 void* wxDataObject::SetSizeInBuffer( void* buffer
, size_t size
, 
 705                                        const wxDataFormat
& WXUNUSED(format
) ) 
 707     size_t* p 
= (size_t*)buffer
; 
 715 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat format
) 
 717     // case 'xxx' is not a valid value for switch of enum 'wxDataFormat' 
 719         #pragma warning(disable:4063) 
 722     static wxChar s_szBuf
[256]; 
 724         case CF_TEXT
:         return wxT("CF_TEXT"); 
 725         case CF_BITMAP
:       return wxT("CF_BITMAP"); 
 726         case CF_SYLK
:         return wxT("CF_SYLK"); 
 727         case CF_DIF
:          return wxT("CF_DIF"); 
 728         case CF_TIFF
:         return wxT("CF_TIFF"); 
 729         case CF_OEMTEXT
:      return wxT("CF_OEMTEXT"); 
 730         case CF_DIB
:          return wxT("CF_DIB"); 
 731         case CF_PALETTE
:      return wxT("CF_PALETTE"); 
 732         case CF_PENDATA
:      return wxT("CF_PENDATA"); 
 733         case CF_RIFF
:         return wxT("CF_RIFF"); 
 734         case CF_WAVE
:         return wxT("CF_WAVE"); 
 735         case CF_UNICODETEXT
:  return wxT("CF_UNICODETEXT"); 
 737         case CF_METAFILEPICT
: return wxT("CF_METAFILEPICT"); 
 738         case CF_ENHMETAFILE
:  return wxT("CF_ENHMETAFILE"); 
 739         case CF_LOCALE
:       return wxT("CF_LOCALE"); 
 740         case CF_HDROP
:        return wxT("CF_HDROP"); 
 744             if ( !::GetClipboardFormatName(format
, s_szBuf
, WXSIZEOF(s_szBuf
)) ) 
 746                 // it must be a new predefined format we don't know the name of 
 747                 wxSprintf(s_szBuf
, wxT("unknown CF (0x%04x)"), format
.GetFormatId()); 
 754         #pragma warning(default:4063) 
 760 // ---------------------------------------------------------------------------- 
 761 // wxBitmapDataObject supports CF_DIB format 
 762 // ---------------------------------------------------------------------------- 
 764 // TODO: support CF_DIB under Windows CE as well 
 766 size_t wxBitmapDataObject::GetDataSize() const 
 768 #if wxUSE_WXDIB && !defined(__WXWINCE__) 
 769     return wxDIB::ConvertFromBitmap(NULL
, GetHbitmapOf(GetBitmap())); 
 775 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 777 #if wxUSE_WXDIB && !defined(__WXWINCE__) 
 778     BITMAPINFO 
* const pbi 
= (BITMAPINFO 
*)buf
; 
 780     return wxDIB::ConvertFromBitmap(pbi
, GetHbitmapOf(GetBitmap())) != 0; 
 787 bool wxBitmapDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 789 #if wxUSE_WXDIB && !defined(__WXWINCE__) 
 790     const BITMAPINFO 
* const pbmi 
= (const BITMAPINFO 
*)buf
; 
 792     HBITMAP hbmp 
= wxDIB::ConvertToBitmap(pbmi
); 
 794     wxCHECK_MSG( hbmp
, FALSE
, wxT("pasting/dropping invalid bitmap") ); 
 796     const BITMAPINFOHEADER 
* const pbmih 
= &pbmi
->bmiHeader
; 
 797     wxBitmap 
bitmap(pbmih
->biWidth
, pbmih
->biHeight
, pbmih
->biBitCount
); 
 798     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 800     // TODO: create wxPalette if the bitmap has any 
 811 // ---------------------------------------------------------------------------- 
 812 // wxBitmapDataObject2 supports CF_BITMAP format 
 813 // ---------------------------------------------------------------------------- 
 815 // the bitmaps aren't passed by value as other types of data (i.e. by copying 
 816 // the data into a global memory chunk and passing it to the clipboard or 
 817 // another application or whatever), but by handle, so these generic functions 
 818 // don't make much sense to them. 
 820 size_t wxBitmapDataObject2::GetDataSize() const 
 825 bool wxBitmapDataObject2::GetDataHere(void *pBuf
) const 
 827     // we put a bitmap handle into pBuf 
 828     *(WXHBITMAP 
*)pBuf 
= GetBitmap().GetHBITMAP(); 
 833 bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len
), const void *pBuf
) 
 835     HBITMAP hbmp 
= *(HBITMAP 
*)pBuf
; 
 838     if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 840         wxLogLastError(wxT("GetObject(HBITMAP)")); 
 843     wxBitmap 
bitmap(bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
); 
 844     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 846     if ( !bitmap
.Ok() ) { 
 847         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 859 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat
& format
) const 
 861     if ( format
.GetFormatId() == CF_DIB 
) 
 866         // shouldn't be selected into a DC or GetDIBits() would fail 
 867         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 868                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 870         // first get the info 
 872         if ( !GetDIBits(hdc
, (HBITMAP
)m_bitmap
.GetHBITMAP(), 0, 0, 
 873                         NULL
, &bi
, DIB_RGB_COLORS
) ) 
 875             wxLogLastError(wxT("GetDIBits(NULL)")); 
 880         return sizeof(BITMAPINFO
) + bi
.bmiHeader
.biSizeImage
; 
 884         // no data to copy - we don't pass HBITMAP via global memory 
 889 bool wxBitmapDataObject::GetDataHere(const wxDataFormat
& format
, 
 892     wxASSERT_MSG( m_bitmap
.Ok(), wxT("copying invalid bitmap") ); 
 894     HBITMAP hbmp 
= (HBITMAP
)m_bitmap
.GetHBITMAP(); 
 895     if ( format
.GetFormatId() == CF_DIB 
) 
 900         // shouldn't be selected into a DC or GetDIBits() would fail 
 901         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 902                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 904         // first get the info 
 905         BITMAPINFO 
*pbi 
= (BITMAPINFO 
*)pBuf
; 
 906         if ( !GetDIBits(hdc
, hbmp
, 0, 0, NULL
, pbi
, DIB_RGB_COLORS
) ) 
 908             wxLogLastError(wxT("GetDIBits(NULL)")); 
 913         // and now copy the bits 
 914         if ( !GetDIBits(hdc
, hbmp
, 0, pbi
->bmiHeader
.biHeight
, pbi 
+ 1, 
 915                         pbi
, DIB_RGB_COLORS
) ) 
 917             wxLogLastError(wxT("GetDIBits")); 
 924         // we put a bitmap handle into pBuf 
 925         *(HBITMAP 
*)pBuf 
= hbmp
; 
 931 bool wxBitmapDataObject::SetData(const wxDataFormat
& format
, 
 932                                  size_t size
, const void *pBuf
) 
 935     if ( format
.GetFormatId() == CF_DIB 
) 
 937         // here we get BITMAPINFO struct followed by the actual bitmap bits and 
 938         // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
 941         BITMAPINFO 
*pbmi 
= (BITMAPINFO 
*)pBuf
; 
 942         BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
 943         hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
 944                               pbmi 
+ 1, pbmi
, DIB_RGB_COLORS
); 
 947             wxLogLastError(wxT("CreateDIBitmap")); 
 950         m_bitmap
.SetWidth(pbmih
->biWidth
); 
 951         m_bitmap
.SetHeight(pbmih
->biHeight
); 
 955         // it's easy with bitmaps: we pass them by handle 
 956         hbmp 
= *(HBITMAP 
*)pBuf
; 
 959         if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 961             wxLogLastError(wxT("GetObject(HBITMAP)")); 
 964         m_bitmap
.SetWidth(bmp
.bmWidth
); 
 965         m_bitmap
.SetHeight(bmp
.bmHeight
); 
 966         m_bitmap
.SetDepth(bmp
.bmPlanes
); 
 969     m_bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 971     wxASSERT_MSG( m_bitmap
.Ok(), wxT("pasting invalid bitmap") ); 
 978 // ---------------------------------------------------------------------------- 
 980 // ---------------------------------------------------------------------------- 
 982 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *pData
) 
 987     // the documentation states that the first member of DROPFILES structure is 
 988     // a "DWORD offset of double NUL terminated file list". What they mean by 
 989     // this (I wonder if you see it immediately) is that the list starts at 
 990     // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised 
 991     // to use DragQueryFile to work with this structure, but not told where and 
 993     HDROP hdrop 
= (HDROP
)pData
;   // NB: it works, but I'm not sure about it 
 995     // get number of files (magic value -1) 
 996     UINT nFiles 
= ::DragQueryFile(hdrop
, (unsigned)-1, NULL
, 0u); 
 998     wxCHECK_MSG ( nFiles 
!= (UINT
)-1, FALSE
, wxT("wrong HDROP handle") ); 
1000     // for each file get the length, allocate memory and then get the name 
1003     for ( n 
= 0; n 
< nFiles
; n
++ ) { 
1004         // +1 for terminating NUL 
1005         len 
= ::DragQueryFile(hdrop
, n
, NULL
, 0) + 1; 
1007         UINT len2 
= ::DragQueryFile(hdrop
, n
, wxStringBuffer(str
, len
), len
); 
1008         m_filenames
.Add(str
); 
1010         if ( len2 
!= len 
- 1 ) { 
1011             wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\ 
1012  %d characters, %d expected."), len2
, len 
- 1); 
1023 void wxFileDataObject::AddFile(const wxString
& file
) 
1025     // just add file to filenames array 
1026     // all useful data (such as DROPFILES struct) will be 
1027     // created later as necessary 
1028     m_filenames
.Add(file
); 
1031 size_t wxFileDataObject::GetDataSize() const 
1034     // size returned will be the size of the DROPFILES structure, 
1035     // plus the list of filesnames (null byte separated), plus 
1036     // a double null at the end 
1038     // if no filenames in list, size is 0 
1039     if ( m_filenames
.GetCount() == 0 ) 
1042     // inital size of DROPFILES struct + null byte 
1043     size_t sz 
= sizeof(DROPFILES
) + (1 * sizeof(wxChar
)); 
1045     size_t count 
= m_filenames
.GetCount(); 
1046     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1048         // add filename length plus null byte 
1049         sz 
+= (m_filenames
[i
].Len() + 1) * sizeof(wxChar
); 
1058 bool wxFileDataObject::GetDataHere(void *pData
) const 
1061     // pData points to an externally allocated memory block 
1062     // created using the size returned by GetDataSize() 
1064     // if pData is NULL, or there are no files, return 
1065     if ( !pData 
|| m_filenames
.GetCount() == 0 ) 
1068     // convert data pointer to a DROPFILES struct pointer 
1069     LPDROPFILES pDrop 
= (LPDROPFILES
) pData
; 
1071     // initialize DROPFILES struct 
1072     pDrop
->pFiles 
= sizeof(DROPFILES
); 
1073     pDrop
->fNC 
= FALSE
;                 // not non-client coords 
1075     pDrop
->fWide 
= TRUE
; 
1077     pDrop
->fWide 
= FALSE
; 
1078 #endif // Unicode/Ansi 
1080     // set start of filenames list (null separated) 
1081     wxChar 
*pbuf 
= (wxChar
*) ((BYTE 
*)pDrop 
+ sizeof(DROPFILES
)); 
1083     size_t count 
= m_filenames
.GetCount(); 
1084     for (size_t i 
= 0; i 
< count
; i
++ ) 
1086         // copy filename to pbuf and add null terminator 
1087         size_t len 
= m_filenames
[i
].Len(); 
1088         memcpy(pbuf
, m_filenames
[i
], len
*sizeof(wxChar
)); 
1090         *pbuf
++ = wxT('\0'); 
1093     // add final null terminator 
1103 // ---------------------------------------------------------------------------- 
1105 // ---------------------------------------------------------------------------- 
1107 class CFSTR_SHELLURLDataObject 
: public wxCustomDataObject
 
1110     CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL
) {} 
1112     virtual size_t GetBufferOffset( const wxDataFormat
& WXUNUSED(format
) ) 
1117     virtual const void* GetSizeFromBuffer( const void* buffer
, size_t* size
, 
1118                                            const wxDataFormat
& WXUNUSED(format
) ) 
1120         // CFSTR_SHELLURL is _always_ ANSI text 
1121         *size 
= strlen( (const char*)buffer 
); 
1126     virtual void* SetSizeInBuffer( void* buffer
, size_t WXUNUSED(size
), 
1127                                    const wxDataFormat
& WXUNUSED(format
) ) 
1133     virtual bool GetDataHere( void* buffer 
) const 
1135         // CFSTR_SHELLURL is _always_ ANSI! 
1136         wxCharBuffer 
char_buffer( GetDataSize() ); 
1137         wxCustomDataObject::GetDataHere( (void*)char_buffer
.data() ); 
1138         wxString 
unicode_buffer( char_buffer
, wxConvLibc 
); 
1139         memcpy( buffer
, unicode_buffer
.c_str(), 
1140                 ( unicode_buffer
.length() + 1 ) * sizeof(wxChar
) ); 
1144     virtual bool GetDataHere(const wxDataFormat
& WXUNUSED(format
), 
1146         { return GetDataHere(buf
); } 
1149     DECLARE_NO_COPY_CLASS(CFSTR_SHELLURLDataObject
) 
1154 wxURLDataObject::wxURLDataObject() 
1156     // we support CF_TEXT and CFSTR_SHELLURL formats which are basicly the same 
1157     // but it seems that some browsers only provide one of them so we have to 
1159     Add(new wxTextDataObject
); 
1160     Add(new CFSTR_SHELLURLDataObject()); 
1162     // we don't have any data yet 
1163     m_dataObjectLast 
= NULL
; 
1166 bool wxURLDataObject::SetData(const wxDataFormat
& format
, 
1170     m_dataObjectLast 
= GetObject(format
); 
1172     wxCHECK_MSG( m_dataObjectLast
, FALSE
, 
1173                  wxT("unsupported format in wxURLDataObject")); 
1175     return m_dataObjectLast
->SetData(len
, buf
); 
1178 wxString 
wxURLDataObject::GetURL() const 
1181     wxCHECK_MSG( m_dataObjectLast
, url
, _T("no data in wxURLDataObject") ); 
1183     size_t len 
= m_dataObjectLast
->GetDataSize(); 
1185     m_dataObjectLast
->GetDataHere(wxStringBuffer(url
, len
)); 
1190 void wxURLDataObject::SetURL(const wxString
& url
) 
1192     SetData(wxDataFormat(wxUSE_UNICODE 
? wxDF_UNICODETEXT 
: wxDF_TEXT
), 
1193             url
.Length()+1, url
.c_str()); 
1195     // CFSTR_SHELLURL is always supposed to be ANSI... 
1196     wxWX2MBbuf urlA 
= (wxWX2MBbuf
)url
.mbc_str(); 
1197     size_t len 
= strlen(urlA
); 
1198     SetData(wxDataFormat(CFSTR_SHELLURL
), len
+1, (const char*)urlA
); 
1201 // ---------------------------------------------------------------------------- 
1202 // private functions 
1203 // ---------------------------------------------------------------------------- 
1207 static const wxChar 
*GetTymedName(DWORD tymed
) 
1209     static wxChar s_szBuf
[128]; 
1211         case TYMED_HGLOBAL
:   return wxT("TYMED_HGLOBAL"); 
1212         case TYMED_FILE
:      return wxT("TYMED_FILE"); 
1213         case TYMED_ISTREAM
:   return wxT("TYMED_ISTREAM"); 
1214         case TYMED_ISTORAGE
:  return wxT("TYMED_ISTORAGE"); 
1215         case TYMED_GDI
:       return wxT("TYMED_GDI"); 
1216         case TYMED_MFPICT
:    return wxT("TYMED_MFPICT"); 
1217         case TYMED_ENHMF
:     return wxT("TYMED_ENHMF"); 
1219             wxSprintf(s_szBuf
, wxT("type of media format %ld (unknown)"), tymed
); 
1226 #else // not using OLE at all 
1228 // ---------------------------------------------------------------------------- 
1230 // ---------------------------------------------------------------------------- 
1234 wxDataObject::wxDataObject() 
1238 wxDataObject::~wxDataObject() 
1242 void wxDataObject::SetAutoDelete() 
1247 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat 
WXUNUSED(format
)) 
1251 #endif // __WXDEBUG__ 
1253 #endif // wxUSE_DATAOBJ 
1255 #endif // wxUSE_OLE/!wxUSE_OLE