]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/enhmeta.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / msw / enhmeta.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/enhmeta.cpp
3// Purpose: implementation of wxEnhMetaFileXXX classes
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 13.01.00
7// Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_ENH_METAFILE
27
28#ifndef WX_PRECOMP
29 #include "wx/string.h"
30 #include "wx/log.h"
31 #include "wx/intl.h"
32#endif //WX_PRECOMP
33
34#include "wx/dc.h"
35#include "wx/msw/dc.h"
36
37#include "wx/metafile.h"
38#include "wx/clipbrd.h"
39
40#include "wx/msw/private.h"
41
42// ----------------------------------------------------------------------------
43// wxWin macros
44// ----------------------------------------------------------------------------
45
46IMPLEMENT_DYNAMIC_CLASS(wxEnhMetaFile, wxObject)
47
48// ----------------------------------------------------------------------------
49// macros
50// ----------------------------------------------------------------------------
51
52#define GetEMF() ((HENHMETAFILE)m_hMF)
53#define GetEMFOf(mf) ((HENHMETAFILE)((mf).m_hMF))
54
55// ----------------------------------------------------------------------------
56// private functions
57// ----------------------------------------------------------------------------
58
59// we must pass NULL if the string is empty to metafile functions
60static inline const wxChar *GetMetaFileName(const wxString& fn)
61 { return !fn ? NULL : wxMSW_CONV_LPCTSTR(fn); }
62
63// ============================================================================
64// implementation
65// ============================================================================
66
67// ----------------------------------------------------------------------------
68// wxEnhMetaFile
69// ----------------------------------------------------------------------------
70
71wxGDIRefData *wxEnhMetaFile::CreateGDIRefData() const
72{
73 wxFAIL_MSG( wxT("must be implemented if used") );
74
75 return NULL;
76}
77
78wxGDIRefData *
79wxEnhMetaFile::CloneGDIRefData(const wxGDIRefData *WXUNUSED(data)) const
80{
81 wxFAIL_MSG( wxT("must be implemented if used") );
82
83 return NULL;
84}
85
86void wxEnhMetaFile::Init()
87{
88 if ( m_filename.empty() )
89 {
90 m_hMF = 0;
91 }
92 else // have valid file name, load metafile from it
93 {
94 m_hMF = (WXHANDLE)::GetEnhMetaFile(m_filename.t_str());
95 if ( !m_hMF )
96 {
97 wxLogSysError(_("Failed to load metafile from file \"%s\"."),
98 m_filename.c_str());
99 }
100 }
101}
102
103void wxEnhMetaFile::Assign(const wxEnhMetaFile& mf)
104{
105 if ( &mf == this )
106 return;
107
108 if ( mf.m_hMF )
109 {
110 m_hMF = (WXHANDLE)::CopyEnhMetaFile(GetEMFOf(mf),
111 GetMetaFileName(m_filename));
112 if ( !m_hMF )
113 {
114 wxLogLastError(wxT("CopyEnhMetaFile"));
115 }
116 }
117 else
118 {
119 m_hMF = 0;
120 }
121}
122
123void wxEnhMetaFile::Free()
124{
125 if ( m_hMF )
126 {
127 if ( !::DeleteEnhMetaFile(GetEMF()) )
128 {
129 wxLogLastError(wxT("DeleteEnhMetaFile"));
130 }
131 }
132}
133
134bool wxEnhMetaFile::Play(wxDC *dc, wxRect *rectBound)
135{
136 wxCHECK_MSG( IsOk(), false, wxT("can't play invalid enhanced metafile") );
137 wxCHECK_MSG( dc, false, wxT("invalid wxDC in wxEnhMetaFile::Play") );
138
139 RECT rect;
140 if ( rectBound )
141 {
142 rect.top = rectBound->y;
143 rect.left = rectBound->x;
144 rect.right = rectBound->x + rectBound->width;
145 rect.bottom = rectBound->y + rectBound->height;
146 }
147 else
148 {
149 wxSize size = GetSize();
150
151 rect.top =
152 rect.left = 0;
153 rect.right = size.x;
154 rect.bottom = size.y;
155 }
156
157 wxDCImpl *impl = dc->GetImpl();
158 wxMSWDCImpl *msw_impl = wxDynamicCast( impl, wxMSWDCImpl );
159 if (!msw_impl)
160 return false;
161
162 if ( !::PlayEnhMetaFile(GetHdcOf(*msw_impl), GetEMF(), &rect) )
163 {
164 wxLogLastError(wxT("PlayEnhMetaFile"));
165
166 return false;
167 }
168
169 return true;
170}
171
172wxSize wxEnhMetaFile::GetSize() const
173{
174 wxSize size = wxDefaultSize;
175
176 if ( IsOk() )
177 {
178 ENHMETAHEADER hdr;
179 if ( !::GetEnhMetaFileHeader(GetEMF(), sizeof(hdr), &hdr) )
180 {
181 wxLogLastError(wxT("GetEnhMetaFileHeader"));
182 }
183 else
184 {
185 // the width and height are in HIMETRIC (0.01mm) units, transform
186 // them to pixels
187 LONG w = hdr.rclFrame.right,
188 h = hdr.rclFrame.bottom;
189
190 HIMETRICToPixel(&w, &h);
191
192 size.x = w;
193 size.y = h;
194 }
195 }
196
197 return size;
198}
199
200bool wxEnhMetaFile::SetClipboard(int WXUNUSED(width), int WXUNUSED(height))
201{
202#if wxUSE_DRAG_AND_DROP && wxUSE_CLIPBOARD
203 wxCHECK_MSG( m_hMF, false, wxT("can't copy invalid metafile to clipboard") );
204
205 return wxTheClipboard->AddData(new wxEnhMetaFileDataObject(*this));
206#else // !wxUSE_DRAG_AND_DROP
207 wxFAIL_MSG(wxT("not implemented"));
208 return false;
209#endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
210}
211
212// ----------------------------------------------------------------------------
213// wxEnhMetaFileDCImpl
214// ----------------------------------------------------------------------------
215
216class wxEnhMetaFileDCImpl : public wxMSWDCImpl
217{
218public:
219 wxEnhMetaFileDCImpl( wxEnhMetaFileDC *owner,
220 const wxString& filename, int width, int height,
221 const wxString& description );
222 wxEnhMetaFileDCImpl( wxEnhMetaFileDC *owner,
223 const wxDC& referenceDC,
224 const wxString& filename, int width, int height,
225 const wxString& description );
226 virtual ~wxEnhMetaFileDCImpl();
227
228 // obtain a pointer to the new metafile (caller should delete it)
229 wxEnhMetaFile *Close();
230
231protected:
232 virtual void DoGetSize(int *width, int *height) const;
233
234private:
235 void Create(HDC hdcRef,
236 const wxString& filename, int width, int height,
237 const wxString& description);
238
239 // size passed to ctor and returned by DoGetSize()
240 int m_width,
241 m_height;
242};
243
244
245wxEnhMetaFileDCImpl::wxEnhMetaFileDCImpl( wxEnhMetaFileDC* owner,
246 const wxString& filename,
247 int width, int height,
248 const wxString& description )
249 : wxMSWDCImpl( owner )
250{
251 Create(ScreenHDC(), filename, width, height, description);
252}
253
254wxEnhMetaFileDCImpl::wxEnhMetaFileDCImpl( wxEnhMetaFileDC* owner,
255 const wxDC& referenceDC,
256 const wxString& filename,
257 int width, int height,
258 const wxString& description )
259 : wxMSWDCImpl( owner )
260{
261 Create(GetHdcOf(referenceDC), filename, width, height, description);
262}
263
264void wxEnhMetaFileDCImpl::Create(HDC hdcRef,
265 const wxString& filename,
266 int width, int height,
267 const wxString& description)
268{
269 m_width = width;
270 m_height = height;
271
272 RECT rect;
273 RECT *pRect;
274 if ( width && height )
275 {
276 rect.top =
277 rect.left = 0;
278 rect.right = width;
279 rect.bottom = height;
280
281 // CreateEnhMetaFile() wants them in HIMETRIC
282 PixelToHIMETRIC(&rect.right, &rect.bottom, hdcRef);
283
284 pRect = &rect;
285 }
286 else
287 {
288 // GDI will try to find out the size for us (not recommended)
289 pRect = (LPRECT)NULL;
290 }
291
292 m_hDC = (WXHDC)::CreateEnhMetaFile(hdcRef, GetMetaFileName(filename),
293 pRect, description.t_str());
294 if ( !m_hDC )
295 {
296 wxLogLastError(wxT("CreateEnhMetaFile"));
297 }
298}
299
300void wxEnhMetaFileDCImpl::DoGetSize(int *width, int *height) const
301{
302 if ( width )
303 *width = m_width;
304 if ( height )
305 *height = m_height;
306}
307
308wxEnhMetaFile *wxEnhMetaFileDCImpl::Close()
309{
310 wxCHECK_MSG( IsOk(), NULL, wxT("invalid wxEnhMetaFileDC") );
311
312 HENHMETAFILE hMF = ::CloseEnhMetaFile(GetHdc());
313 if ( !hMF )
314 {
315 wxLogLastError(wxT("CloseEnhMetaFile"));
316
317 return NULL;
318 }
319
320 wxEnhMetaFile *mf = new wxEnhMetaFile;
321 mf->SetHENHMETAFILE((WXHANDLE)hMF);
322 return mf;
323}
324
325wxEnhMetaFileDCImpl::~wxEnhMetaFileDCImpl()
326{
327 // avoid freeing it in the base class dtor
328 m_hDC = 0;
329}
330
331// ----------------------------------------------------------------------------
332// wxEnhMetaFileDC
333// ----------------------------------------------------------------------------
334
335IMPLEMENT_ABSTRACT_CLASS(wxEnhMetaFileDC, wxDC)
336
337wxEnhMetaFileDC::wxEnhMetaFileDC(const wxString& filename,
338 int width, int height,
339 const wxString& description)
340 : wxDC(new wxEnhMetaFileDCImpl(this,
341 filename,
342 width, height,
343 description))
344{
345}
346
347wxEnhMetaFileDC::wxEnhMetaFileDC(const wxDC& referenceDC,
348 const wxString& filename,
349 int width, int height,
350 const wxString& description)
351 : wxDC(new wxEnhMetaFileDCImpl(this,
352 referenceDC,
353 filename,
354 width, height,
355 description))
356{
357}
358
359wxEnhMetaFile *wxEnhMetaFileDC::Close()
360{
361 wxEnhMetaFileDCImpl * const
362 impl = static_cast<wxEnhMetaFileDCImpl *>(GetImpl());
363 wxCHECK_MSG( impl, NULL, wxT("no wxEnhMetaFileDC implementation") );
364
365 return impl->Close();
366}
367
368#if wxUSE_DRAG_AND_DROP
369
370// ----------------------------------------------------------------------------
371// wxEnhMetaFileDataObject
372// ----------------------------------------------------------------------------
373
374wxDataFormat
375wxEnhMetaFileDataObject::GetPreferredFormat(Direction WXUNUSED(dir)) const
376{
377 return wxDF_ENHMETAFILE;
378}
379
380size_t wxEnhMetaFileDataObject::GetFormatCount(Direction WXUNUSED(dir)) const
381{
382 // wxDF_ENHMETAFILE and wxDF_METAFILE
383 return 2;
384}
385
386void wxEnhMetaFileDataObject::GetAllFormats(wxDataFormat *formats,
387 Direction WXUNUSED(dir)) const
388{
389 formats[0] = wxDF_ENHMETAFILE;
390 formats[1] = wxDF_METAFILE;
391}
392
393size_t wxEnhMetaFileDataObject::GetDataSize(const wxDataFormat& format) const
394{
395 if ( format == wxDF_ENHMETAFILE )
396 {
397 // we pass data by handle and not HGLOBAL
398 return 0u;
399 }
400 else
401 {
402 wxASSERT_MSG( format == wxDF_METAFILE, wxT("unsupported format") );
403
404 return sizeof(METAFILEPICT);
405 }
406}
407
408bool wxEnhMetaFileDataObject::GetDataHere(const wxDataFormat& format, void *buf) const
409{
410 wxCHECK_MSG( m_metafile.IsOk(), false, wxT("copying invalid enh metafile") );
411
412 HENHMETAFILE hEMF = (HENHMETAFILE)m_metafile.GetHENHMETAFILE();
413
414 if ( format == wxDF_ENHMETAFILE )
415 {
416 HENHMETAFILE hEMFCopy = ::CopyEnhMetaFile(hEMF, NULL);
417 if ( !hEMFCopy )
418 {
419 wxLogLastError(wxT("CopyEnhMetaFile"));
420
421 return false;
422 }
423
424 *(HENHMETAFILE *)buf = hEMFCopy;
425 }
426 else
427 {
428 wxASSERT_MSG( format == wxDF_METAFILE, wxT("unsupported format") );
429
430 // convert to WMF
431
432 ScreenHDC hdc;
433
434 // first get the buffer size and alloc memory
435 size_t size = ::GetWinMetaFileBits(hEMF, 0, NULL, MM_ANISOTROPIC, hdc);
436 wxCHECK_MSG( size, false, wxT("GetWinMetaFileBits() failed") );
437
438 BYTE *bits = (BYTE *)malloc(size);
439
440 // then get the enh metafile bits
441 if ( !::GetWinMetaFileBits(hEMF, size, bits, MM_ANISOTROPIC, hdc) )
442 {
443 wxLogLastError(wxT("GetWinMetaFileBits"));
444
445 free(bits);
446
447 return false;
448 }
449
450 // and finally convert them to the WMF
451 HMETAFILE hMF = ::SetMetaFileBitsEx(size, bits);
452 free(bits);
453 if ( !hMF )
454 {
455 wxLogLastError(wxT("SetMetaFileBitsEx"));
456
457 return false;
458 }
459
460 METAFILEPICT *mfpict = (METAFILEPICT *)buf;
461
462 wxSize sizeMF = m_metafile.GetSize();
463 mfpict->hMF = hMF;
464 mfpict->mm = MM_ANISOTROPIC;
465 mfpict->xExt = sizeMF.x;
466 mfpict->yExt = sizeMF.y;
467
468 PixelToHIMETRIC(&mfpict->xExt, &mfpict->yExt);
469 }
470
471 return true;
472}
473
474bool wxEnhMetaFileDataObject::SetData(const wxDataFormat& format,
475 size_t WXUNUSED(len),
476 const void *buf)
477{
478 HENHMETAFILE hEMF;
479
480 if ( format == wxDF_ENHMETAFILE )
481 {
482 hEMF = *(HENHMETAFILE *)buf;
483
484 wxCHECK_MSG( hEMF, false, wxT("pasting invalid enh metafile") );
485 }
486 else
487 {
488 wxASSERT_MSG( format == wxDF_METAFILE, wxT("unsupported format") );
489
490 // convert from WMF
491 const METAFILEPICT *mfpict = (const METAFILEPICT *)buf;
492
493 // first get the buffer size
494 size_t size = ::GetMetaFileBitsEx(mfpict->hMF, 0, NULL);
495 wxCHECK_MSG( size, false, wxT("GetMetaFileBitsEx() failed") );
496
497 // then get metafile bits
498 BYTE *bits = (BYTE *)malloc(size);
499 if ( !::GetMetaFileBitsEx(mfpict->hMF, size, bits) )
500 {
501 wxLogLastError(wxT("GetMetaFileBitsEx"));
502
503 free(bits);
504
505 return false;
506 }
507
508 ScreenHDC hdcRef;
509
510 // and finally create an enhanced metafile from them
511 hEMF = ::SetWinMetaFileBits(size, bits, hdcRef, mfpict);
512 free(bits);
513 if ( !hEMF )
514 {
515 wxLogLastError(wxT("SetWinMetaFileBits"));
516
517 return false;
518 }
519 }
520
521 m_metafile.SetHENHMETAFILE((WXHANDLE)hEMF);
522
523 return true;
524}
525
526// ----------------------------------------------------------------------------
527// wxEnhMetaFileSimpleDataObject
528// ----------------------------------------------------------------------------
529
530size_t wxEnhMetaFileSimpleDataObject::GetDataSize() const
531{
532 // we pass data by handle and not HGLOBAL
533 return 0u;
534}
535
536bool wxEnhMetaFileSimpleDataObject::GetDataHere(void *buf) const
537{
538 wxCHECK_MSG( m_metafile.IsOk(), false, wxT("copying invalid enh metafile") );
539
540 HENHMETAFILE hEMF = (HENHMETAFILE)m_metafile.GetHENHMETAFILE();
541
542 HENHMETAFILE hEMFCopy = ::CopyEnhMetaFile(hEMF, NULL);
543 if ( !hEMFCopy )
544 {
545 wxLogLastError(wxT("CopyEnhMetaFile"));
546
547 return false;
548 }
549
550 *(HENHMETAFILE *)buf = hEMFCopy;
551 return true;
552}
553
554bool wxEnhMetaFileSimpleDataObject::SetData(size_t WXUNUSED(len),
555 const void *buf)
556{
557 HENHMETAFILE hEMF = *(HENHMETAFILE *)buf;
558
559 wxCHECK_MSG( hEMF, false, wxT("pasting invalid enh metafile") );
560 m_metafile.SetHENHMETAFILE((WXHANDLE)hEMF);
561
562 return true;
563}
564
565
566#endif // wxUSE_DRAG_AND_DROP
567
568#endif // wxUSE_ENH_METAFILE