1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Clipboard functionality 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  21     #pragma implementation "clipbrd.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  38     #include "wx/object.h" 
  42     #include "wx/bitmap.h" 
  48     #include "wx/metafile.h" 
  52 #include "wx/clipbrd.h" 
  57 #include "wx/msw/private.h" 
  58 #include "wx/msw/dib.h" 
  60 // wxDataObject is tied to OLE/drag and drop implementation, therefore so are 
  61 // the functions using wxDataObject in wxClipboard 
  62 #define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP 
  65     #include "wx/dataobj.h" 
  68     #define wxUSE_OLE_CLIPBOARD 1 
  69 #else // !wxUSE_DATAOBJ 
  70     // use Win clipboard API 
  71     #define wxUSE_OLE_CLIPBOARD 0 
  74 #if wxUSE_OLE_CLIPBOARD 
  76 #endif // wxUSE_OLE_CLIPBOARD 
  79     #define memcpy hmemcpy 
  82 // =========================================================================== 
  84 // =========================================================================== 
  86 // --------------------------------------------------------------------------- 
  87 // old-style clipboard functions using Windows API 
  88 // --------------------------------------------------------------------------- 
  90 static bool gs_wxClipboardIsOpen 
= FALSE
; 
  92 bool wxOpenClipboard() 
  94     wxCHECK_MSG( !gs_wxClipboardIsOpen
, TRUE
, wxT("clipboard already opened.") ); 
  96     wxWindow 
*win 
= wxTheApp
->GetTopWindow(); 
  99         gs_wxClipboardIsOpen 
= ::OpenClipboard((HWND
)win
->GetHWND()) != 0; 
 101         if ( !gs_wxClipboardIsOpen 
) 
 102             wxLogSysError(_("Failed to open the clipboard.")); 
 104         return gs_wxClipboardIsOpen
; 
 108         wxLogDebug(wxT("Can not open clipboard without a main window.")); 
 114 bool wxCloseClipboard() 
 116     wxCHECK_MSG( gs_wxClipboardIsOpen
, FALSE
, wxT("clipboard is not opened") ); 
 118     gs_wxClipboardIsOpen 
= FALSE
; 
 120     if ( ::CloseClipboard() == 0 ) 
 122         wxLogSysError(_("Failed to close the clipboard.")); 
 130 bool wxEmptyClipboard() 
 132     if ( ::EmptyClipboard() == 0 ) 
 134         wxLogSysError(_("Failed to empty the clipboard.")); 
 142 bool wxIsClipboardOpened() 
 144   return gs_wxClipboardIsOpen
; 
 147 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat
) 
 149     // for bitmaps, DIBs will also do 
 150     return (::IsClipboardFormatAvailable(dataFormat
) != 0) || 
 151            (dataFormat
.GetFormatId() == CF_BITMAP 
&& 
 152             ::IsClipboardFormatAvailable(CF_DIB
)); 
 155 bool wxSetClipboardData(wxDataFormat dataFormat
, 
 157                         int width
, int height
) 
 159     HANDLE handle 
= 0; // return value of SetClipboardData 
 165                 wxBitmap 
*bitmap 
= (wxBitmap 
*)data
; 
 167                 HDC hdcMem 
= CreateCompatibleDC((HDC
) NULL
); 
 168                 HDC hdcSrc 
= CreateCompatibleDC((HDC
) NULL
); 
 169                 HBITMAP old 
= (HBITMAP
) 
 170                     ::SelectObject(hdcSrc
, (HBITMAP
)bitmap
->GetHBITMAP()); 
 171                 HBITMAP hBitmap 
= CreateCompatibleBitmap(hdcSrc
, 
 173                                                          bitmap
->GetHeight()); 
 176                     SelectObject(hdcSrc
, old
); 
 182                 HBITMAP old1 
