]>
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
8 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #if wxUSE_ENH_METAFILE
30 #include "wx/string.h"
36 #include "wx/msw/dc.h"
38 #include "wx/metafile.h"
39 #include "wx/clipbrd.h"
41 #include "wx/msw/private.h"
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 IMPLEMENT_DYNAMIC_CLASS(wxEnhMetaFile
, wxObject
)
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 #define GetEMF() ((HENHMETAFILE)m_hMF)
54 #define GetEMFOf(mf) ((HENHMETAFILE)((mf).m_hMF))
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 // we must pass NULL if the string is empty to metafile functions
61 static inline const wxChar
*GetMetaFileName(const wxString
& fn
)
62 { return !fn
? NULL
: wxMSW_CONV_LPCTSTR(fn
); }
64 // ============================================================================
66 // ============================================================================
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
72 wxGDIRefData
*wxEnhMetaFile::CreateGDIRefData() const
74 wxFAIL_MSG( wxT("must be implemented if used") );
80 wxEnhMetaFile::CloneGDIRefData(const wxGDIRefData
*WXUNUSED(data
)) const
82 wxFAIL_MSG( wxT("must be implemented if used") );
87 void wxEnhMetaFile::Init()
89 if ( m_filename
.empty() )
93 else // have valid file name, load metafile from it
95 m_hMF
= (WXHANDLE
)::GetEnhMetaFile(m_filename
.t_str());
98 wxLogSysError(_("Failed to load metafile from file \"%s\"."),
104 void wxEnhMetaFile::Assign(const wxEnhMetaFile
& mf
)
111 m_hMF
= (WXHANDLE
)::CopyEnhMetaFile(GetEMFOf(mf
),
112 GetMetaFileName(m_filename
));
115 wxLogLastError(wxT("CopyEnhMetaFile"));
124 void wxEnhMetaFile::Free()
128 if ( !::DeleteEnhMetaFile(GetEMF()) )
130 wxLogLastError(wxT("DeleteEnhMetaFile"));
135 bool wxEnhMetaFile::Play(wxDC
*dc
, wxRect
*rectBound
)
137 wxCHECK_MSG( IsOk(), false, wxT("can't play invalid enhanced metafile") );
138 wxCHECK_MSG( dc
, false, wxT("invalid wxDC in wxEnhMetaFile::Play") );
143 rect
.top
= rectBound
->y
;
144 rect
.left
= rectBound
->x
;
145 rect
.right
= rectBound
->x
+ rectBound
->width
;
146 rect
.bottom
= rectBound
->y
+ rectBound
->height
;
150 wxSize size
= GetSize();
155 rect
.bottom
= size
.y
;
158 wxDCImpl
*impl
= dc
->GetImpl();
159 wxMSWDCImpl
*msw_impl
= wxDynamicCast( impl
, wxMSWDCImpl
);
163 if ( !::PlayEnhMetaFile(GetHdcOf(*msw_impl
), GetEMF(), &rect
) )
165 wxLogLastError(wxT("PlayEnhMetaFile"));
173 wxSize
wxEnhMetaFile::GetSize() const
175 wxSize size
= wxDefaultSize
;
180 if ( !::GetEnhMetaFileHeader(GetEMF(), sizeof(hdr
), &hdr
) )
182 wxLogLastError(wxT("GetEnhMetaFileHeader"));
186 // the width and height are in HIMETRIC (0.01mm) units, transform
188 LONG w
= hdr
.rclFrame
.right
,
189 h
= hdr
.rclFrame
.bottom
;
191 HIMETRICToPixel(&w
, &h
);
201 bool wxEnhMetaFile::SetClipboard(int WXUNUSED(width
), int WXUNUSED(height
))
203 #if wxUSE_DRAG_AND_DROP && wxUSE_CLIPBOARD
204 wxCHECK_MSG( m_hMF
, false, wxT("can't copy invalid metafile to clipboard") );
206 return wxTheClipboard
->AddData(new wxEnhMetaFileDataObject(*this));
207 #else // !wxUSE_DRAG_AND_DROP
208 wxFAIL_MSG(wxT("not implemented"));
210 #endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
213 // ----------------------------------------------------------------------------
214 // wxEnhMetaFileDCImpl
215 // ----------------------------------------------------------------------------
217 class wxEnhMetaFileDCImpl
: public wxMSWDCImpl
220 wxEnhMetaFileDCImpl( wxEnhMetaFileDC
*owner
,
221 const wxString
& filename
, int width
, int height
,
222 const wxString
& description
);
223 wxEnhMetaFileDCImpl( wxEnhMetaFileDC
*owner
,
224 const wxDC
& referenceDC
,
225 const wxString
& filename
, int width
, int height
,
226 const wxString
& description
);
227 virtual ~wxEnhMetaFileDCImpl();
229 // obtain a pointer to the new metafile (caller should delete it)
230 wxEnhMetaFile
*Close();
233 virtual void DoGetSize(int *width
, int *height
) const;
236 void Create(HDC hdcRef
,
237 const wxString
& filename
, int width
, int height
,
238 const wxString
& description
);
240 // size passed to ctor and returned by DoGetSize()
246 wxEnhMetaFileDCImpl::wxEnhMetaFileDCImpl( wxEnhMetaFileDC
* owner
,
247 const wxString
& filename
,
248 int width
, int height
,
249 const wxString
& description
)
250 : wxMSWDCImpl( owner
)
252 Create(ScreenHDC(), filename
, width
, height
, description
);
255 wxEnhMetaFileDCImpl::wxEnhMetaFileDCImpl( wxEnhMetaFileDC
* owner
,
256 const wxDC
& referenceDC
,
257 const wxString
& filename
,
258 int width
, int height
,
259 const wxString
& description
)
260 : wxMSWDCImpl( owner
)
262 Create(GetHdcOf(referenceDC
), filename
, width
, height
, description
);
265 void wxEnhMetaFileDCImpl::Create(HDC hdcRef
,
266 const wxString
& filename
,
267 int width
, int height
,
268 const wxString
& description
)
275 if ( width
&& height
)
280 rect
.bottom
= height
;
282 // CreateEnhMetaFile() wants them in HIMETRIC
283 PixelToHIMETRIC(&rect
.right
, &rect
.bottom
, hdcRef
);
289 // GDI will try to find out the size for us (not recommended)
290 pRect
= (LPRECT
)NULL
;
293 m_hDC
= (WXHDC
)::CreateEnhMetaFile(hdcRef
, GetMetaFileName(filename
),
294 pRect
, description
.t_str());
297 wxLogLastError(wxT("CreateEnhMetaFile"));
301 void wxEnhMetaFileDCImpl::DoGetSize(int *width
, int *height
) const
309 wxEnhMetaFile
*wxEnhMetaFileDCImpl::Close()
311 wxCHECK_MSG( IsOk(), NULL
, wxT("invalid wxEnhMetaFileDC") );
313 HENHMETAFILE hMF
= ::CloseEnhMetaFile(GetHdc());
316 wxLogLastError(wxT("CloseEnhMetaFile"));
321 wxEnhMetaFile
*mf
= new wxEnhMetaFile
;
322 mf
->SetHENHMETAFILE((WXHANDLE
)hMF
);
326 wxEnhMetaFileDCImpl::~wxEnhMetaFileDCImpl()
328 // avoid freeing it in the base class dtor
332 // ----------------------------------------------------------------------------
334 // ----------------------------------------------------------------------------
336 IMPLEMENT_ABSTRACT_CLASS(wxEnhMetaFileDC
, wxDC
)
338 wxEnhMetaFileDC::wxEnhMetaFileDC(const wxString
& filename
,
339 int width
, int height
,
340 const wxString
& description
)
341 : wxDC(new wxEnhMetaFileDCImpl(this,
348 wxEnhMetaFileDC::wxEnhMetaFileDC(const wxDC
& referenceDC
,
349 const wxString
& filename
,
350 int width
, int height
,
351 const wxString
& description
)
352 : wxDC(new wxEnhMetaFileDCImpl(this,
360 wxEnhMetaFile
*wxEnhMetaFileDC::Close()
362 wxEnhMetaFileDCImpl
* const
363 impl
= static_cast<wxEnhMetaFileDCImpl
*>(GetImpl());
364 wxCHECK_MSG( impl
, NULL
, wxT("no wxEnhMetaFileDC implementation") );
366 return impl
->Close();
369 #if wxUSE_DRAG_AND_DROP
371 // ----------------------------------------------------------------------------
372 // wxEnhMetaFileDataObject
373 // ----------------------------------------------------------------------------
376 wxEnhMetaFileDataObject::GetPreferredFormat(Direction
WXUNUSED(dir
)) const
378 return wxDF_ENHMETAFILE
;
381 size_t wxEnhMetaFileDataObject::GetFormatCount(Direction
WXUNUSED(dir
)) const
383 // wxDF_ENHMETAFILE and wxDF_METAFILE
387 void wxEnhMetaFileDataObject::GetAllFormats(wxDataFormat
*formats
,
388 Direction
WXUNUSED(dir
)) const
390 formats
[0] = wxDF_ENHMETAFILE
;
391 formats
[1] = wxDF_METAFILE
;
394 size_t wxEnhMetaFileDataObject::GetDataSize(const wxDataFormat
& format
) const
396 if ( format
== wxDF_ENHMETAFILE
)
398 // we pass data by handle and not HGLOBAL
403 wxASSERT_MSG( format
== wxDF_METAFILE
, wxT("unsupported format") );
405 return sizeof(METAFILEPICT
);
409 bool wxEnhMetaFileDataObject::GetDataHere(const wxDataFormat
& format
, void *buf
) const
411 wxCHECK_MSG( m_metafile
.IsOk(), false, wxT("copying invalid enh metafile") );
413 HENHMETAFILE hEMF
= (HENHMETAFILE
)m_metafile
.GetHENHMETAFILE();
415 if ( format
== wxDF_ENHMETAFILE
)
417 HENHMETAFILE hEMFCopy
= ::CopyEnhMetaFile(hEMF
, NULL
);
420 wxLogLastError(wxT("CopyEnhMetaFile"));
425 *(HENHMETAFILE
*)buf
= hEMFCopy
;
429 wxASSERT_MSG( format
== wxDF_METAFILE
, wxT("unsupported format") );
435 // first get the buffer size and alloc memory
436 size_t size
= ::GetWinMetaFileBits(hEMF
, 0, NULL
, MM_ANISOTROPIC
, hdc
);
437 wxCHECK_MSG( size
, false, wxT("GetWinMetaFileBits() failed") );
439 BYTE
*bits
= (BYTE
*)malloc(size
);
441 // then get the enh metafile bits
442 if ( !::GetWinMetaFileBits(hEMF
, size
, bits
, MM_ANISOTROPIC
, hdc
) )
444 wxLogLastError(wxT("GetWinMetaFileBits"));
451 // and finally convert them to the WMF
452 HMETAFILE hMF
= ::SetMetaFileBitsEx(size
, bits
);
456 wxLogLastError(wxT("SetMetaFileBitsEx"));
461 METAFILEPICT
*mfpict
= (METAFILEPICT
*)buf
;
463 wxSize sizeMF
= m_metafile
.GetSize();
465 mfpict
->mm
= MM_ANISOTROPIC
;
466 mfpict
->xExt
= sizeMF
.x
;
467 mfpict
->yExt
= sizeMF
.y
;
469 PixelToHIMETRIC(&mfpict
->xExt
, &mfpict
->yExt
);
475 bool wxEnhMetaFileDataObject::SetData(const wxDataFormat
& format
,
476 size_t WXUNUSED(len
),
481 if ( format
== wxDF_ENHMETAFILE
)
483 hEMF
= *(HENHMETAFILE
*)buf
;
485 wxCHECK_MSG( hEMF
, false, wxT("pasting invalid enh metafile") );
489 wxASSERT_MSG( format
== wxDF_METAFILE
, wxT("unsupported format") );
492 const METAFILEPICT
*mfpict
= (const METAFILEPICT
*)buf
;
494 // first get the buffer size
495 size_t size
= ::GetMetaFileBitsEx(mfpict
->hMF
, 0, NULL
);
496 wxCHECK_MSG( size
, false, wxT("GetMetaFileBitsEx() failed") );
498 // then get metafile bits
499 BYTE
*bits
= (BYTE
*)malloc(size
);
500 if ( !::GetMetaFileBitsEx(mfpict
->hMF
, size
, bits
) )
502 wxLogLastError(wxT("GetMetaFileBitsEx"));
511 // and finally create an enhanced metafile from them
512 hEMF
= ::SetWinMetaFileBits(size
, bits
, hdcRef
, mfpict
);
516 wxLogLastError(wxT("SetWinMetaFileBits"));
522 m_metafile
.SetHENHMETAFILE((WXHANDLE
)hEMF
);
527 // ----------------------------------------------------------------------------
528 // wxEnhMetaFileSimpleDataObject
529 // ----------------------------------------------------------------------------
531 size_t wxEnhMetaFileSimpleDataObject::GetDataSize() const
533 // we pass data by handle and not HGLOBAL
537 bool wxEnhMetaFileSimpleDataObject::GetDataHere(void *buf
) const
539 wxCHECK_MSG( m_metafile
.IsOk(), false, wxT("copying invalid enh metafile") );
541 HENHMETAFILE hEMF
= (HENHMETAFILE
)m_metafile
.GetHENHMETAFILE();
543 HENHMETAFILE hEMFCopy
= ::CopyEnhMetaFile(hEMF
, NULL
);
546 wxLogLastError(wxT("CopyEnhMetaFile"));
551 *(HENHMETAFILE
*)buf
= hEMFCopy
;
555 bool wxEnhMetaFileSimpleDataObject::SetData(size_t WXUNUSED(len
),
558 HENHMETAFILE hEMF
= *(HENHMETAFILE
*)buf
;
560 wxCHECK_MSG( hEMF
, false, wxT("pasting invalid enh metafile") );
561 m_metafile
.SetHENHMETAFILE((WXHANDLE
)hEMF
);
567 #endif // wxUSE_DRAG_AND_DROP
569 #endif // wxUSE_ENH_METAFILE