]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
   1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/ole/dataobj.cpp 
   3 // Purpose:     implementation of wx[I]DataObject class 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "dataobj.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  27 #if defined(__BORLANDC__) 
  36 #include "wx/dataobj.h" 
  38 #if wxUSE_OLE && defined(__WIN32__) && !defined(__GNUWIN32_OLD__) 
  40 #include "wx/msw/private.h"         // includes <windows.h> 
  42 #if wxUSE_NORLANDER_HEADERS 
  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) _T("") 
  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 
  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 inversed, that is we delete it 
 108     // when this object is deleted - setting this flag enables such logic 
 109     void SetDeleteFlag() { m_mustDelete 
= TRUE
; } 
 111     DECLARE_IUNKNOWN_METHODS
; 
 114     STDMETHODIMP 
GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
); 
 115     STDMETHODIMP 
GetDataHere(FORMATETC 
*pformatetc
, STGMEDIUM 
*pmedium
); 
 116     STDMETHODIMP 
QueryGetData(FORMATETC 
*pformatetc
); 
 117     STDMETHODIMP 
GetCanonicalFormatEtc(FORMATETC 
*In
, FORMATETC 
*pOut
); 
 118     STDMETHODIMP 
SetData(FORMATETC 
*pfetc
, STGMEDIUM 
*pmedium
, BOOL fRelease
); 
 119     STDMETHODIMP 
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC 
**ppenumFEtc
); 
 120     STDMETHODIMP 
DAdvise(FORMATETC 
*pfetc
, DWORD ad
, IAdviseSink 
*p
, DWORD 
*pdw
); 
 121     STDMETHODIMP 
DUnadvise(DWORD dwConnection
); 
 122     STDMETHODIMP 
EnumDAdvise(IEnumSTATDATA 
**ppenumAdvise
); 
 125     wxDataObject 
*m_pDataObject
;      // pointer to C++ class we belong to 
 130 // ============================================================================ 
 132 // ============================================================================ 
 134 // ---------------------------------------------------------------------------- 
 136 // ---------------------------------------------------------------------------- 
 138 void wxDataFormat::SetId(const wxChar 
*format
) 
 140     m_format 
= (wxDataFormat::NativeFormat
)::RegisterClipboardFormat(format
); 
 143         wxLogError(_("Couldn't register clipboard format '%s'."), format
); 
 147 wxString 
wxDataFormat::GetId() const 
 149     static const int max 
= 256; 
 153     wxCHECK_MSG( !IsStandard(), s
, 
 154                  wxT("name of predefined format cannot be retrieved") ); 
 156     int len 
= ::GetClipboardFormatName(m_format
, s
.GetWriteBuf(max
), max
); 
 161         wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
); 
 167 // ---------------------------------------------------------------------------- 
 169 // ---------------------------------------------------------------------------- 
 171 BEGIN_IID_TABLE(wxIEnumFORMATETC
) 
 173     ADD_IID(EnumFORMATETC
) 
 176 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
) 
 178 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat 
*formats
, ULONG nCount
) 
 183     m_formats 
