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