]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/enhmeta.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/enhmeta.cpp
3 // Purpose: implementation of wxEnhMetaFileXXX classes
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
26 #if wxUSE_ENH_METAFILE
29 #include "wx/string.h"
35 #include "wx/msw/dc.h"
37 #include "wx/metafile.h"
38 #include "wx/clipbrd.h"
40 #include "wx/msw/private.h"
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 IMPLEMENT_DYNAMIC_CLASS(wxEnhMetaFile
, wxObject
)
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 #define GetEMF() ((HENHMETAFILE)m_hMF)
53 #define GetEMFOf(mf) ((HENHMETAFILE)((mf).m_hMF))
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 // we must pass NULL if the string is empty to metafile functions
60 static inline const wxChar
*GetMetaFileName(const wxString
& fn
)
61 { return !fn
? NULL
: wxMSW_CONV_LPCTSTR(fn
); }
63 // ============================================================================
65 // ============================================================================
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 wxGDIRefData
*wxEnhMetaFile::CreateGDIRefData() const
73 wxFAIL_MSG( wxT("must be implemented if used") );
79 wxEnhMetaFile::CloneGDIRefData(const wxGDIRefData
*WXUNUSED(data
)) const
81 wxFAIL_MSG( wxT("must be implemented if used") );
86 void wxEnhMetaFile::Init()
88 if ( m_filename
.empty() )
92 else // have valid file name, load metafile from it
94 m_hMF
= (WXHANDLE
)::GetEnhMetaFile(m_filename
.t_str());
97 wxLogSysError(_("Failed to load metafile from file \"%s\"."),
103 void wxEnhMetaFile::Assign(const wxEnhMetaFile
& mf
)
110 m_hMF
= (WXHANDLE
)::CopyEnhMetaFile(GetEMFOf(mf
),
111 GetMetaFileName(m_filename
));
114 wxLogLastError(wxT("CopyEnhMetaFile"));
123 void wxEnhMetaFile::Free()
127 if ( !::DeleteEnhMetaFile(GetEMF()) )
129 wxLogLastError(wxT("DeleteEnhMetaFile"));
134 bool wxEnhMetaFile::Play(wxDC
*dc
, wxRect
*rectBound
)
136 wxCHECK_MSG( IsOk(), false, wxT("can't play invalid enhanced metafile") );
137 wxCHECK_MSG( dc
, false, wxT("invalid wxDC in wxEnhMetaFile::Play") );
142 rect
.top
= rectBound
->y
;
143 rect
.left
= rectBound
->x
;
144 rect
.right
= rectBound
->x
+ rectBound
->width
;
145 rect
.bottom
= rectBound
->y
+ rectBound
->height
;
149 wxSize size
= GetSize();
154 rect
.bottom
= size
.y
;
157 wxDCImpl
*impl
= dc
->GetImpl();
158 wxMSWDCImpl
*msw_impl
= wxDynamicCast( impl
, wxMSWDCImpl
);
162 if ( !::PlayEnhMetaFile(GetHdcOf(*msw_impl
), GetEMF(), &rect
) )
164 wxLogLastError(wxT("PlayEnhMetaFile"));
172 wxSize
wxEnhMetaFile::GetSize() const
174 wxSize size
= wxDefaultSize
;
179 if ( !::GetEnhMetaFileHeader(GetEMF(), sizeof(hdr
), &hdr
) )
181 wxLogLastError(wxT("GetEnhMetaFileHeader"));
185 // the width and height are in HIMETRIC (0.01mm) units, transform
187 LONG w
= hdr
.rclFrame
.right
,
188 h
= hdr
.rclFrame
.bottom
;
190 HIMETRICToPixel(&w
, &h
);
200 bool wxEnhMetaFile::SetClipboard(int WXUNUSED(width
), int WXUNUSED(height
))
202 #if wxUSE_DRAG_AND_DROP && wxUSE_CLIPBOARD
203 wxCHECK_MSG( m_hMF
, false, wxT("can't copy invalid metafile to clipboard") );
205 return wxTheClipboard
->AddData(new wxEnhMetaFileDataObject(*this));
206 #else // !wxUSE_DRAG_AND_DROP
207 wxFAIL_MSG(wxT("not implemented"));
209 #endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
212 // ----------------------------------------------------------------------------
213 // wxEnhMetaFileDCImpl
214 // ----------------------------------------------------------------------------
216 class wxEnhMetaFileDCImpl
: public wxMSWDCImpl
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();
228 // obtain a pointer to the new metafile (caller should delete it)
229 wxEnhMetaFile
*Close();
232 virtual void DoGetSize(int *width
, int *height
) const;
235 void Create(HDC hdcRef
,
236 const wxString
& filename
, int width
, int height
,
237 const wxString
& description
);
239 // size passed to ctor and returned by DoGetSize()
245 wxEnhMetaFileDCImpl::wxEnhMetaFileDCImpl( wxEnhMetaFileDC
* owner
,
246 const wxString
& filename
,
247 int width
, int height
,
248 const wxString
& description
)
249 : wxMSWDCImpl( owner
)
251 Create(ScreenHDC(), filename
, width
, height
, description
);
254 wxEnhMetaFileDCImpl::wxEnhMetaFileDCImpl( wxEnhMetaFileDC
* owner
,
255 const wxDC
& referenceDC
,
256 const wxString
& filename
,
257 int width
, int height
,
258 const wxString
& description
)
259 : wxMSWDCImpl( owner
)
261 Create(GetHdcOf(referenceDC
), filename
, width
, height
, description
);
264 void wxEnhMetaFileDCImpl::Create(HDC hdcRef
,
265 const wxString
& filename
,
266 int width
, int height
,
267 const wxString
& description
)
274 if ( width
&& height
)
279 rect
.bottom
= height
;
281 // CreateEnhMetaFile() wants them in HIMETRIC
282 PixelToHIMETRIC(&rect
.right
, &rect
.bottom
, hdcRef
);
288 // GDI will try to find out the size for us (not recommended)
289 pRect
= (LPRECT
)NULL
;
292 m_hDC
= (WXHDC
)::CreateEnhMetaFile(hdcRef
, GetMetaFileName(filename
),
293 pRect
, description
.t_str());
296 wxLogLastError(wxT("CreateEnhMetaFile"));
300 void wxEnhMetaFileDCImpl::DoGetSize(int *width
, int *height
) const
308 wxEnhMetaFile
*wxEnhMetaFileDCImpl::Close()
310 wxCHECK_MSG( IsOk(), NULL
, wxT("invalid wxEnhMetaFileDC") );
312 HENHMETAFILE hMF
= ::CloseEnhMetaFile(GetHdc());
315 wxLogLastError(wxT("CloseEnhMetaFile"));
320 wxEnhMetaFile
*mf
= new wxEnhMetaFile
;
321 mf
->SetHENHMETAFILE((WXHANDLE
)hMF
);
325 wxEnhMetaFileDCImpl::~wxEnhMetaFileDCImpl()
327 // avoid freeing it in the base class dtor
331 // ----------------------------------------------------------------------------
333 // ----------------------------------------------------------------------------
335 IMPLEMENT_ABSTRACT_CLASS(wxEnhMetaFileDC
, wxDC
)
337 wxEnhMetaFileDC::wxEnhMetaFileDC(const wxString
& filename
,
338 int width
, int height
,
339 const wxString
& description
)
340 : wxDC(new wxEnhMetaFileDCImpl(this,
347 wxEnhMetaFileDC::wxEnhMetaFileDC(const wxDC
& referenceDC
,
348 const wxString
& filename
,
349 int width
, int height
,
350 const wxString
& description
)
351 : wxDC(new wxEnhMetaFileDCImpl(this,
359 wxEnhMetaFile
*wxEnhMetaFileDC::Close()
361 wxEnhMetaFileDCImpl
* const
362 impl
= static_cast<wxEnhMetaFileDCImpl
*>(GetImpl());
363 wxCHECK_MSG( impl
, NULL
, wxT("no wxEnhMetaFileDC implementation") );
365 return impl
->Close();
368 #if wxUSE_DRAG_AND_DROP
370 // ----------------------------------------------------------------------------
371 // wxEnhMetaFileDataObject
372 // ----------------------------------------------------------------------------
375 wxEnhMetaFileDataObject::GetPreferredFormat(Direction
WXUNUSED(dir
)) const
377 return wxDF_ENHMETAFILE
;
380 size_t wxEnhMetaFileDataObject::GetFormatCount(Direction
WXUNUSED(dir
)) const
382 // wxDF_ENHMETAFILE and wxDF_METAFILE
386 void wxEnhMetaFileDataObject::GetAllFormats(wxDataFormat
*formats
,
387 Direction
WXUNUSED(dir
)) const
389 formats
[0] = wxDF_ENHMETAFILE
;
390 formats
[1] = wxDF_METAFILE
;
393 size_t wxEnhMetaFileDataObject::GetDataSize(const wxDataFormat
& format
) const
395 if ( format
== wxDF_ENHMETAFILE
)
397 // we pass data by handle and not HGLOBAL
402 wxASSERT_MSG( format
== wxDF_METAFILE
, wxT("unsupported format") );
404 return sizeof(METAFILEPICT
);
408 bool wxEnhMetaFileDataObject::GetDataHere(const wxDataFormat
& format
, void *buf
) const
410 wxCHECK_MSG( m_metafile
.IsOk(), false, wxT("copying invalid enh metafile") );
412 HENHMETAFILE hEMF
= (HENHMETAFILE
)m_metafile
.GetHENHMETAFILE();
414 if ( format
== wxDF_ENHMETAFILE
)
416 HENHMETAFILE hEMFCopy
= ::CopyEnhMetaFile(hEMF
, NULL
);
419 wxLogLastError(wxT("CopyEnhMetaFile"));
424 *(HENHMETAFILE
*)buf
= hEMFCopy
;
428 wxASSERT_MSG( format
== wxDF_METAFILE
, wxT("unsupported format") );
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") );
438 BYTE
*bits
= (BYTE
*)malloc(size
);
440 // then get the enh metafile bits
441 if ( !::GetWinMetaFileBits(hEMF
, size
, bits
, MM_ANISOTROPIC
, hdc
) )
443 wxLogLastError(wxT("GetWinMetaFileBits"));
450 // and finally convert them to the WMF
451 HMETAFILE hMF
= ::SetMetaFileBitsEx(size
, bits
);
455 wxLogLastError(wxT("SetMetaFileBitsEx"));
460 METAFILEPICT
*mfpict
= (METAFILEPICT
*)buf
;
462 wxSize sizeMF
= m_metafile
.GetSize();
464 mfpict
->mm
= MM_ANISOTROPIC
;
465 mfpict
->xExt
= sizeMF
.x
;
466 mfpict
->yExt
= sizeMF
.y
;
468 PixelToHIMETRIC(&mfpict
->xExt
, &mfpict
->yExt
);
474 bool wxEnhMetaFileDataObject::SetData(const wxDataFormat
& format
,
475 size_t WXUNUSED(len
),
480 if ( format
== wxDF_ENHMETAFILE
)
482 hEMF
= *(HENHMETAFILE
*)buf
;
484 wxCHECK_MSG( hEMF
, false, wxT("pasting invalid enh metafile") );
488 wxASSERT_MSG( format
== wxDF_METAFILE
, wxT("unsupported format") );
491 const METAFILEPICT
*mfpict
= (const METAFILEPICT
*)buf
;
493 // first get the buffer size
494 size_t size
= ::GetMetaFileBitsEx(mfpict
->hMF
, 0, NULL
);
495 wxCHECK_MSG( size
, false, wxT("GetMetaFileBitsEx() failed") );
497 // then get metafile bits
498 BYTE
*bits
= (BYTE
*)malloc(size
);
499 if ( !::GetMetaFileBitsEx(mfpict
->hMF
, size
, bits
) )
501 wxLogLastError(wxT("GetMetaFileBitsEx"));
510 // and finally create an enhanced metafile from them
511 hEMF
= ::SetWinMetaFileBits(size
, bits
, hdcRef
, mfpict
);
515 wxLogLastError(wxT("SetWinMetaFileBits"));
521 m_metafile
.SetHENHMETAFILE((WXHANDLE
)hEMF
);
526 // ----------------------------------------------------------------------------
527 // wxEnhMetaFileSimpleDataObject
528 // ----------------------------------------------------------------------------
530 size_t wxEnhMetaFileSimpleDataObject::GetDataSize() const
532 // we pass data by handle and not HGLOBAL
536 bool wxEnhMetaFileSimpleDataObject::GetDataHere(void *buf
) const
538 wxCHECK_MSG( m_metafile
.IsOk(), false, wxT("copying invalid enh metafile") );
540 HENHMETAFILE hEMF
= (HENHMETAFILE
)m_metafile
.GetHENHMETAFILE();
542 HENHMETAFILE hEMFCopy
= ::CopyEnhMetaFile(hEMF
, NULL
);
545 wxLogLastError(wxT("CopyEnhMetaFile"));
550 *(HENHMETAFILE
*)buf
= hEMFCopy
;
554 bool wxEnhMetaFileSimpleDataObject::SetData(size_t WXUNUSED(len
),
557 HENHMETAFILE hEMF
= *(HENHMETAFILE
*)buf
;
559 wxCHECK_MSG( hEMF
, false, wxT("pasting invalid enh metafile") );
560 m_metafile
.SetHENHMETAFILE((WXHANDLE
)hEMF
);
566 #endif // wxUSE_DRAG_AND_DROP
568 #endif // wxUSE_ENH_METAFILE