= new CLIPFORMAT
[nCount
]; 
 184     for ( ULONG n 
= 0; n 
< nCount
; n
++ ) { 
 185         m_formats
[n
] = formats
[n
].GetFormatId(); 
 189 STDMETHODIMP 
wxIEnumFORMATETC::Next(ULONG      celt
, 
 191                                     ULONG     
*WXUNUSED(pceltFetched
)) 
 193     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Next")); 
 196         // we only return 1 element at a time - mainly because I'm too lazy to 
 197         // implement something which you're never asked for anyhow 
 201     if ( m_nCurrent 
< m_nCount 
) { 
 203         format
.cfFormat 
= m_formats
[m_nCurrent
++]; 
 205         format
.dwAspect 
= DVASPECT_CONTENT
; 
 207         format
.tymed    
= TYMED_HGLOBAL
; 
 218 STDMETHODIMP 
wxIEnumFORMATETC::Skip(ULONG celt
) 
 220     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Skip")); 
 223     if ( m_nCurrent 
< m_nCount 
) 
 226     // no, can't skip this many elements 
 232 STDMETHODIMP 
wxIEnumFORMATETC::Reset() 
 234     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Reset")); 
 241 STDMETHODIMP 
wxIEnumFORMATETC::Clone(IEnumFORMATETC 
**ppenum
) 
 243     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Clone")); 
 245     // unfortunately, we can't reuse the code in ctor - types are different 
 246     wxIEnumFORMATETC 
*pNew 
= new wxIEnumFORMATETC(NULL
, 0); 
 247     pNew
->m_nCount 
= m_nCount
; 
 248     pNew
->m_formats 
= new CLIPFORMAT
[m_nCount
]; 
 249     for ( ULONG n 
= 0; n 
< m_nCount
; n
++ ) { 
 250         pNew
->m_formats
[n
] = m_formats
[n
]; 
 258 // ---------------------------------------------------------------------------- 
 260 // ---------------------------------------------------------------------------- 
 262 BEGIN_IID_TABLE(wxIDataObject
) 
 267 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
) 
 269 wxIDataObject::wxIDataObject(wxDataObject 
*pDataObject
) 
 272     m_pDataObject 
= pDataObject
; 
 273     m_mustDelete 
= FALSE
; 
 276 wxIDataObject::~wxIDataObject() 
 280         delete m_pDataObject
; 
 284 // get data functions 
 285 STDMETHODIMP 
wxIDataObject::GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
) 
 287     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetData")); 
 289     // is data is in our format? 
 290     HRESULT hr 
= QueryGetData(pformatetcIn
); 
 294     // for the bitmaps and metafiles we use the handles instead of global memory 
 296     wxDataFormat format 
= (wxDataFormatId
)pformatetcIn
->cfFormat
; 
 301             pmedium
->tymed 
= TYMED_GDI
; 
 304         case wxDF_ENHMETAFILE
: 
 305             pmedium
->tymed 
= TYMED_ENHMF
; 
 309             pmedium
->hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, 
 310                                            sizeof(METAFILEPICT
)); 
 311             if ( !pmedium
->hGlobal 
) { 
 312                 wxLogLastError(wxT("GlobalAlloc")); 
 313                 return E_OUTOFMEMORY
; 
 315             pmedium
->tymed 
= TYMED_MFPICT
; 
 320             size_t size 
= m_pDataObject
->GetDataSize(format
); 
 322                 // it probably means that the method is just not implemented 
 323                 wxLogDebug(wxT("Invalid data size - can't be 0")); 
 325                 return DV_E_FORMATETC
; 
 328             if ( !format
.IsStandard() ) { 
 329                 // for custom formats, put the size with the data - alloc the 
 331                 // MB: not completely sure this is correct, 
 332                 //     even if I can't figure out what's wrong 
 333                 size 
+= m_pDataObject
->GetBufferOffset( format 
); 
 336             HGLOBAL hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, size
); 
 337             if ( hGlobal 
== NULL 
) { 
 338                 wxLogLastError(wxT("GlobalAlloc")); 
 339                 return E_OUTOFMEMORY
; 
 343             pmedium
->tymed   
= TYMED_HGLOBAL
; 
 344             pmedium
->hGlobal 
= hGlobal
; 
 347     pmedium
->pUnkForRelease 
= NULL
; 
 350     hr 
= GetDataHere(pformatetcIn
, pmedium
); 
 352         // free resources we allocated 
 353         if ( pmedium
->tymed 
& (TYMED_HGLOBAL 
| TYMED_MFPICT
) ) { 
 354             GlobalFree(pmedium
->hGlobal
); 
 363 STDMETHODIMP 
wxIDataObject::GetDataHere(FORMATETC 
*pformatetc
, 
 366     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetDataHere")); 
 368     // put data in caller provided medium 
 369     switch ( pmedium
->tymed 
) 
 372             if ( !m_pDataObject
->GetDataHere(wxDF_BITMAP
, &pmedium
->hBitmap
) ) 
 377             if ( !m_pDataObject
->GetDataHere(wxDF_ENHMETAFILE
, 
 378                                              &pmedium
->hEnhMetaFile
) ) 
 383             // fall through - we pass METAFILEPICT through HGLOBAL 
 388                 HGLOBAL hGlobal 
= pmedium
->hGlobal
; 
 389                 void *pBuf 
= GlobalLock(hGlobal
); 
 390                 if ( pBuf 
== NULL 
) { 
 391                     wxLogLastError(wxT("GlobalLock")); 
 392                     return E_OUTOFMEMORY
; 
 395                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 396                 if ( !format
.IsStandard() ) { 
 397                     // for custom formats, put the size with the data 
 398                     pBuf 
= m_pDataObject
->SetSizeInBuffer( pBuf
, GlobalSize(hGlobal
), format 
); 
 401                 if ( !m_pDataObject
->GetDataHere(format
, pBuf
) ) 
 404                 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
->IsSupportedFormat(format
) ) { 
 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 
= ::wcslen((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) 
 487                         // the handler will calculate size itself (it's too 
 488                         // complicated to do it here) 
 492                     case CF_METAFILEPICT
: 
 493                         size 
= sizeof(METAFILEPICT
); 
 498                             // we suppose that the size precedes the data 
 499                             pBuf 
= m_pDataObject
->GetSizeFromBuffer( pBuf
, &size
, format 
); 
 500                             if (! format
.IsStandard() ) { 
 501                                 // see GetData for coresponding increment 
 502                                 size 
-= m_pDataObject
->GetBufferOffset( format  
); 
 507                 bool ok 
= m_pDataObject
->SetData(format
, size
, pBuf
); 
 509                 GlobalUnlock(pmedium
->hGlobal
); 
 522         // we own the medium, so we must release it - but do *not* free any 
 523         // data we pass by handle because we have copied it elsewhere 
 524         switch ( pmedium
->tymed 
) 
 527                 pmedium
->hBitmap 
= 0; 
 531                 pmedium
->hMetaFilePict 
= 0; 
 535                 pmedium
->hEnhMetaFile 
= 0; 
 539         ReleaseStgMedium(pmedium
); 
 545 // information functions 
 546 STDMETHODIMP 
wxIDataObject::QueryGetData(FORMATETC 
*pformatetc
) 
 548     // do we accept data in this format? 
 549     if ( pformatetc 
== NULL 
) { 
 550         wxLogTrace(wxTRACE_OleCalls
, 
 551                    wxT("wxIDataObject::QueryGetData: invalid ptr.")); 
 556     // the only one allowed by current COM implementation 
 557     if ( pformatetc
->lindex 
!= -1 ) { 
 558         wxLogTrace(wxTRACE_OleCalls
, 
 559                    wxT("wxIDataObject::QueryGetData: bad lindex %d"), 
 565     // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...) 
 566     if ( pformatetc
->dwAspect 
!= DVASPECT_CONTENT 
) { 
 567         wxLogTrace(wxTRACE_OleCalls
, 
 568                    wxT("wxIDataObject::QueryGetData: bad dwAspect %d"), 
 569                    pformatetc
->dwAspect
); 
 571         return DV_E_DVASPECT
; 
 574     // and now check the type of data requested 
 575     wxDataFormat format 
= pformatetc
->cfFormat
; 
 576     if ( m_pDataObject
->IsSupportedFormat(format
) ) { 
 577         wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok"), 
 578                    wxGetFormatName(format
)); 
 581         wxLogTrace(wxTRACE_OleCalls
, 
 582                    wxT("wxIDataObject::QueryGetData: %s unsupported"), 
 583                    wxGetFormatName(format
)); 
 585         return DV_E_FORMATETC
; 
 588     // we only transfer data by global memory, except for some particular cases 
 589     DWORD tymed 
= pformatetc
->tymed
; 
 590     if ( (format 
== wxDF_BITMAP 
&& !(tymed 
& TYMED_GDI
)) && 
 591          !(tymed 
& TYMED_HGLOBAL
) ) { 
 592         // it's not what we're waiting for 
 593         wxLogTrace(wxTRACE_OleCalls
, 
 594                    wxT("wxIDataObject::QueryGetData: %s != %s"), 
 596                    GetTymedName(format 
== wxDF_BITMAP 
? TYMED_GDI
 
 605 STDMETHODIMP 
wxIDataObject::GetCanonicalFormatEtc(FORMATETC 
*WXUNUSED(pFormatetcIn
), 
 606                                                   FORMATETC 
*pFormatetcOut
) 
 608     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetCanonicalFormatEtc")); 
 610     // TODO we might want something better than this trivial implementation here 
 611     if ( pFormatetcOut 
!= NULL 
) 
 612         pFormatetcOut
->ptd 
= NULL
; 
 614     return DATA_S_SAMEFORMATETC
; 
 617 STDMETHODIMP 
wxIDataObject::EnumFormatEtc(DWORD dwDir
, 
 618                                           IEnumFORMATETC 
**ppenumFormatEtc
) 
 620     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::EnumFormatEtc")); 
 622     wxDataObject::Direction dir 
= dwDir 
== DATADIR_GET 
? wxDataObject::Get
 
 625     size_t nFormatCount 
= m_pDataObject
->GetFormatCount(dir
); 
 627     wxDataFormat 
*formats
; 
 628     formats 
= nFormatCount 
== 1 ? &format 
: new wxDataFormat
[nFormatCount
]; 
 629     m_pDataObject
->GetAllFormats(formats
, dir
); 
 631     wxIEnumFORMATETC 
*pEnum 
= new wxIEnumFORMATETC(formats
, nFormatCount
); 
 633     *ppenumFormatEtc 
= pEnum
; 
 635     if ( formats 
!= &format 
) { 
 642 // ---------------------------------------------------------------------------- 
 643 // advise sink functions (not implemented) 
 644 // ---------------------------------------------------------------------------- 
 646 STDMETHODIMP 
wxIDataObject::DAdvise(FORMATETC   
*WXUNUSED(pformatetc
), 
 647                                     DWORD        
WXUNUSED(advf
), 
 648                                     IAdviseSink 
*WXUNUSED(pAdvSink
), 
 649                                     DWORD       
*WXUNUSED(pdwConnection
)) 
 651   return OLE_E_ADVISENOTSUPPORTED
; 
 654 STDMETHODIMP 
wxIDataObject::DUnadvise(DWORD 
WXUNUSED(dwConnection
)) 
 656   return OLE_E_ADVISENOTSUPPORTED
; 
 659 STDMETHODIMP 
wxIDataObject::EnumDAdvise(IEnumSTATDATA 
**WXUNUSED(ppenumAdvise
)) 
 661   return OLE_E_ADVISENOTSUPPORTED
; 
 664 // ---------------------------------------------------------------------------- 
 666 // ---------------------------------------------------------------------------- 
 668 wxDataObject::wxDataObject() 
 670     m_pIDataObject 
= new wxIDataObject(this); 
 671     m_pIDataObject
->AddRef(); 
 674 wxDataObject::~wxDataObject() 
 676     ReleaseInterface(m_pIDataObject
); 
 679 void wxDataObject::SetAutoDelete() 
 681     ((wxIDataObject 
*)m_pIDataObject
)->SetDeleteFlag(); 
 682     m_pIDataObject
->Release(); 
 684     // so that the dtor doesnt' crash 
 685     m_pIDataObject 
= NULL
; 
 688 size_t wxDataObject::GetBufferOffset( const wxDataFormat
& format 
) 
 690     return sizeof(size_t); 
 693 const void* wxDataObject::GetSizeFromBuffer( const void* buffer
, size_t* size
, 
 694                                              const wxDataFormat
& format 
) 
 696     size_t* p 
= (size_t*)buffer
; 
 702 void* wxDataObject::SetSizeInBuffer( void* buffer
, size_t size
, 
 703                                        const wxDataFormat
& format 
) 
 705     size_t* p 
= (size_t*)buffer
; 
 713 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat format
) 
 715     // case 'xxx' is not a valid value for switch of enum 'wxDataFormat' 
 717         #pragma warning(disable:4063) 
 720     static wxChar s_szBuf
[256]; 
 722         case CF_TEXT
:         return wxT("CF_TEXT"); 
 723         case CF_BITMAP
:       return wxT("CF_BITMAP"); 
 724         case CF_METAFILEPICT
: return wxT("CF_METAFILEPICT"); 
 725         case CF_SYLK
:         return wxT("CF_SYLK"); 
 726         case CF_DIF
:          return wxT("CF_DIF"); 
 727         case CF_TIFF
:         return wxT("CF_TIFF"); 
 728         case CF_OEMTEXT
:      return wxT("CF_OEMTEXT"); 
 729         case CF_DIB
:          return wxT("CF_DIB"); 
 730         case CF_PALETTE
:      return wxT("CF_PALETTE"); 
 731         case CF_PENDATA
:      return wxT("CF_PENDATA"); 
 732         case CF_RIFF
:         return wxT("CF_RIFF"); 
 733         case CF_WAVE
:         return wxT("CF_WAVE"); 
 734         case CF_UNICODETEXT
:  return wxT("CF_UNICODETEXT"); 
 735         case CF_ENHMETAFILE
:  return wxT("CF_ENHMETAFILE"); 
 736         case CF_HDROP
:        return wxT("CF_HDROP"); 
 737         case CF_LOCALE
:       return wxT("CF_LOCALE"); 
 740             if ( !::GetClipboardFormatName(format
, s_szBuf
, WXSIZEOF(s_szBuf
)) ) 
 742                 // it must be a new predefined format we don't know the name of 
 743                 wxSprintf(s_szBuf
, wxT("unknown CF (0x%04x)"), format
.GetFormatId()); 
 750         #pragma warning(default:4063) 
 756 // ---------------------------------------------------------------------------- 
 757 // wxBitmapDataObject supports CF_DIB format 
 758 // ---------------------------------------------------------------------------- 
 760 size_t wxBitmapDataObject::GetDataSize() const 
 762     return wxConvertBitmapToDIB(NULL
, GetBitmap()); 
 765 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 767     return wxConvertBitmapToDIB((LPBITMAPINFO
)buf
, GetBitmap()) != 0; 
 770 bool wxBitmapDataObject::SetData(size_t WXUNUSED(len
), const void *buf
) 
 772     wxBitmap 
bitmap(wxConvertDIBToBitmap((const LPBITMAPINFO
)buf
)); 
 774     if ( !bitmap
.Ok() ) { 
 775         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 785 // ---------------------------------------------------------------------------- 
 786 // wxBitmapDataObject2 supports CF_BITMAP format 
 787 // ---------------------------------------------------------------------------- 
 789 // the bitmaps aren't passed by value as other types of data (i.e. by copying 
 790 // the data into a global memory chunk and passing it to the clipboard or 
 791 // another application or whatever), but by handle, so these generic functions 
 792 // don't make much sense to them. 
 794 size_t wxBitmapDataObject2::GetDataSize() const 
 799 bool wxBitmapDataObject2::GetDataHere(void *pBuf
) const 
 801     // we put a bitmap handle into pBuf 
 802     *(WXHBITMAP 
*)pBuf 
= GetBitmap().GetHBITMAP(); 
 807 bool wxBitmapDataObject2::SetData(size_t WXUNUSED(len
), const void *pBuf
) 
 809     HBITMAP hbmp 
= *(HBITMAP 
*)pBuf
; 
 812     if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 814         wxLogLastError(wxT("GetObject(HBITMAP)")); 
 817     wxBitmap 
bitmap(bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
); 
 818     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 820     if ( !bitmap
.Ok() ) { 
 821         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 833 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat
& format
) const 
 835     if ( format
.GetFormatId() == CF_DIB 
) 
 840         // shouldn't be selected into a DC or GetDIBits() would fail 
 841         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 842                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 844         // first get the info 
 846         if ( !GetDIBits(hdc
, (HBITMAP
)m_bitmap
.GetHBITMAP(), 0, 0, 
 847                         NULL
, &bi
, DIB_RGB_COLORS
) ) 
 849             wxLogLastError(wxT("GetDIBits(NULL)")); 
 854         return sizeof(BITMAPINFO
) + bi
.bmiHeader
.biSizeImage
; 
 858         // no data to copy - we don't pass HBITMAP via global memory 
 863 bool wxBitmapDataObject::GetDataHere(const wxDataFormat
& format
, 
 866     wxASSERT_MSG( m_bitmap
.Ok(), wxT("copying invalid bitmap") ); 
 868     HBITMAP hbmp 
= (HBITMAP
)m_bitmap
.GetHBITMAP(); 
 869     if ( format
.GetFormatId() == CF_DIB 
) 
 874         // shouldn't be selected into a DC or GetDIBits() would fail 
 875         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 876                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 878         // first get the info 
 879         BITMAPINFO 
*pbi 
= (BITMAPINFO 
*)pBuf
; 
 880         if ( !GetDIBits(hdc
, hbmp
, 0, 0, NULL
, pbi
, DIB_RGB_COLORS
) ) 
 882             wxLogLastError(wxT("GetDIBits(NULL)")); 
 887         // and now copy the bits 
 888         if ( !GetDIBits(hdc
, hbmp
, 0, pbi
->bmiHeader
.biHeight
, pbi 
+ 1, 
 889                         pbi
, DIB_RGB_COLORS
) ) 
 891             wxLogLastError(wxT("GetDIBits")); 
 898         // we put a bitmap handle into pBuf 
 899         *(HBITMAP 
*)pBuf 
= hbmp
; 
 905 bool wxBitmapDataObject::SetData(const wxDataFormat
& format
, 
 906                                  size_t size
, const void *pBuf
) 
 909     if ( format
.GetFormatId() == CF_DIB 
) 
 911         // here we get BITMAPINFO struct followed by the actual bitmap bits and 
 912         // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
 915         BITMAPINFO 
*pbmi 
= (BITMAPINFO 
*)pBuf
; 
 916         BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
 917         hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
 918                               pbmi 
+ 1, pbmi
, DIB_RGB_COLORS
); 
 921             wxLogLastError(wxT("CreateDIBitmap")); 
 924         m_bitmap
.SetWidth(pbmih
->biWidth
); 
 925         m_bitmap
.SetHeight(pbmih
->biHeight
); 
 929         // it's easy with bitmaps: we pass them by handle 
 930         hbmp 
= *(HBITMAP 
*)pBuf
; 
 933         if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 935             wxLogLastError(wxT("GetObject(HBITMAP)")); 
 938         m_bitmap
.SetWidth(bmp
.bmWidth
); 
 939         m_bitmap
.SetHeight(bmp
.bmHeight
); 
 940         m_bitmap
.SetDepth(bmp
.bmPlanes
); 
 943     m_bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 945     wxASSERT_MSG( m_bitmap
.Ok(), wxT("pasting invalid bitmap") ); 
 952 // ---------------------------------------------------------------------------- 
 954 // ---------------------------------------------------------------------------- 
 956 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *pData
) 
 960     // the documentation states that the first member of DROPFILES structure is 
 961     // a "DWORD offset of double NUL terminated file list". What they mean by 
 962     // this (I wonder if you see it immediately) is that the list starts at 
 963     // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised 
 964     // to use DragQueryFile to work with this structure, but not told where and 
 966     HDROP hdrop 
= (HDROP
)pData
;   // NB: it works, but I'm not sure about it 
 968     // get number of files (magic value -1) 
 969     UINT nFiles 
= ::DragQueryFile(hdrop
, (unsigned)-1, NULL
, 0u); 
 971     wxCHECK_MSG ( nFiles 
!= (UINT
)-1, FALSE
, wxT("wrong HDROP handle") ); 
 973     // for each file get the length, allocate memory and then get the name 
 976     for ( n 
= 0; n 
< nFiles
; n
++ ) { 
 977         // +1 for terminating NUL 
 978         len 
= ::DragQueryFile(hdrop
, n
, NULL
, 0) + 1; 
 980         UINT len2 
= ::DragQueryFile(hdrop
, n
, str
.GetWriteBuf(len
), len
); 
 982         m_filenames
.Add(str
); 
 984         if ( len2 
!= len 
- 1 ) { 
 985             wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned\ 
 986  %d characters, %d expected."), len2
, len 
- 1); 
 993 void wxFileDataObject::AddFile(const wxString
& file
) 
 995     // just add file to filenames array 
 996     // all useful data (such as DROPFILES struct) will be 
 997     // created later as necessary 
 998     m_filenames
.Add(file
); 
1001 size_t wxFileDataObject::GetDataSize() const 
1003     // size returned will be the size of the DROPFILES structure, 
1004     // plus the list of filesnames (null byte separated), plus 
1005     // a double null at the end 
1007     // if no filenames in list, size is 0 
1008     if ( m_filenames
.GetCount() == 0 ) 
1011     // inital size of DROPFILES struct + null byte 
1012     size_t sz 
= sizeof(DROPFILES
) + 1; 
1014     size_t count 
= m_filenames
.GetCount(); 
1015     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1017         // add filename length plus null byte 
1018         sz 
+= m_filenames
[i
].Len() + 1; 
1024 bool wxFileDataObject::GetDataHere(void *pData
) const 
1026     // pData points to an externally allocated memory block 
1027     // created using the size returned by GetDataSize() 
1029     // if pData is NULL, or there are no files, return 
1030     if ( !pData 
|| m_filenames
.GetCount() == 0 ) 
1033     // convert data pointer to a DROPFILES struct pointer 
1034     LPDROPFILES pDrop 
= (LPDROPFILES
) pData
; 
1036     // initialize DROPFILES struct 
1037     pDrop
->pFiles 
= sizeof(DROPFILES
); 
1038     pDrop
->fNC 
= FALSE
;                 // not non-client coords 
1040     pDrop
->fWide 
= TRUE
; 
1042     pDrop
->fWide 
= FALSE
; 
1043 #endif // Unicode/Ansi 
1045     // set start of filenames list (null separated) 
1046     wxChar 
*pbuf 
= (wxChar
*) ((BYTE 
*)pDrop 
+ sizeof(DROPFILES
)); 
1048     size_t count 
= m_filenames
.GetCount(); 
1049     for (size_t i 
= 0; i 
< count
; i
++ ) 
1051         // copy filename to pbuf and add null terminator 
1052         size_t len 
= m_filenames
[i
].Len(); 
1053         memcpy(pbuf
, m_filenames
[i
], len
); 
1055         *pbuf
++ = wxT('\0'); 
1058     // add final null terminator 
1064 // ---------------------------------------------------------------------------- 
1066 // ---------------------------------------------------------------------------- 
1068 class CFSTR_SHELLURLDataObject
:public wxCustomDataObject
 
1071     CFSTR_SHELLURLDataObject() : wxCustomDataObject(CFSTR_SHELLURL
) {} 
1073     virtual size_t GetBufferOffset( const wxDataFormat
& format 
) 
1078     virtual const void* GetSizeFromBuffer( const void* buffer
, size_t* size
, 
1079                                            const wxDataFormat
& format 
) 
1081         // CFSTR_SHELLURL is _always_ ANSI text 
1082         *size 
= strlen( (const char*)buffer 
); 
1087     virtual void* SetSizeInBuffer( void* buffer
, size_t size
, 
1088                                    const wxDataFormat
& format 
) 
1093     virtual bool GetDataHere( void* buffer 
) const 
1095         // CFSTR_SHELLURL is _always_ ANSI! 
1096         wxCharBuffer 
char_buffer( GetDataSize() ); 
1097         wxCustomDataObject::GetDataHere( (void*)char_buffer
.data() ); 
1098         wxString 
unicode_buffer( char_buffer 
); 
1099         memcpy( buffer
, unicode_buffer
.c_str(), 
1100                 ( unicode_buffer
.length() + 1 ) * sizeof(wxChar
) ); 
1107 wxURLDataObject::wxURLDataObject() 
1109     // we support CF_TEXT and CFSTR_SHELLURL formats which are basicly the same 
1110     // but it seems that some browsers only provide one of them so we have to 
1112     Add(new wxTextDataObject
); 
1113     Add(new CFSTR_SHELLURLDataObject()); 
1115     // we don't have any data yet 
1116     m_dataObjectLast 
= NULL
; 
1119 bool wxURLDataObject::SetData(const wxDataFormat
& format
, 
1123     m_dataObjectLast 
= GetObject(format
); 
1125     wxCHECK_MSG( m_dataObjectLast
, FALSE
, 
1126                  wxT("unsupported format in wxURLDataObject")); 
1128     return m_dataObjectLast
->SetData(len
, buf
); 
1131 wxString 
wxURLDataObject::GetURL() const 
1134     wxCHECK_MSG( m_dataObjectLast
, url
, _T("no data in wxURLDataObject") ); 
1136     size_t len 
= m_dataObjectLast
->GetDataSize(); 
1138     m_dataObjectLast
->GetDataHere(url
.GetWriteBuf(len
)); 
1139     url
.UngetWriteBuf(); 
1144 void wxURLDataObject::SetURL(const wxString
& url
) 
1146     SetData(wxDataFormat(wxDF_TEXT
), url
.Length()+1, url
.c_str()); 
1147     SetData(wxDataFormat(CFSTR_SHELLURL
), url
.Length()+1, url
.c_str()); 
1150 // ---------------------------------------------------------------------------- 
1151 // private functions 
1152 // ---------------------------------------------------------------------------- 
1154 static size_t wxGetNumOfBitmapColors(size_t bitsPerPixel
) 
1156     switch ( bitsPerPixel 
) 
1159             // monochrome bitmap, 2 entries 
1169             // may be used with 24bit bitmaps, but we don't use it here - fall 
1174             // bmiColors not used at all with these bitmaps 
1178             wxFAIL_MSG( wxT("unknown bitmap format") ); 
1183 size_t wxConvertBitmapToDIB(LPBITMAPINFO pbi
, const wxBitmap
& bitmap
) 
1185     wxASSERT_MSG( bitmap
.Ok(), wxT("invalid bmp can't be converted to DIB") ); 
1187     // shouldn't be selected into a DC or GetDIBits() would fail 
1188     wxASSERT_MSG( !bitmap
.GetSelectedInto(), 
1189                   wxT("can't copy bitmap selected into wxMemoryDC") ); 
1191     // prepare all the info we need 
1193     HBITMAP hbmp 
= (HBITMAP
)bitmap
.GetHBITMAP(); 
1194     if ( !GetObject(hbmp
, sizeof(bm
), &bm
) ) 
1196         wxLogLastError(wxT("GetObject(bitmap)")); 
1201     // calculate the number of bits per pixel and the number of items in 
1202     // bmiColors array (whose meaning depends on the bitmap format) 
1203     WORD biBits 
= bm
.bmPlanes 
* bm
.bmBitsPixel
; 
1204     WORD biColors 
= (WORD
)wxGetNumOfBitmapColors(biBits
); 
1208     bool wantSizeOnly 
= pbi 
== NULL
; 
1212     // just for convenience 
1213     BITMAPINFOHEADER
& bi 
= pbi
->bmiHeader
; 
1215     bi
.biSize 
= sizeof(BITMAPINFOHEADER
); 
1216     bi
.biWidth 
= bm
.bmWidth
; 
1217     bi
.biHeight 
= bm
.bmHeight
; 
1219     bi
.biBitCount 
= biBits
; 
1220     bi
.biCompression 
= BI_RGB
; 
1222     bi
.biXPelsPerMeter 
= 0; 
1223     bi
.biYPelsPerMeter 
= 0; 
1225     bi
.biClrImportant 
= 0; 
1227     // memory we need for BITMAPINFO only 
1228     DWORD dwLen 
= bi
.biSize 
+ biColors 
* sizeof(RGBQUAD
); 
1230     // first get the image size 
1232     if ( !GetDIBits(hdc
, hbmp
, 0, bi
.biHeight
, NULL
, pbi
, DIB_RGB_COLORS
) ) 
1234         wxLogLastError(wxT("GetDIBits(NULL)")); 
1241         // size of the header + size of the image 
1242         return dwLen 
+ bi
.biSizeImage
; 
1245     // and now copy the bits 
1246     void *image 
= (char *)pbi 
+ dwLen
; 
1247     if ( !GetDIBits(hdc
, hbmp
, 0, bi
.biHeight
, image
, pbi
, DIB_RGB_COLORS
) ) 
1249         wxLogLastError(wxT("GetDIBits")); 
1254     return dwLen 
+ bi
.biSizeImage
; 
1257 wxBitmap 
wxConvertDIBToBitmap(const LPBITMAPINFO pbmi
) 
1259     // here we get BITMAPINFO struct followed by the actual bitmap bits and 
1260     // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
1261     const BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
1263     // biClrUsed has the number of colors, unless it's 0 
1264     int numColors 
= pbmih
->biClrUsed
; 
1267         numColors 
= wxGetNumOfBitmapColors(pbmih
->biBitCount
); 
1270     // offset of image from the beginning of the header 
1271     DWORD ofs 
= numColors 
* sizeof(RGBQUAD
); 
1272     void *image 
= (char *)pbmih 
+ sizeof(BITMAPINFOHEADER
) + ofs
; 
1275     HBITMAP hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
1276                                   image
, pbmi
, DIB_RGB_COLORS
); 
1279         wxLogLastError(wxT("CreateDIBitmap")); 
1282     wxBitmap 
bitmap(pbmih
->biWidth
, pbmih
->biHeight
, pbmih
->biBitCount
); 
1283     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
1290 static const wxChar 
*GetTymedName(DWORD tymed
) 
1292     static wxChar s_szBuf
[128]; 
1294         case TYMED_HGLOBAL
:   return wxT("TYMED_HGLOBAL"); 
1295         case TYMED_FILE
:      return wxT("TYMED_FILE"); 
1296         case TYMED_ISTREAM
:   return wxT("TYMED_ISTREAM"); 
1297         case TYMED_ISTORAGE
:  return wxT("TYMED_ISTORAGE"); 
1298         case TYMED_GDI
:       return wxT("TYMED_GDI"); 
1299         case TYMED_MFPICT
:    return wxT("TYMED_MFPICT"); 
1300         case TYMED_ENHMF
:     return wxT("TYMED_ENHMF"); 
1302             wxSprintf(s_szBuf
, wxT("type of media format %ld (unknown)"), tymed
); 
1309 #else // not using OLE at all 
1310 // ---------------------------------------------------------------------------- 
1312 // ---------------------------------------------------------------------------- 
1314 wxDataObject::wxDataObject() 
1318 wxDataObject::~wxDataObject() 
1322 void wxDataObject::SetAutoDelete() 
1327 const wxChar 
*wxDataObject::GetFormatName(wxDataFormat format
)