]> git.saurik.com Git - wxWidgets.git/blame - src/msw/clipbrd.cpp
Add detachmenu
[wxWidgets.git] / src / msw / clipbrd.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose: Clipboard functionality
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
26f86486 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
26f86486
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
26f86486 21 #pragma implementation "clipbrd.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
26f86486 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
26f86486 32 #include "wx/setup.h"
2bda0e17
KB
33#endif
34
47d67540 35#if wxUSE_CLIPBOARD
2bda0e17
KB
36
37#ifndef WX_PRECOMP
26f86486
VZ
38 #include "wx/object.h"
39 #include "wx/event.h"
40 #include "wx/app.h"
41 #include "wx/frame.h"
42 #include "wx/bitmap.h"
43 #include "wx/utils.h"
0c589ad0 44 #include "wx/intl.h"
2bda0e17
KB
45#endif
46
06e43511 47#if wxUSE_METAFILE
26f86486 48 #include "wx/metafile.h"
06e43511
JS
49#endif
50
dbda9e86 51#include "wx/log.h"
2bda0e17 52#include "wx/clipbrd.h"
06e43511 53
3f480da3 54#include <string.h>
06e43511
JS
55#include <windows.h>
56
2bda0e17
KB
57#include "wx/msw/private.h"
58#include "wx/msw/dib.h"
59
06e43511
JS
60// wxDataObject is tied to OLE/drag and drop implementation,
61// therefore so is wxClipboard :-(
62#if wxUSE_DRAG_AND_DROP
26f86486 63 #include "wx/dataobj.h"
3f480da3
VZ
64
65 static bool wxSetClipboardData(wxDataObject *data);
2bda0e17
KB
66#endif
67
3f480da3
VZ
68#ifdef __WIN16__
69 #define memcpy hmemcpy
70#endif
06e43511 71
26f86486
VZ
72// ===========================================================================
73// implementation
74// ===========================================================================
75
76// ---------------------------------------------------------------------------
77// old-style clipboard functions using Windows API
78// ---------------------------------------------------------------------------
2bda0e17 79
26f86486
VZ
80static bool gs_wxClipboardIsOpen = FALSE;
81
82bool wxOpenClipboard()
2bda0e17 83{
837e5743 84 wxCHECK_MSG( !gs_wxClipboardIsOpen, TRUE, _T("clipboard already opened.") );
26f86486
VZ
85
86 wxWindow *win = wxTheApp->GetTopWindow();
87 if ( win )
88 {
89 gs_wxClipboardIsOpen = ::OpenClipboard((HWND)win->GetHWND()) != 0;
90
91 if ( !gs_wxClipboardIsOpen )
92 wxLogSysError(_("Failed to open the clipboard."));
93
94 return gs_wxClipboardIsOpen;
95 }
96 else
97 {
837e5743 98 wxLogDebug(_T("Can not open clipboard without a main window."));
26f86486
VZ
99
100 return FALSE;
101 }
2bda0e17
KB
102}
103
26f86486 104bool wxCloseClipboard()
2bda0e17 105{
837e5743 106 wxCHECK_MSG( gs_wxClipboardIsOpen, FALSE, _T("clipboard is not opened") );
26f86486
VZ
107
108 gs_wxClipboardIsOpen = FALSE;
109
110 if ( ::CloseClipboard() == 0 )
111 {
112 wxLogSysError(_("Failed to close the clipboard."));
113
114 return FALSE;
115 }
116
117 return TRUE;
2bda0e17
KB
118}
119
26f86486 120bool wxEmptyClipboard()
2bda0e17 121{
26f86486
VZ
122 if ( ::EmptyClipboard() == 0 )
123 {
124 wxLogSysError(_("Failed to empty the clipboard."));
125
126 return FALSE;
127 }
128
129 return TRUE;
2bda0e17
KB
130}
131
26f86486 132bool wxIsClipboardOpened()
2bda0e17 133{
26f86486 134 return gs_wxClipboardIsOpen;
2bda0e17
KB
135}
136
06e43511 137bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
2bda0e17 138{
26f86486 139 return ::IsClipboardFormatAvailable(dataFormat) != 0;
2bda0e17
KB
140}
141
3f480da3
VZ
142#if wxUSE_DRAG_AND_DROP
143static bool wxSetClipboardData(wxDataObject *data)
144{
145 size_t size = data->GetDataSize();
146 HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
147 if ( !hGlobal )
148 {
149 wxLogSysError(_("Failed to allocate %dKb of memory for clipboard "
150 "transfer."), size / 1024);
151
152 return FALSE;
153 }
154
155 LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
156
157 data->GetDataHere(lpGlobalMemory);
158
159 GlobalUnlock(hGlobal);
160
161 wxDataFormat format = data->GetPreferredFormat();
162 if ( !::SetClipboardData(format, hGlobal) )
163 {
164 wxLogSysError(_("Failed to set clipboard data in format %s"),
165 wxDataObject::GetFormatName(format));
166
167 return FALSE;
168 }
169
170 return TRUE;
171}
172#endif // wxUSE_DRAG_AND_DROP
173
26f86486
VZ
174bool wxSetClipboardData(wxDataFormat dataFormat,
175 const void *data,
176 int width, int height)
2bda0e17 177{
26f86486
VZ
178 HANDLE handle = 0; // return value of SetClipboardData
179
180 switch (dataFormat)
2bda0e17 181 {
26f86486
VZ
182 case wxDF_BITMAP:
183 {
184 wxBitmap *bitmap = (wxBitmap *)data;
185
186 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
187 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
188 HBITMAP old = (HBITMAP)
189 ::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP());
190 HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc,
191 bitmap->GetWidth(),
192 bitmap->GetHeight());
193 if (!hBitmap)
194 {
195 SelectObject(hdcSrc, old);
196 DeleteDC(hdcMem);
197 DeleteDC(hdcSrc);
198 return FALSE;
199 }
200
201 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap);
202 BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(),
203 hdcSrc, 0, 0, SRCCOPY);
204
205 // Select new bitmap out of memory DC
206 SelectObject(hdcMem, old1);
207
208 // Set the data
209 handle = ::SetClipboardData(CF_BITMAP, hBitmap);
210
211 // Clean up
212 SelectObject(hdcSrc, old);
213 DeleteDC(hdcSrc);
214 DeleteDC(hdcMem);
215 break;
216 }
217
218 case wxDF_DIB:
219 {
47d67540 220#if wxUSE_IMAGE_LOADING_IN_MSW
26f86486
VZ
221 wxBitmap *bitmap = (wxBitmap *)data;
222 HBITMAP hBitmap = (HBITMAP)bitmap->GetHBITMAP();
223 // NULL palette means to use the system one
224 HANDLE hDIB = BitmapToDIB(hBitmap, (HPALETTE)NULL);
225 handle = SetClipboardData(CF_DIB, hDIB);
2bda0e17 226#endif
26f86486
VZ
227 break;
228 }
229
47d67540 230#if wxUSE_METAFILE
26f86486
VZ
231 case wxDF_METAFILE:
232 {
233 wxMetafile *wxMF = (wxMetafile *)data;
234 HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
26f86486 235 METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data);
2bda0e17 236
26f86486
VZ
237 mf->mm = wxMF->GetWindowsMappingMode();
238 mf->xExt = width;
239 mf->yExt = height;
240 mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE();
241 GlobalUnlock(data);
242 wxMF->SetHMETAFILE((WXHANDLE) NULL);
2bda0e17 243
26f86486
VZ
244 handle = SetClipboardData(CF_METAFILEPICT, data);
245 break;
246 }
2bda0e17 247#endif
26f86486
VZ
248 case CF_SYLK:
249 case CF_DIF:
250 case CF_TIFF:
251 case CF_PALETTE:
252 default:
253 {
254 wxLogError(_("Unsupported clipboard format."));
255 return FALSE;
256 }
2bda0e17 257
26f86486
VZ
258 case wxDF_OEMTEXT:
259 dataFormat = wxDF_TEXT;
260 // fall through
2bda0e17 261
26f86486
VZ
262 case wxDF_TEXT:
263 {
264 char *s = (char *)data;
265
266 width = strlen(s) + 1;
267 height = 1;
268 DWORD l = (width * height);
269 HANDLE hGlobalMemory = GlobalAlloc(GHND, l);
270 if ( hGlobalMemory )
271 {
26f86486 272 LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
2bda0e17 273
26f86486 274 memcpy(lpGlobalMemory, s, l);
2bda0e17 275
26f86486
VZ
276 GlobalUnlock(hGlobalMemory);
277 }
2bda0e17 278
26f86486
VZ
279 handle = SetClipboardData(dataFormat, hGlobalMemory);
280 break;
281 }
2bda0e17 282 }
26f86486
VZ
283
284 if ( handle == 0 )
2bda0e17 285 {
26f86486
VZ
286 wxLogSysError(_("Failed to set clipboard data."));
287
288 return FALSE;
2bda0e17 289 }
26f86486
VZ
290
291 return TRUE;
292}
293
294void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
295{
296 void *retval = NULL;
297
298 switch ( dataFormat )
2bda0e17 299 {
26f86486
VZ
300 case wxDF_BITMAP:
301 {
302 BITMAP bm;
303 HBITMAP hBitmap = (HBITMAP) GetClipboardData(CF_BITMAP);
304 if (!hBitmap)
305 break;
306
307 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
308 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
309
310 HBITMAP old = (HBITMAP) ::SelectObject(hdcSrc, hBitmap);
311 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
312
313 HBITMAP hNewBitmap = CreateBitmapIndirect(&bm);
314
315 if (!hNewBitmap)
316 {
317 SelectObject(hdcSrc, old);
318 DeleteDC(hdcMem);
319 DeleteDC(hdcSrc);
320 break;
321 }
322
323 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hNewBitmap);
324 BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,
325 hdcSrc, 0, 0, SRCCOPY);
326
327 // Select new bitmap out of memory DC
328 SelectObject(hdcMem, old1);
329
330 // Clean up
331 SelectObject(hdcSrc, old);
332 DeleteDC(hdcSrc);
333 DeleteDC(hdcMem);
334
335 // Create and return a new wxBitmap
336 wxBitmap *wxBM = new wxBitmap;
337 wxBM->SetHBITMAP((WXHBITMAP) hNewBitmap);
338 wxBM->SetWidth(bm.bmWidth);
339 wxBM->SetHeight(bm.bmHeight);
340 wxBM->SetDepth(bm.bmPlanes);
341 wxBM->SetOk(TRUE);
342 retval = wxBM;
343 break;
344 }
345
346 case wxDF_METAFILE:
347 case CF_SYLK:
348 case CF_DIF:
349 case CF_TIFF:
350 case CF_PALETTE:
351 case wxDF_DIB:
26f86486
VZ
352 {
353 wxLogError(_("Unsupported clipboard format."));
354 return FALSE;
355 }
356
357 case wxDF_OEMTEXT:
358 dataFormat = wxDF_TEXT;
359 // fall through
360
361 case wxDF_TEXT:
362 {
363 HANDLE hGlobalMemory = ::GetClipboardData(dataFormat);
364 if (!hGlobalMemory)
365 break;
2bda0e17 366
26f86486
VZ
367 DWORD hsize = ::GlobalSize(hGlobalMemory);
368 if (len)
369 *len = hsize;
2bda0e17 370
26f86486
VZ
371 char *s = new char[hsize];
372 if (!s)
373 break;
2bda0e17 374
26f86486 375 LPSTR lpGlobalMemory = (LPSTR)::GlobalLock(hGlobalMemory);
2bda0e17 376
26f86486 377 memcpy(s, lpGlobalMemory, hsize);
2bda0e17 378
26f86486
VZ
379 ::GlobalUnlock(hGlobalMemory);
380
381 retval = s;
382 break;
383 }
3f480da3
VZ
384
385 default:
386 {
387 HANDLE hGlobalMemory = ::GetClipboardData(dataFormat);
388 if ( !hGlobalMemory )
389 break;
390
391 DWORD size = ::GlobalSize(hGlobalMemory);
392 if ( len )
393 *len = size;
394
395 void *buf = malloc(size);
396 if ( !buf )
397 break;
398
399 LPSTR lpGlobalMemory = (LPSTR)::GlobalLock(hGlobalMemory);
400
401 memcpy(buf, lpGlobalMemory, size);
402
403 ::GlobalUnlock(hGlobalMemory);
404
405 retval = buf;
406 break;
407 }
26f86486 408 }
2bda0e17 409
26f86486
VZ
410 if ( !retval )
411 {
412 wxLogSysError(_("Failed to retrieve data from the clipboard."));
2bda0e17 413 }
26f86486
VZ
414
415 return retval;
2bda0e17
KB
416}
417
3f480da3 418wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
2bda0e17 419{
3f480da3 420 return ::EnumClipboardFormats(dataFormat);
2bda0e17
KB
421}
422
837e5743 423int wxRegisterClipboardFormat(wxChar *formatName)
2bda0e17
KB
424{
425 return ::RegisterClipboardFormat(formatName);
426}
427
26f86486 428bool wxGetClipboardFormatName(wxDataFormat dataFormat,
837e5743 429 wxChar *formatName,
26f86486 430 int maxCount)
2bda0e17 431{
26f86486 432 return ::GetClipboardFormatName((int)dataFormat, formatName, maxCount) > 0;
2bda0e17
KB
433}
434
26f86486 435// ---------------------------------------------------------------------------
06e43511 436// wxClipboard
26f86486 437// ---------------------------------------------------------------------------
2bda0e17 438
26f86486 439IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
2bda0e17 440
26f86486 441wxClipboard* wxTheClipboard = (wxClipboard *)NULL;
4ce81a75 442
2bda0e17
KB
443wxClipboard::wxClipboard()
444{
2bda0e17
KB
445}
446
447wxClipboard::~wxClipboard()
448{
26f86486 449 Clear();
2bda0e17
KB
450}
451
06e43511 452void wxClipboard::Clear()
2bda0e17 453{
2bda0e17
KB
454}
455
06e43511 456bool wxClipboard::Open()
2bda0e17 457{
06e43511 458 return wxOpenClipboard();
2bda0e17
KB
459}
460
06e43511 461bool wxClipboard::SetData( wxDataObject *data )
2bda0e17 462{
26f86486
VZ
463 (void)wxEmptyClipboard();
464
465 if ( data )
466 return AddData(data);
467 else
468 return TRUE;
469}
470
471bool wxClipboard::AddData( wxDataObject *data )
472{
837e5743 473 wxCHECK_MSG( data, FALSE, _T("data is invalid") );
06e43511 474
26f86486 475#if wxUSE_DRAG_AND_DROP
837e5743 476 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, _T("clipboard not open") );
26f86486
VZ
477
478 wxDataFormat format = data->GetFormat();
479
480 switch ( format )
06e43511
JS
481 {
482 case wxDF_TEXT:
483 case wxDF_OEMTEXT:
484 {
485 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
486 wxString str(textDataObject->GetText());
26f86486 487 return wxSetClipboardData(format, str.c_str());
06e43511 488 }
26f86486 489
06e43511
JS
490 case wxDF_BITMAP:
491 case wxDF_DIB:
492 {
493 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
494 wxBitmap bitmap(bitmapDataObject->GetBitmap());
26f86486 495 return wxSetClipboardData(data->GetFormat(), &bitmap);
06e43511 496 }
26f86486 497
06e43511
JS
498#if wxUSE_METAFILE
499 case wxDF_METAFILE:
500 {
26f86486
VZ
501 wxMetafileDataObject* metaFileDataObject =
502 (wxMetafileDataObject*) data;
06e43511 503 wxMetafile metaFile = metaFileDataObject->GetMetafile();
26f86486
VZ
504 return wxSetClipboardData(wxDF_METAFILE, &metaFile,
505 metaFileDataObject->GetWidth(),
506 metaFileDataObject->GetHeight());
06e43511 507 }
26f86486
VZ
508#endif // wxUSE_METAFILE
509
06e43511 510 default:
3f480da3 511 return wxSetClipboardData(data);
06e43511 512 }
3f480da3 513#else // !wxUSE_DRAG_AND_DROP
06e43511 514 return FALSE;
3f480da3 515#endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
2bda0e17
KB
516}
517
06e43511 518void wxClipboard::Close()
2bda0e17 519{
06e43511 520 wxCloseClipboard();
2bda0e17
KB
521}
522
26f86486 523bool wxClipboard::IsSupported( wxDataFormat format )
2bda0e17 524{
06e43511 525 return wxIsClipboardFormatAvailable(format);
2bda0e17
KB
526}
527
06e43511 528bool wxClipboard::GetData( wxDataObject *data )
2bda0e17 529{
837e5743 530 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, _T("clipboard not open") );
26f86486 531
06e43511 532#if wxUSE_DRAG_AND_DROP
26f86486
VZ
533 wxDataFormat format = data->GetFormat();
534 switch ( format )
06e43511
JS
535 {
536 case wxDF_TEXT:
537 case wxDF_OEMTEXT:
538 {
539 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
26f86486
VZ
540 char* s = (char*) wxGetClipboardData(format);
541 if ( s )
06e43511
JS
542 {
543 textDataObject->SetText(s);
544 delete[] s;
545 return TRUE;
546 }
547 else
548 return FALSE;
06e43511 549 }
26f86486 550
06e43511
JS
551 case wxDF_BITMAP:
552 case wxDF_DIB:
553 {
26f86486
VZ
554 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject *)data;
555 wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(data->GetFormat());
06e43511
JS
556 if (bitmap)
557 {
558 bitmapDataObject->SetBitmap(* bitmap);
559 delete bitmap;
560 return TRUE;
561 }
562 else
563 return FALSE;
06e43511
JS
564 }
565#if wxUSE_METAFILE
566 case wxDF_METAFILE:
567 {
26f86486
VZ
568 wxMetafileDataObject* metaFileDataObject = (wxMetafileDataObject *)data;
569 wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE);
06e43511
JS
570 if (metaFile)
571 {
26f86486 572 metaFileDataObject->SetMetafile(*metaFile);
06e43511
JS
573 delete metaFile;
574 return TRUE;
575 }
576 else
577 return FALSE;
06e43511
JS
578 }
579#endif
580 default:
3f480da3
VZ
581 {
582 long len;
583 void *buf = wxGetClipboardData(format, &len);
584 if ( buf )
585 {
586 // FIXME this is for testing only!!
587 ((wxPrivateDataObject *)data)->SetData(buf, len);
588 free(buf);
589
590 return TRUE;
591 }
592 }
26f86486 593
06e43511 594 return FALSE;
06e43511 595 }
06e43511
JS
596#else
597 return FALSE;
598#endif
2bda0e17
KB
599}
600
4ce81a75
JS
601//-----------------------------------------------------------------------------
602// wxClipboardModule
603//-----------------------------------------------------------------------------
604
605IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
606
607bool wxClipboardModule::OnInit()
608{
609 wxTheClipboard = new wxClipboard();
26f86486 610
4ce81a75
JS
611 return TRUE;
612}
613
614void wxClipboardModule::OnExit()
615{
616 if (wxTheClipboard) delete wxTheClipboard;
617 wxTheClipboard = (wxClipboard*) NULL;
618}
619
26f86486
VZ
620#else
621 #error "Please turn wxUSE_CLIPBOARD on to compile this file."
47d67540 622#endif // wxUSE_CLIPBOARD
4ce81a75 623