= (HBITMAP
) SelectObject(hdcMem
, hBitmap
); 
 183                 BitBlt(hdcMem
, 0, 0, bitmap
->GetWidth(), bitmap
->GetHeight(), 
 184                        hdcSrc
, 0, 0, SRCCOPY
); 
 186                 // Select new bitmap out of memory DC 
 187                 SelectObject(hdcMem
, old1
); 
 190                 handle 
= ::SetClipboardData(CF_BITMAP
, hBitmap
); 
 193                 SelectObject(hdcSrc
, old
); 
 201 #if wxUSE_IMAGE_LOADING_IN_MSW 
 202                 wxBitmap 
*bitmap 
= (wxBitmap 
*)data
; 
 203                 HBITMAP hBitmap 
= (HBITMAP
)bitmap
->GetHBITMAP(); 
 204                 // NULL palette means to use the system one 
 205                 HANDLE hDIB 
= wxBitmapToDIB(hBitmap
, (HPALETTE
)NULL
);  
 206                 handle 
= SetClipboardData(CF_DIB
, hDIB
); 
 207 #endif // wxUSE_IMAGE_LOADING_IN_MSW 
 214                 wxMetafile 
*wxMF 
= (wxMetafile 
*)data
; 
 215                 HANDLE data 
= GlobalAlloc(GHND
, sizeof(METAFILEPICT
) + 1); 
 216                 METAFILEPICT 
*mf 
= (METAFILEPICT 
*)GlobalLock(data
); 
 218                 mf
->mm 
= wxMF
->GetWindowsMappingMode(); 
 221                 mf
->hMF 
= (HMETAFILE
) wxMF
->GetHMETAFILE(); 
 223                 wxMF
->SetHMETAFILE((WXHANDLE
) NULL
); 
 225                 handle 
= SetClipboardData(CF_METAFILEPICT
, data
); 
 235                 wxLogError(_("Unsupported clipboard format.")); 
 240             dataFormat 
= wxDF_TEXT
; 
 245                 char *s 
= (char *)data
; 
 247                 width 
= strlen(s
) + 1; 
 249                 DWORD l 
= (width 
* height
); 
 250                 HANDLE hGlobalMemory 
= GlobalAlloc(GHND
, l
); 
 253                     LPSTR lpGlobalMemory 
= (LPSTR
)GlobalLock(hGlobalMemory
); 
 255                     memcpy(lpGlobalMemory
, s
, l
); 
 257                     GlobalUnlock(hGlobalMemory
); 
 260                 handle 
= SetClipboardData(dataFormat
, hGlobalMemory
); 
 267         wxLogSysError(_("Failed to set clipboard data.")); 
 275 void *wxGetClipboardData(wxDataFormat dataFormat
, long *len
) 
 279     switch ( dataFormat 
) 
 284                 HBITMAP hBitmap 
= (HBITMAP
) GetClipboardData(CF_BITMAP
); 
 288                 HDC hdcMem 
= CreateCompatibleDC((HDC
) NULL
); 
 289                 HDC hdcSrc 
= CreateCompatibleDC((HDC
) NULL
); 
 291                 HBITMAP old 
= (HBITMAP
) ::SelectObject(hdcSrc
, hBitmap
); 
 292                 GetObject(hBitmap
, sizeof(BITMAP
), (LPSTR
)&bm
); 
 294                 HBITMAP hNewBitmap 
= CreateBitmapIndirect(&bm
); 
 298                     SelectObject(hdcSrc
, old
); 
 304                 HBITMAP old1 
= (HBITMAP
) SelectObject(hdcMem
, hNewBitmap
); 
 305                 BitBlt(hdcMem
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, 
 306                        hdcSrc
, 0, 0, SRCCOPY
); 
 308                 // Select new bitmap out of memory DC 
 309                 SelectObject(hdcMem
, old1
); 
 312                 SelectObject(hdcSrc
, old
); 
 316                 // Create and return a new wxBitmap 
 317                 wxBitmap 
*wxBM 
= new wxBitmap
; 
 318                 wxBM
