]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/dataobj.cpp
72e6a05a9ce2fc71ca789e622ee6d01a1fb6e5bc
   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__) 
  31 #if defined(__WIN32__) && !defined(__GNUWIN32_OLD__) 
  38 #include "wx/dataobj.h" 
  40 #include "wx/msw/private.h"         // includes <windows.h> 
  42 #ifdef wxUSE_NORLANDER_HEADERS 
  54 #include "wx/msw/ole/oleutils.h" 
  56 #include "wx/msw/dib.h" 
  58 // ---------------------------------------------------------------------------- 
  60 // ---------------------------------------------------------------------------- 
  63     static const wxChar 
*GetTymedName(DWORD tymed
); 
  65     #define GetTymedName(tymed) "" 
  66 #endif // Debug/!Debug 
  68 // ---------------------------------------------------------------------------- 
  69 // wxIEnumFORMATETC interface implementation 
  70 // ---------------------------------------------------------------------------- 
  72 class wxIEnumFORMATETC 
: public IEnumFORMATETC
 
  75     wxIEnumFORMATETC(const wxDataFormat
* formats
, ULONG nCount
); 
  76     ~wxIEnumFORMATETC() { delete [] m_formats
; } 
  78     DECLARE_IUNKNOWN_METHODS
; 
  81     STDMETHODIMP 
Next(ULONG celt
, FORMATETC 
*rgelt
, ULONG 
*pceltFetched
); 
  82     STDMETHODIMP 
Skip(ULONG celt
); 
  84     STDMETHODIMP 
Clone(IEnumFORMATETC 
**ppenum
); 
  87     CLIPFORMAT 
*m_formats
;  // formats we can provide data in 
  88     ULONG       m_nCount
,   // number of formats we support 
  89                 m_nCurrent
; // current enum position 
  92 // ---------------------------------------------------------------------------- 
  93 // wxIDataObject implementation of IDataObject interface 
  94 // ---------------------------------------------------------------------------- 
  96 class wxIDataObject 
: public IDataObject
 
  99     wxIDataObject(wxDataObject 
*pDataObject
); 
 102     // normally, wxDataObject controls our lifetime (i.e. we're deleted when it 
 103     // is), but in some cases, the situation is inversed, that is we delete it 
 104     // when this object is deleted - setting this flag enables such logic 
 105     void SetDeleteFlag() { m_mustDelete 
= TRUE
; } 
 107     DECLARE_IUNKNOWN_METHODS
; 
 110     STDMETHODIMP 
GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
); 
 111     STDMETHODIMP 
GetDataHere(FORMATETC 
*pformatetc
, STGMEDIUM 
*pmedium
); 
 112     STDMETHODIMP 
QueryGetData(FORMATETC 
*pformatetc
); 
 113     STDMETHODIMP 
GetCanonicalFormatEtc(FORMATETC 
*In
, FORMATETC 
*pOut
); 
 114     STDMETHODIMP 
SetData(FORMATETC 
*pfetc
, STGMEDIUM 
*pmedium
, BOOL fRelease
); 
 115     STDMETHODIMP 
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC 
**ppenumFEtc
); 
 116     STDMETHODIMP 
DAdvise(FORMATETC 
*pfetc
, DWORD ad
, IAdviseSink 
*p
, DWORD 
*pdw
); 
 117     STDMETHODIMP 
DUnadvise(DWORD dwConnection
); 
 118     STDMETHODIMP 
EnumDAdvise(IEnumSTATDATA 
**ppenumAdvise
); 
 121     wxDataObject 
*m_pDataObject
;      // pointer to C++ class we belong to 
 126 // ============================================================================ 
 128 // ============================================================================ 
 130 // ---------------------------------------------------------------------------- 
 132 // ---------------------------------------------------------------------------- 
 134 void wxDataFormat::SetId(const wxChar 
*format
) 
 136     m_format 
= ::RegisterClipboardFormat(format
); 
 139         wxLogError(_("Couldn't register clipboard format '%s'."), format
); 
 143 wxString 
wxDataFormat::GetId() const 
 145     static const int max 
= 256; 
 149     wxCHECK_MSG( !IsStandard(), s
, 
 150                  wxT("name of predefined format cannot be retrieved") ); 
 152     int len 
