///////////////////////////////////////////////////////////////////////////// // Name: src/msw/clipbrd.cpp // Purpose: Clipboard functionality // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id: clipbrd.cpp 43884 2006-12-09 19:49:40Z PC $ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // =========================================================================== // declarations // =========================================================================== // --------------------------------------------------------------------------- // headers // --------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #if wxUSE_CLIPBOARD #include "wx/clipbrd.h" #ifndef WX_PRECOMP #include "wx/object.h" #include "wx/event.h" #include "wx/app.h" #include "wx/frame.h" #include "wx/bitmap.h" #include "wx/utils.h" #include "wx/intl.h" #include "wx/log.h" #include "wx/dataobj.h" #endif #if wxUSE_METAFILE #include "wx/metafile.h" #endif #include #include "wx/msw/private.h" #include "wx/msw/ole/oleutils.h" #if wxUSE_WXDIB #include "wx/msw/dib.h" #endif // wxDataObject is tied to OLE/drag and drop implementation, therefore so are // the functions using wxDataObject in wxClipboard //#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP #if wxUSE_OLE && !defined(__WXWINCE__) // use OLE clipboard #define wxUSE_OLE_CLIPBOARD 1 #else // !wxUSE_DATAOBJ // use Win clipboard API #define wxUSE_OLE_CLIPBOARD 0 #endif #if wxUSE_OLE_CLIPBOARD #include #endif // wxUSE_OLE_CLIPBOARD // =========================================================================== // implementation // =========================================================================== // --------------------------------------------------------------------------- // old-style clipboard functions using Windows API // --------------------------------------------------------------------------- static bool gs_wxClipboardIsOpen = false; bool wxOpenClipboard() { wxCHECK_MSG( !gs_wxClipboardIsOpen, true, wxT("clipboard already opened.") ); wxWindow *win = wxTheApp->GetTopWindow(); if ( win ) { gs_wxClipboardIsOpen = ::OpenClipboard((HWND)win->GetHWND()) != 0; if ( !gs_wxClipboardIsOpen ) wxLogSysError(_("Failed to open the clipboard.")); return gs_wxClipboardIsOpen; } else { wxLogDebug(wxT("Can not open clipboard without a main window.")); return false; } } bool wxCloseClipboard() { wxCHECK_MSG( gs_wxClipboardIsOpen, false, wxT("clipboard is not opened") ); gs_wxClipboardIsOpen = false; if ( ::CloseClipboard() == 0 ) { wxLogSysError(_("Failed to close the clipboard.")); return false; } return true; } bool wxEmptyClipboard() { if ( ::EmptyClipboard() == 0 ) { wxLogSysError(_("Failed to empty the clipboard.")); return false; } return true; } bool wxIsClipboardOpened() { return gs_wxClipboardIsOpen; } bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat) { wxDataFormat::NativeFormat cf = dataFormat.GetFormatId(); if ( ::IsClipboardFormatAvailable(cf) ) { // ok from the first try return true; } // for several standard formats, we can convert from some other ones too switch ( cf ) { // for bitmaps, DIBs will also do case CF_BITMAP: return ::IsClipboardFormatAvailable(CF_DIB) != 0; #if wxUSE_ENH_METAFILE && !defined(__WXWINCE__) case CF_METAFILEPICT: return ::IsClipboardFormatAvailable(CF_ENHMETAFILE) != 0; #endif // wxUSE_ENH_METAFILE default: return false; } } bool wxSetClipboardData(wxDataFormat dataFormat, const void *data, int width, int height) { HANDLE handle = 0; // return value of SetClipboardData switch (dataFormat) { case wxDF_BITMAP: { wxBitmap *bitmap = (wxBitmap *)data; HDC hdcMem = CreateCompatibleDC((HDC) NULL); HDC hdcSrc = CreateCompatibleDC((HDC) NULL); HBITMAP old = (HBITMAP) ::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP()); HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc, bitmap->GetWidth(), bitmap->GetHeight()); if (!hBitmap) { SelectObject(hdcSrc, old); DeleteDC(hdcMem); DeleteDC(hdcSrc); return false; } HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap); BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(), hdcSrc, 0, 0, SRCCOPY); // Select new bitmap out of memory DC SelectObject(hdcMem, old1); // Set the data handle = ::SetClipboardData(CF_BITMAP, hBitmap); // Clean up SelectObject(hdcSrc, old); DeleteDC(hdcSrc); DeleteDC(hdcMem); break; } #if wxUSE_WXDIB case wxDF_DIB: { wxBitmap *bitmap = (wxBitmap *)data; if ( bitmap && bitmap->Ok() ) { wxDIB dib(*bitmap); if ( dib.IsOk() ) { handle = ::SetClipboardData(CF_DIB, dib.Detach()); } } break; } #endif // VZ: I'm told that this code works, but it doesn't seem to work for me // and, anyhow, I'd be highly surprised if it did. So I leave it here // but IMNSHO it is completely broken. #if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH) && !defined(__WXWINCE__) case wxDF_METAFILE: { wxMetafile *wxMF = (wxMetafile *)data; HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1); METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data); mf->mm = wxMF->GetWindowsMappingMode(); mf->xExt = width; mf->yExt = height; mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE(); GlobalUnlock(data); wxMF->SetHMETAFILE((WXHANDLE) NULL); handle = SetClipboardData(CF_METAFILEPICT, data); break; } #endif // wxUSE_METAFILE #if wxUSE_ENH_METAFILE && !defined(__WXWINCE__) case wxDF_ENHMETAFILE: { wxEnhMetaFile *emf = (wxEnhMetaFile *)data; wxEnhMetaFile emfCopy = *emf; handle = SetClipboardData(CF_ENHMETAFILE, (void *)emfCopy.GetHENHMETAFILE()); } break; #endif // wxUSE_ENH_METAFILE case CF_SYLK: case CF_DIF: case CF_TIFF: case CF_PALETTE: default: { wxLogError(_("Unsupported clipboard format.")); return false; } case wxDF_OEMTEXT: dataFormat = wxDF_TEXT; // fall through case wxDF_TEXT: { char *s = (char *)data; width = strlen(s) + 1; height = 1; DWORD l = (width * height); HANDLE hGlobalMemory = GlobalAlloc(GHND, l); if ( hGlobalMemory ) { LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory); memcpy(lpGlobalMemory, s, l); GlobalUnlock(hGlobalMemory); } handle = SetClipboardData(dataFormat, hGlobalMemory); break; } // Only tested with Visual C++ 6.0 so far #if defined(__VISUALC__) case wxDF_HTML: { char* html = (char *)data; // Create temporary buffer for HTML header... char *buf = new char [400 + strlen(html)]; if(!buf) return false; // Get clipboard id for HTML format... static int cfid = 0; if(!cfid) cfid = RegisterClipboardFormat(wxT("HTML Format")); // Create a template string for the HTML header... strcpy(buf, "Version:0.9\r\n" "StartHTML:00000000\r\n" "EndHTML:00000000\r\n" "StartFragment:00000000\r\n" "EndFragment:00000000\r\n" "\r\n" "\r\n"); // Append the HTML... strcat(buf, html); strcat(buf, "\r\n"); // Finish up the HTML format... strcat(buf, "\r\n" "\r\n" ""); // Now go back, calculate all the lengths, and write out the // necessary header information. Note, wsprintf() truncates the // string when you overwrite it so you follow up with code to replace // the 0 appended at the end with a '\r'... char *ptr = strstr(buf, "StartHTML"); sprintf(ptr+10, "%08u", strstr(buf, "") - buf); *(ptr+10+8) = '\r'; ptr = strstr(buf, "EndHTML"); sprintf(ptr+8, "%08u", strlen(buf)); *(ptr+8+8) = '\r'; ptr = strstr(buf, "StartFragment"); sprintf(ptr+14, "%08u", strstr(buf, "