->SetHBITMAP((WXHBITMAP
) hNewBitmap
); 
 319                 wxBM
->SetWidth(bm
.bmWidth
); 
 320                 wxBM
->SetHeight(bm
.bmHeight
); 
 321                 wxBM
->SetDepth(bm
.bmPlanes
); 
 334                 wxLogError(_("Unsupported clipboard format.")); 
 339             dataFormat 
= wxDF_TEXT
; 
 344                 HANDLE hGlobalMemory 
= ::GetClipboardData(dataFormat
); 
 348                 DWORD hsize 
= ::GlobalSize(hGlobalMemory
); 
 352                 char *s 
= new char[hsize
]; 
 356                 LPSTR lpGlobalMemory 
= (LPSTR
)::GlobalLock(hGlobalMemory
); 
 358                 memcpy(s
, lpGlobalMemory
, hsize
); 
 360                 ::GlobalUnlock(hGlobalMemory
); 
 368                 HANDLE hGlobalMemory 
= ::GetClipboardData(dataFormat
); 
 369                 if ( !hGlobalMemory 
) 
 372                 DWORD size 
= ::GlobalSize(hGlobalMemory
); 
 376                 void *buf 
= malloc(size
); 
 380                 LPSTR lpGlobalMemory 
= (LPSTR
)::GlobalLock(hGlobalMemory
); 
 382                 memcpy(buf
, lpGlobalMemory
, size
); 
 384                 ::GlobalUnlock(hGlobalMemory
); 
 393         wxLogSysError(_("Failed to retrieve data from the clipboard.")); 
 399 wxDataFormat 
wxEnumClipboardFormats(wxDataFormat dataFormat
) 
 401   return ::EnumClipboardFormats(dataFormat
); 
 404 int wxRegisterClipboardFormat(wxChar 
*formatName
) 
 406   return ::RegisterClipboardFormat(formatName
); 
 409 bool wxGetClipboardFormatName(wxDataFormat dataFormat
, 
 413   return ::GetClipboardFormatName((int)dataFormat
, formatName
, maxCount
) > 0; 
 416 // --------------------------------------------------------------------------- 
 418 // --------------------------------------------------------------------------- 
 420 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
, wxObject
) 
 422 wxClipboard
* wxTheClipboard 
= (wxClipboard 
*)NULL
; 
 424 wxClipboard::wxClipboard() 
 426     m_clearOnExit 
= FALSE
; 
 429 wxClipboard::~wxClipboard() 
 437 void wxClipboard::Clear() 
 439 #if wxUSE_OLE_CLIPBOARD 
 440     if ( FAILED(OleSetClipboard(NULL
)) ) 
 442         wxLogLastError("OleSetClipboard(NULL)"); 
 447 bool wxClipboard::Flush() 
 449 #if wxUSE_OLE_CLIPBOARD 
 450     if ( FAILED(OleFlushClipboard()) ) 
 452         wxLogLastError("OleFlushClipboard"); 
 458         m_clearOnExit 
= FALSE
; 
 462 #else // !wxUSE_OLE_CLIPBOARD 
 464 #endif // wxUSE_OLE_CLIPBOARD/!wxUSE_OLE_CLIPBOARD 
 467 bool wxClipboard::Open() 
 469     // OLE opens clipboard for us 
 470 #if wxUSE_OLE_CLIPBOARD 
 473     return wxOpenClipboard(); 
 477 bool wxClipboard::IsOpened() const 
 479 #if wxUSE_OLE_CLIPBOARD 
 482     return wxIsClipboardOpened(); 
 486 bool wxClipboard::SetData( wxDataObject 
*data 
) 
 488     (void)wxEmptyClipboard(); 
 491         return AddData(data
); 
 496 bool wxClipboard::AddData( wxDataObject 
*data 
) 
 498     wxCHECK_MSG( data
, FALSE
, wxT("data is invalid") ); 
 500 #if wxUSE_OLE_CLIPBOARD 
 501     HRESULT hr 