= ::GetClipboardFormatName(m_format
, s
.GetWriteBuf(max
), max
); 
 157         wxLogError(_("The clipboard format '%d' doesn't exist."), m_format
); 
 163 // ---------------------------------------------------------------------------- 
 165 // ---------------------------------------------------------------------------- 
 167 BEGIN_IID_TABLE(wxIEnumFORMATETC
) 
 169     ADD_IID(EnumFORMATETC
) 
 172 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC
) 
 174 wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat 
*formats
, ULONG nCount
) 
 179     m_formats 
= new CLIPFORMAT
[nCount
]; 
 180     for ( ULONG n 
= 0; n 
< nCount
; n
++ ) { 
 181         m_formats
[n
] = formats
[n
].GetFormatId(); 
 185 STDMETHODIMP 
wxIEnumFORMATETC::Next(ULONG      celt
, 
 189     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Next")); 
 192         // we only return 1 element at a time - mainly because I'm too lazy to 
 193         // implement something which you're never asked for anyhow 
 197     if ( m_nCurrent 
< m_nCount 
) { 
 199         format
.cfFormat 
= m_formats
[m_nCurrent
++]; 
 201         format
.dwAspect 
= DVASPECT_CONTENT
; 
 203         format
.tymed    
= TYMED_HGLOBAL
; 
 214 STDMETHODIMP 
wxIEnumFORMATETC::Skip(ULONG celt
) 
 216     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Skip")); 
 219     if ( m_nCurrent 
< m_nCount 
) 
 222     // no, can't skip this many elements 
 228 STDMETHODIMP 
wxIEnumFORMATETC::Reset() 
 230     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Reset")); 
 237 STDMETHODIMP 
wxIEnumFORMATETC::Clone(IEnumFORMATETC 
**ppenum
) 
 239     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIEnumFORMATETC::Clone")); 
 241     // unfortunately, we can't reuse the code in ctor - types are different 
 242     wxIEnumFORMATETC 
*pNew 
= new wxIEnumFORMATETC(NULL
, 0); 
 243     pNew
->m_nCount 
= m_nCount
; 
 244     pNew
->m_formats 
= new CLIPFORMAT
[m_nCount
]; 
 245     for ( ULONG n 
= 0; n 
< m_nCount
; n
++ ) { 
 246         pNew
->m_formats
[n
] = m_formats
[n
]; 
 254 // ---------------------------------------------------------------------------- 
 256 // ---------------------------------------------------------------------------- 
 258 BEGIN_IID_TABLE(wxIDataObject
) 
 263 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject
) 
 265 wxIDataObject::wxIDataObject(wxDataObject 
*pDataObject
) 
 268     m_pDataObject 
= pDataObject
; 
 269     m_mustDelete 
= FALSE
; 
 272 wxIDataObject::~wxIDataObject() 
 276         delete m_pDataObject
; 
 280 // get data functions 
 281 STDMETHODIMP 
wxIDataObject::GetData(FORMATETC 
*pformatetcIn
, STGMEDIUM 
*pmedium
) 
 283     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetData")); 
 285     // is data is in our format? 
 286     HRESULT hr 
= QueryGetData(pformatetcIn
); 
 290     // for the bitmaps and metafiles we use the handles instead of global memory 
 292     wxDataFormat format 
= (wxDataFormatId
)pformatetcIn
->cfFormat
; 
 297             pmedium
->tymed 
= TYMED_GDI
; 
 301             pmedium
->tymed 
= TYMED_MFPICT
; 
 306             size_t size 
= m_pDataObject
->GetDataSize(format
); 
 308                 // it probably means that the method is just not implemented 
 309                 wxLogDebug(wxT("Invalid data size - can't be 0")); 
 311                 return DV_E_FORMATETC
; 
 314             if ( !format
.IsStandard() ) { 
 315                 // for custom formats, put the size with the data - alloc the 
 317                 size 
+= sizeof(size_t); 
 320             HGLOBAL hGlobal 
= GlobalAlloc(GMEM_MOVEABLE 
| GMEM_SHARE
, size
); 
 321             if ( hGlobal 
== NULL 
) { 
 322                 wxLogLastError("GlobalAlloc"); 
 323                 return E_OUTOFMEMORY
; 
 327             pmedium
->tymed   
= TYMED_HGLOBAL
; 
 328             pmedium
->hGlobal 
= hGlobal
; 
 331     pmedium
->pUnkForRelease 
= NULL
; 
 334     hr 
= GetDataHere(pformatetcIn
, pmedium
); 
 336         // free resources we allocated 
 337         if ( pmedium
->tymed 
== TYMED_HGLOBAL 
) { 
 338             GlobalFree(pmedium
->hGlobal
); 
 347 STDMETHODIMP 
wxIDataObject::GetDataHere(FORMATETC 
*pformatetc
, 
 350     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetDataHere")); 
 352     // put data in caller provided medium 
 353     switch ( pmedium
->tymed 
) 
 356             if ( !m_pDataObject
->GetDataHere(wxDF_BITMAP
, &pmedium
->hBitmap
) ) 
 361             // this should be copied on bitmaps - but I don't have time for 
 363             wxFAIL_MSG(wxT("TODO - no support for metafiles in wxDataObject")); 
 369                 HGLOBAL hGlobal 
= pmedium
->hGlobal
; 
 370                 void *pBuf 
= GlobalLock(hGlobal
); 
 371                 if ( pBuf 
== NULL 
) { 
 372                     wxLogLastError(wxT("GlobalLock")); 
 373                     return E_OUTOFMEMORY
; 
 376                 if ( !wxDataFormat(pformatetc
->cfFormat
).IsStandard() ) { 
 377                     // for custom formats, put the size with the data 
 378                     size_t *p 
= (size_t *)pBuf
; 
 379                     *p
++ = GlobalSize(hGlobal
); 
 383                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 384                 if ( !m_pDataObject
->GetDataHere(format
, pBuf
) ) 
 387                 GlobalUnlock(hGlobal
); 
 398 // set data functions 
 399 STDMETHODIMP 
wxIDataObject::SetData(FORMATETC 
*pformatetc
, 
 403     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::SetData")); 
 405     switch ( pmedium
->tymed 
) 
 408             m_pDataObject
->SetData(wxDF_BITMAP
, 0, &pmedium
->hBitmap
); 
 412             // this should be copied on bitmaps - but I don't have time for 
 414             wxFAIL_MSG(wxT("TODO - no support for metafiles in wxDataObject")); 
 419                 wxDataFormat format 
= pformatetc
->cfFormat
; 
 421                 // this is quite weird, but for file drag and drop, explorer 
 422                 // calls our SetData() with the formats we do *not* support! 
 424                 // as we can't fix this bug in explorer (it's a bug because it 
 425                 // should only use formats returned by EnumFormatEtc), do the 
 427                 if ( !m_pDataObject
->IsSupportedFormat(format
) ) { 
 429                     return DV_E_FORMATETC
; 
 433                 void *pBuf 
= GlobalLock(pmedium
->hGlobal
); 
 434                 if ( pBuf 
== NULL 
) { 
 435                     wxLogLastError("GlobalLock"); 
 437                     return E_OUTOFMEMORY
; 
 440                 // we've got a problem with SetData() here because the base 
 441                 // class version requires the size parameter which we don't 
 442                 // have anywhere in OLE data transfer - so we need to 
 443                 // synthetise it for known formats and we suppose that all data 
 444                 // in custom formats starts with a DWORD containing the size 
 450                         size 
= strlen((const char *)pBuf
); 
 454                         size 
= wcslen((const wchar_t *)pBuf
); 
 459                         // these formats don't use size at all, anyhow (but 
 460                         // pass data by handle, which is always a single DWORD) 
 465                         // the handler will calculate size itself (it's too 
 466                         // complicated to do it here) 
 472                             // we suppose that the size precedes the data 
 473                             size_t *p 
= (size_t *)pBuf
; 
 479                 bool ok 
= m_pDataObject
->SetData(format
, size
, pBuf
); 
 481                 GlobalUnlock(pmedium
->hGlobal
); 
 494         // we own the medium, so we must release it - but do *not* free the 
 495         // bitmap handle fi we have it because we have copied it elsewhere 
 496         if ( pmedium
->tymed 
== TYMED_GDI 
) 
 498             pmedium
->hBitmap 
= 0; 
 501         ReleaseStgMedium(pmedium
); 
 507 // information functions 
 508 STDMETHODIMP 
wxIDataObject::QueryGetData(FORMATETC 
*pformatetc
) 
 510     // do we accept data in this format? 
 511     if ( pformatetc 
== NULL 
) { 
 512         wxLogTrace(wxTRACE_OleCalls
, 
 513                    wxT("wxIDataObject::QueryGetData: invalid ptr.")); 
 518     // the only one allowed by current COM implementation 
 519     if ( pformatetc
->lindex 
!= -1 ) { 
 520         wxLogTrace(wxTRACE_OleCalls
, 
 521                    wxT("wxIDataObject::QueryGetData: bad lindex %d"), 
 527     // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...) 
 528     if ( pformatetc
->dwAspect 
!= DVASPECT_CONTENT 
) { 
 529         wxLogTrace(wxTRACE_OleCalls
, 
 530                    wxT("wxIDataObject::QueryGetData: bad dwAspect %d"), 
 531                    pformatetc
->dwAspect
); 
 533         return DV_E_DVASPECT
; 
 536     // and now check the type of data requested 
 537     wxDataFormat format 
= pformatetc
->cfFormat
; 
 538     if ( m_pDataObject
->IsSupportedFormat(format
) ) { 
 539         wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::QueryGetData: %s ok"), 
 540                    wxGetFormatName(format
)); 
 543         wxLogTrace(wxTRACE_OleCalls
, 
 544                    wxT("wxIDataObject::QueryGetData: %s unsupported"), 
 545                    wxGetFormatName(format
)); 
 547         return DV_E_FORMATETC
; 
 550     // we only transfer data by global memory, except for some particular cases 
 551     DWORD tymed 
= pformatetc
->tymed
; 
 552     if ( (format 
== wxDF_BITMAP 
&& !(tymed 
& TYMED_GDI
)) && 
 553          !(tymed 
& TYMED_HGLOBAL
) ) { 
 554         // it's not what we're waiting for 
 555         wxLogTrace(wxTRACE_OleCalls
, 
 556                    wxT("wxIDataObject::QueryGetData: %s != %s"), 
 558                    GetTymedName(format 
== wxDF_BITMAP 
? TYMED_GDI
 
 567 STDMETHODIMP 
wxIDataObject::GetCanonicalFormatEtc(FORMATETC 
*pFormatetcIn
, 
 568                                                   FORMATETC 
*pFormatetcOut
) 
 570     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::GetCanonicalFormatEtc")); 
 572     // TODO we might want something better than this trivial implementation here 
 573     if ( pFormatetcOut 
!= NULL 
) 
 574         pFormatetcOut
->ptd 
= NULL
; 
 576     return DATA_S_SAMEFORMATETC
; 
 579 STDMETHODIMP 
wxIDataObject::EnumFormatEtc(DWORD dwDir
, 
 580                                           IEnumFORMATETC 
**ppenumFormatEtc
) 
 582     wxLogTrace(wxTRACE_OleCalls
, wxT("wxIDataObject::EnumFormatEtc")); 
 584     wxDataObject::Direction dir 
= dwDir 
== DATADIR_GET 
? wxDataObject::Get
 
 587     size_t nFormatCount 
= m_pDataObject
->GetFormatCount(dir
); 
 588     wxDataFormat format
, *formats
; 
 589     formats 
= nFormatCount 
== 1 ? &format 
: new wxDataFormat
[nFormatCount
]; 
 590     m_pDataObject
->GetAllFormats(formats
, dir
); 
 592     wxIEnumFORMATETC 
*pEnum 
= new wxIEnumFORMATETC(formats
, nFormatCount
); 
 594     *ppenumFormatEtc 
= pEnum
; 
 596     if ( formats 
!= &format 
) { 
 603 // ---------------------------------------------------------------------------- 
 604 // advise sink functions (not implemented) 
 605 // ---------------------------------------------------------------------------- 
 607 STDMETHODIMP 
wxIDataObject::DAdvise(FORMATETC   
*pformatetc
, 
 609                                     IAdviseSink 
*pAdvSink
, 
 610                                     DWORD       
*pdwConnection
) 
 612   return OLE_E_ADVISENOTSUPPORTED
; 
 615 STDMETHODIMP 
wxIDataObject::DUnadvise(DWORD dwConnection
) 
 617   return OLE_E_ADVISENOTSUPPORTED
; 
 620 STDMETHODIMP 
wxIDataObject::EnumDAdvise(IEnumSTATDATA 
**ppenumAdvise
) 
 622   return OLE_E_ADVISENOTSUPPORTED
; 
 625 // ---------------------------------------------------------------------------- 
 627 // ---------------------------------------------------------------------------- 
 629 wxDataObject::wxDataObject() 
 631     m_pIDataObject 
= new wxIDataObject(this); 
 632     m_pIDataObject
->AddRef(); 
 635 wxDataObject::~wxDataObject() 
 637     ReleaseInterface(m_pIDataObject
); 
 640 void wxDataObject::SetAutoDelete() 
 642     ((wxIDataObject 
*)m_pIDataObject
)->SetDeleteFlag(); 
 643     m_pIDataObject
->Release(); 
 645     // so that the dtor doesnt' crash 
 646     m_pIDataObject 
= NULL
; 
 649 bool wxDataObject::IsSupportedFormat(const wxDataFormat
& format
) const 
 651     size_t nFormatCount 
= GetFormatCount(); 
 652     if ( nFormatCount 
== 1 ) { 
 653         return format 
== GetPreferredFormat(); 
 656         wxDataFormat 
*formats 
= new wxDataFormat
[nFormatCount
]; 
 657         GetAllFormats(formats
); 
 660         for ( n 
= 0; n 
< nFormatCount
; n
++ ) { 
 661             if ( formats
[n
] == format 
) 
 668         return n 
< nFormatCount
; 
 674 const char *wxDataObject::GetFormatName(wxDataFormat format
) 
 676   // case 'xxx' is not a valid value for switch of enum 'wxDataFormat' 
 678     #pragma warning(disable:4063) 
 681   static char s_szBuf
[128]; 
 683     case CF_TEXT
:         return "CF_TEXT"; 
 684     case CF_BITMAP
:       return "CF_BITMAP"; 
 685     case CF_METAFILEPICT
: return "CF_METAFILEPICT"; 
 686     case CF_SYLK
:         return "CF_SYLK"; 
 687     case CF_DIF
:          return "CF_DIF"; 
 688     case CF_TIFF
:         return "CF_TIFF"; 
 689     case CF_OEMTEXT
:      return "CF_OEMTEXT"; 
 690     case CF_DIB
:          return "CF_DIB"; 
 691     case CF_PALETTE
:      return "CF_PALETTE"; 
 692     case CF_PENDATA
:      return "CF_PENDATA"; 
 693     case CF_RIFF
:         return "CF_RIFF"; 
 694     case CF_WAVE
:         return "CF_WAVE"; 
 695     case CF_UNICODETEXT
:  return "CF_UNICODETEXT"; 
 696     case CF_ENHMETAFILE
:  return "CF_ENHMETAFILE"; 
 697     case CF_HDROP
:        return "CF_HDROP"; 
 698     case CF_LOCALE
:       return "CF_LOCALE"; 
 700       sprintf(s_szBuf
, "clipboard format 0x%x (unknown)", format
); 
 705     #pragma warning(default:4063) 
 711 // ---------------------------------------------------------------------------- 
 712 // wxBitmapDataObject supports CF_DIB format 
 713 // ---------------------------------------------------------------------------- 
 715 size_t wxBitmapDataObject::GetDataSize() const 
 717     return wxConvertBitmapToDIB(NULL
, GetBitmap()); 
 720 bool wxBitmapDataObject::GetDataHere(void *buf
) const 
 722     return wxConvertBitmapToDIB((LPBITMAPINFO
)buf
, GetBitmap()) != 0; 
 725 bool wxBitmapDataObject::SetData(size_t len
, const void *buf
) 
 727     wxBitmap 
bitmap(wxConvertDIBToBitmap((const LPBITMAPINFO
)buf
)); 
 729     if ( !bitmap
.Ok() ) { 
 730         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 740 // ---------------------------------------------------------------------------- 
 741 // wxBitmapDataObject2 supports CF_BITMAP format 
 742 // ---------------------------------------------------------------------------- 
 744 // the bitmaps aren't passed by value as other types of data (i.e. by copying 
 745 // the data into a global memory chunk and passing it to the clipboard or 
 746 // another application or whatever), but by handle, so these generic functions 
 747 // don't make much sense to them. 
 749 size_t wxBitmapDataObject2::GetDataSize() const 
 754 bool wxBitmapDataObject2::GetDataHere(void *pBuf
) const 
 756     // we put a bitmap handle into pBuf 
 757     *(WXHBITMAP 
*)pBuf 
= GetBitmap().GetHBITMAP(); 
 762 bool wxBitmapDataObject2::SetData(size_t len
, const void *pBuf
) 
 764     HBITMAP hbmp 
= *(HBITMAP 
*)pBuf
; 
 767     if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 769         wxLogLastError("GetObject(HBITMAP)"); 
 772     wxBitmap 
bitmap(bmp
.bmWidth
, bmp
.bmHeight
, bmp
.bmPlanes
); 
 773     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 775     if ( !bitmap
.Ok() ) { 
 776         wxFAIL_MSG(wxT("pasting/dropping invalid bitmap")); 
 788 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat
& format
) const 
 790     if ( format
.GetFormatId() == CF_DIB 
) 
 795         // shouldn't be selected into a DC or GetDIBits() would fail 
 796         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 797                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 799         // first get the info 
 801         if ( !GetDIBits(hdc
, (HBITMAP
)m_bitmap
.GetHBITMAP(), 0, 0, 
 802                         NULL
, &bi
, DIB_RGB_COLORS
) ) 
 804             wxLogLastError("GetDIBits(NULL)"); 
 809         return sizeof(BITMAPINFO
) + bi
.bmiHeader
.biSizeImage
; 
 813         // no data to copy - we don't pass HBITMAP via global memory 
 818 bool wxBitmapDataObject::GetDataHere(const wxDataFormat
& format
, 
 821     wxASSERT_MSG( m_bitmap
.Ok(), wxT("copying invalid bitmap") ); 
 823     HBITMAP hbmp 
= (HBITMAP
)m_bitmap
.GetHBITMAP(); 
 824     if ( format
.GetFormatId() == CF_DIB 
) 
 829         // shouldn't be selected into a DC or GetDIBits() would fail 
 830         wxASSERT_MSG( !m_bitmap
.GetSelectedInto(), 
 831                       wxT("can't copy bitmap selected into wxMemoryDC") ); 
 833         // first get the info 
 834         BITMAPINFO 
*pbi 
= (BITMAPINFO 
*)pBuf
; 
 835         if ( !GetDIBits(hdc
, hbmp
, 0, 0, NULL
, pbi
, DIB_RGB_COLORS
) ) 
 837             wxLogLastError("GetDIBits(NULL)"); 
 842         // and now copy the bits 
 843         if ( !GetDIBits(hdc
, hbmp
, 0, pbi
->bmiHeader
.biHeight
, pbi 
+ 1, 
 844                         pbi
, DIB_RGB_COLORS
) ) 
 846             wxLogLastError("GetDIBits"); 
 853         // we put a bitmap handle into pBuf 
 854         *(HBITMAP 
*)pBuf 
= hbmp
; 
 860 bool wxBitmapDataObject::SetData(const wxDataFormat
& format
, 
 861                                  size_t size
, const void *pBuf
) 
 864     if ( format
.GetFormatId() == CF_DIB 
) 
 866         // here we get BITMAPINFO struct followed by the actual bitmap bits and 
 867         // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
 870         BITMAPINFO 
*pbmi 
= (BITMAPINFO 
*)pBuf
; 
 871         BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
 872         hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
 873                               pbmi 
+ 1, pbmi
, DIB_RGB_COLORS
); 
 876             wxLogLastError("CreateDIBitmap"); 
 879         m_bitmap
.SetWidth(pbmih
->biWidth
); 
 880         m_bitmap
.SetHeight(pbmih
->biHeight
); 
 884         // it's easy with bitmaps: we pass them by handle 
 885         hbmp 
= *(HBITMAP 
*)pBuf
; 
 888         if ( !GetObject(hbmp
, sizeof(BITMAP
), &bmp
) ) 
 890             wxLogLastError("GetObject(HBITMAP)"); 
 893         m_bitmap
.SetWidth(bmp
.bmWidth
); 
 894         m_bitmap
.SetHeight(bmp
.bmHeight
); 
 895         m_bitmap
.SetDepth(bmp
.bmPlanes
); 
 898     m_bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
 900     wxASSERT_MSG( m_bitmap
.Ok(), wxT("pasting invalid bitmap") ); 
 907 // ---------------------------------------------------------------------------- 
 909 // ---------------------------------------------------------------------------- 
 911 bool wxFileDataObject::SetData(size_t WXUNUSED(size
), const void *pData
) 
 915     // the documentation states that the first member of DROPFILES structure is 
 916     // a "DWORD offset of double NUL terminated file list". What they mean by 
 917     // this (I wonder if you see it immediately) is that the list starts at 
 918     // ((char *)&(pDropFiles.pFiles)) + pDropFiles.pFiles. We're also advised 
 919     // to use DragQueryFile to work with this structure, but not told where and 
 921     HDROP hdrop 
= (HDROP
)pData
;   // NB: it works, but I'm not sure about it 
 923     // get number of files (magic value -1) 
 924     UINT nFiles 
= ::DragQueryFile(hdrop
, (unsigned)-1, NULL
, 0u); 
 926     wxCHECK_MSG ( nFiles 
!= (UINT
)-1, FALSE
, wxT("wrong HDROP handle") ); 
 928     // for each file get the length, allocate memory and then get the name 
 931     for ( n 
= 0; n 
< nFiles
; n
++ ) { 
 932         // +1 for terminating NUL 
 933         len 
= ::DragQueryFile(hdrop
, n
, NULL
, 0) + 1; 
 935         UINT len2 
= ::DragQueryFile(hdrop
, n
, str
.GetWriteBuf(len
), len
); 
 937         m_filenames
.Add(str
); 
 939         if ( len2 
!= len 
- 1 ) { 
 940             wxLogDebug(wxT("In wxFileDropTarget::OnDrop DragQueryFile returned" 
 941                            " %d characters, %d expected."), len2
, len 
- 1); 
 948 void wxFileDataObject::AddFile(const wxString
& file
) 
 950     // just add file to filenames array 
 951     // all useful data (such as DROPFILES struct) will be 
 952     // created later as necessary 
 953     m_filenames
.Add(file
); 
 956 size_t wxFileDataObject::GetDataSize() const 
 958     // size returned will be the size of the DROPFILES structure, 
 959     // plus the list of filesnames (null byte separated), plus 
 960     // a double null at the end 
 962     // if no filenames in list, size is 0 
 963     if ( m_filenames
.GetCount() == 0 ) 
 966     // inital size of DROPFILES struct + null byte 
 967     size_t sz 
= sizeof(DROPFILES
) + 1; 
 969     size_t count 
= m_filenames
.GetCount(); 
 970     for ( size_t i 
= 0; i 
< count
; i
++ ) 
 972         // add filename length plus null byte 
 973         sz 
+= m_filenames
[i
].Len() + 1; 
 979 bool wxFileDataObject::GetDataHere(void *pData
) const 
 981     // pData points to an externally allocated memory block 
 982     // created using the size returned by GetDataSize() 
 984     // if pData is NULL, or there are no files, return 
 985     if ( !pData 
|| m_filenames
.GetCount() == 0 ) 
 988     // convert data pointer to a DROPFILES struct pointer 
 989     LPDROPFILES pDrop 
= (LPDROPFILES
) pData
; 
 991     // initialize DROPFILES struct 
 992     pDrop
->pFiles 
= sizeof(DROPFILES
); 
 993     pDrop
->fNC 
= FALSE
;                 // not non-client coords 
 997     pDrop
->fWide 
= FALSE
; 
 998 #endif // Unicode/Ansi 
1000     // set start of filenames list (null separated) 
1001     wxChar 
*pbuf 
= (wxChar
*) ((BYTE 
*)pDrop 
+ sizeof(DROPFILES
)); 
1003     size_t count 
= m_filenames
.GetCount(); 
1004     for (size_t i 
= 0; i 
< count
; i
++ ) 
1006         // copy filename to pbuf and add null terminator 
1007         size_t len 
= m_filenames
[i
].Len(); 
1008         memcpy(pbuf
, m_filenames
[i
], len
); 
1010         *pbuf
++ = wxT('\0'); 
1013     *pbuf 
= wxT('\0');  // add final null terminator 
1018 // ---------------------------------------------------------------------------- 
1019 // private functions 
1020 // ---------------------------------------------------------------------------- 
1022 static size_t wxGetNumOfBitmapColors(size_t bitsPerPixel
) 
1024     switch ( bitsPerPixel 
) 
1027             // monochrome bitmap, 2 entries 
1037             // may be used with 24bit bitmaps, but we don't use it here - fall 
1042             // bmiColors not used at all with these bitmaps 
1046             wxFAIL_MSG( wxT("unknown bitmap format") ); 
1051 size_t wxConvertBitmapToDIB(LPBITMAPINFO pbi
, const wxBitmap
& bitmap
) 
1053     wxASSERT_MSG( bitmap
.Ok(), wxT("invalid bmp can't be converted to DIB") ); 
1055     // shouldn't be selected into a DC or GetDIBits() would fail 
1056     wxASSERT_MSG( !bitmap
.GetSelectedInto(), 
1057                   wxT("can't copy bitmap selected into wxMemoryDC") ); 
1059     // prepare all the info we need 
1061     HBITMAP hbmp 
= (HBITMAP
)bitmap
.GetHBITMAP(); 
1062     if ( !GetObject(hbmp
, sizeof(bm
), &bm
) ) 
1064         wxLogLastError("GetObject(bitmap)"); 
1069     // calculate the number of bits per pixel and the number of items in 
1070     // bmiColors array (whose meaning depends on the bitmap format) 
1071     WORD biBits 
= bm
.bmPlanes 
* bm
.bmBitsPixel
; 
1072     WORD biColors 
= wxGetNumOfBitmapColors(biBits
); 
1076     bool wantSizeOnly 
= pbi 
== NULL
; 
1080     // just for convenience 
1081     BITMAPINFOHEADER
& bi 
= pbi
->bmiHeader
; 
1083     bi
.biSize 
= sizeof(BITMAPINFOHEADER
); 
1084     bi
.biWidth 
= bm
.bmWidth
; 
1085     bi
.biHeight 
= bm
.bmHeight
; 
1087     bi
.biBitCount 
= biBits
; 
1088     bi
.biCompression 
= BI_RGB
; 
1090     bi
.biXPelsPerMeter 
= 0; 
1091     bi
.biYPelsPerMeter 
= 0; 
1093     bi
.biClrImportant 
= 0; 
1095     // memory we need for BITMAPINFO only 
1096     DWORD dwLen 
= bi
.biSize 
+ biColors 
* sizeof(RGBQUAD
); 
1098     // first get the image size 
1100     if ( !GetDIBits(hdc
, hbmp
, 0, bi
.biHeight
, NULL
, pbi
, DIB_RGB_COLORS
) ) 
1102         wxLogLastError("GetDIBits(NULL)"); 
1109         // size of the header + size of the image 
1110         return dwLen 
+ bi
.biSizeImage
; 
1113     // and now copy the bits 
1114     void *image 
= (char *)pbi 
+ dwLen
; 
1115     if ( !GetDIBits(hdc
, hbmp
, 0, bi
.biHeight
, image
, pbi
, DIB_RGB_COLORS
) ) 
1117         wxLogLastError("GetDIBits"); 
1122     return dwLen 
+ bi
.biSizeImage
; 
1125 wxBitmap 
wxConvertDIBToBitmap(const LPBITMAPINFO pbmi
) 
1127     // here we get BITMAPINFO struct followed by the actual bitmap bits and 
1128     // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info 
1129     const BITMAPINFOHEADER 
*pbmih 
= &pbmi
->bmiHeader
; 
1131     // offset of image from the beginning of the header 
1132     DWORD ofs 
= wxGetNumOfBitmapColors(pbmih
->biBitCount
) * sizeof(RGBQUAD
); 
1133     void *image 
= (char *)pbmih 
+ sizeof(BITMAPINFOHEADER
) + ofs
; 
1136     HBITMAP hbmp 
= CreateDIBitmap(hdc
, pbmih
, CBM_INIT
, 
1137                                   image
, pbmi
, DIB_RGB_COLORS
); 
1140         wxLogLastError("CreateDIBitmap"); 
1143     wxBitmap 
bitmap(pbmih
->biWidth
, pbmih
->biHeight
, pbmih
->biBitCount
); 
1144     bitmap
.SetHBITMAP((WXHBITMAP
)hbmp
); 
1151 static const wxChar 
*GetTymedName(DWORD tymed
) 
1153     static wxChar s_szBuf
[128]; 
1155         case TYMED_HGLOBAL
:   return wxT("TYMED_HGLOBAL"); 
1156         case TYMED_FILE
:      return wxT("TYMED_FILE"); 
1157         case TYMED_ISTREAM
:   return wxT("TYMED_ISTREAM"); 
1158         case TYMED_ISTORAGE
:  return wxT("TYMED_ISTORAGE"); 
1159         case TYMED_GDI
:       return wxT("TYMED_GDI"); 
1160         case TYMED_MFPICT
:    return wxT("TYMED_MFPICT"); 
1161         case TYMED_ENHMF
:     return wxT("TYMED_ENHMF"); 
1163             wxSprintf(s_szBuf
, wxT("type of media format %d (unknown)"), tymed
); 
1170 #endif // not using OLE at all