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