= OleSetClipboard(data
->GetInterface()); 
 504         wxLogSysError(hr
, _("Failed to put data on the clipboard")); 
 506         // don't free anything in this case 
 511     // we have a problem here because we should delete wxDataObject, but we 
 512     // can't do it because IDataObject which we just gave to the clipboard 
 513     // would try to use it when it will need the data. IDataObject is ref 
 514     // counted and so doesn't suffer from such problem, so we release it now 
 515     // and tell it to delete wxDataObject when it is deleted itself. 
 516     data
->SetAutoDelete(); 
 518     // we have to call either OleSetClipboard(NULL) or OleFlushClipboard() when 
 519     // using OLE clipboard when the app terminates - by default, we call 
 520     // OleSetClipboard(NULL) which won't waste RAM, but the app can call 
 521     // wxClipboard::Flush() to chaneg this 
 522     m_clearOnExit 
= TRUE
; 
 526     wxCHECK_MSG( wxIsClipboardOpened(), FALSE
, wxT("clipboard not open") ); 
 528     wxDataFormat format 
= data
->GetFormat(); 
 535             wxTextDataObject
* textDataObject 
= (wxTextDataObject
*) data
; 
 536             wxString 
str(textDataObject
->GetText()); 
 537             return wxSetClipboardData(format
, str
.c_str()); 
 543             wxBitmapDataObject
* bitmapDataObject 
= (wxBitmapDataObject
*) data
; 
 544             wxBitmap 
bitmap(bitmapDataObject
->GetBitmap()); 
 545             return wxSetClipboardData(data
->GetFormat(), &bitmap
); 
 551             wxMetafileDataObject
* metaFileDataObject 
=  
 552                 (wxMetafileDataObject
*) data
; 
 553             wxMetafile metaFile 
= metaFileDataObject
->GetMetafile(); 
 554             return wxSetClipboardData(wxDF_METAFILE
, &metaFile
, 
 555                                       metaFileDataObject
->GetWidth(), 
 556                                       metaFileDataObject
->GetHeight()); 
 558 #endif // wxUSE_METAFILE 
 561             return wxSetClipboardData(data
); 
 563 #else // !wxUSE_DATAOBJ 
 565 #endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ 
 568 void wxClipboard::Close() 
 570     // OLE closes clipboard for us 
 571 #if !wxUSE_OLE_CLIPBOARD 
 576 bool wxClipboard::IsSupported( wxDataFormat format 
) 
 578     return wxIsClipboardFormatAvailable(format
); 
 581 bool wxClipboard::GetData( wxDataObject 
*data 
) 
 583     wxCHECK_MSG( data
, FALSE
, wxT("invalid data object") ); 
 585 #if wxUSE_OLE_CLIPBOARD 
 586     IDataObject 
*pDataObject 
= NULL
; 
 587     HRESULT hr 
= OleGetClipboard(&pDataObject
); 
 588     if ( FAILED(hr
) || !pDataObject 
) 
 590         wxLogSysError(hr
, _("Failed to get data from the clipboard")); 
 595     // build the list of supported formats 
 596     size_t nFormats 
= data
->GetFormatCount(wxDataObject::Set
); 
 597     wxDataFormat format
, *formats
; 
 600         // the most common case 
 605         // bad luck, need to alloc mem 
 606         formats 
= new wxDataFormat
[nFormats
]; 
 609     data
->GetAllFormats(formats
, wxDataObject::Set
); 
 611     // get the format enumerator 
 613     wxArrayInt supportedFormats
; 
 614     IEnumFORMATETC 
*pEnumFormatEtc 
= NULL
; 
 615     hr 
= pDataObject
->EnumFormatEtc(DATADIR_GET
, &pEnumFormatEtc
); 
 616     if ( FAILED(hr
) || !pEnumFormatEtc 
) 
 619                       _("Failed to retrieve the supported clipboard formats")); 
 623         // ask for the supported formats and see if there are any we support 
 628             hr 
= pEnumFormatEtc
->Next(1, &formatEtc
, &nCount
); 
 630             // don't use FAILED() because S_FALSE would pass it 
 637             CLIPFORMAT cf 
= formatEtc
.cfFormat
; 
 640             wxLogTrace(wxTRACE_OleCalls
, 
 641                        wxT("Object on the clipboard supports format %s."), 
 642                        wxDataObject::GetFormatName(cf
)); 
 646             for ( size_t n 
= 0; n 
< nFormats
; n
++ ) 
 648                 if ( formats
[n
].GetFormatId() == cf 
) 
 650                     if ( supportedFormats
.Index(cf
) == wxNOT_FOUND 
) 
 652                         supportedFormats
.Add(cf
); 
 658         pEnumFormatEtc
->Release(); 
 661     if ( formats 
!= &format 
) 
 665     //else: we didn't allocate any memory 
 667     if ( !supportedFormats
.IsEmpty() ) 
 670         formatEtc
.ptd      
= NULL
; 
 671         formatEtc
.dwAspect 
= DVASPECT_CONTENT
; 
 672         formatEtc
.lindex   
= -1; 
 673         formatEtc
.tymed    
= TYMED_HGLOBAL
; 
 675         size_t nSupportedFormats 
= supportedFormats
.GetCount(); 
 676         for ( size_t n 
= 0; !result 
&& (n 
< nSupportedFormats
); n
++ ) 
 679             formatEtc
.cfFormat 
= supportedFormats
[n
]; 
 682             hr 
= pDataObject
->GetData(&formatEtc
, &medium
); 
 685                 // try other tymed for GDI objects 
 686                 if ( formatEtc
.cfFormat 
== CF_BITMAP 
) 
 688                     formatEtc
.tymed 
= TYMED_HGLOBAL
; 
 689                     hr 
= pDataObject
->GetData(&formatEtc
, &medium
); 
 695                 // pass the data to the data object 
 696                 hr 
= data
->GetInterface()->SetData(&formatEtc
, &medium
, TRUE
); 
 699                     wxLogDebug(wxT("Failed to set data in wxIDataObject")); 
 701                     // IDataObject only takes the ownership of data if it 
 702                     // successfully got it - which is not the case here 
 703                     ReleaseStgMedium(&medium
); 
 710             //else: unsupported tymed? 
 713     //else: unsupported format 
 715     // clean up and return 
 716     pDataObject
->Release(); 
 720     wxCHECK_MSG( wxIsClipboardOpened(), FALSE
, wxT("clipboard not open") ); 
 722     wxDataFormat format 
= data
->GetFormat(); 
 728             wxTextDataObject
* textDataObject 
= (wxTextDataObject
*) data
; 
 729             char* s 
= (char*) wxGetClipboardData(format
); 
 732                 textDataObject
->SetText(s
); 
 743             wxBitmapDataObject
* bitmapDataObject 
= (wxBitmapDataObject 
*)data
; 
 744             wxBitmap
* bitmap 
= (wxBitmap 
*)wxGetClipboardData(data
->GetFormat()); 
 747                 bitmapDataObject
->SetBitmap(* bitmap
); 
 757             wxMetafileDataObject
* metaFileDataObject 
= (wxMetafileDataObject 
*)data
; 
 758             wxMetafile
* metaFile 
= (wxMetafile 
*)wxGetClipboardData(wxDF_METAFILE
); 
 761                 metaFileDataObject
->SetMetafile(*metaFile
); 
 772                 void *buf 
= wxGetClipboardData(format
, &len
); 
 775                     // FIXME this is for testing only!! 
 776                     ((wxPrivateDataObject 
*)data
)->SetData(buf
, len
); 
 785 #else // !wxUSE_DATAOBJ 
 787 #endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ 
 791     #error "Please turn wxUSE_CLIPBOARD on to compile this file." 
 792 #endif // wxUSE_CLIPBOARD