]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/metafile.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/metafile.cpp
3 // Purpose: wxMetafileDC etc.
4 // Author: Julian Smart
5 // Modified by: VZ 07.01.00: implemented wxMetaFileDataObject
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
36 #include "wx/metafile.h"
38 #if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH)
40 #include "wx/clipbrd.h"
41 #include "wx/msw/private.h"
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
)
51 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
)
53 // ============================================================================
55 // ============================================================================
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
63 * Currently, the only purpose for making a metafile is to put
64 * it on the clipboard.
67 wxMetafileRefData::wxMetafileRefData()
70 m_windowsMappingMode
= wxMM_ANISOTROPIC
;
71 m_width
= m_height
= 0;
74 wxMetafileRefData::~wxMetafileRefData()
78 DeleteMetaFile((HMETAFILE
) m_metafile
);
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 wxMetafile::wxMetafile(const wxString
& file
)
89 m_refData
= new wxMetafileRefData
;
91 M_METAFILEDATA
->m_windowsMappingMode
= wxMM_ANISOTROPIC
;
92 M_METAFILEDATA
->m_metafile
= 0;
94 M_METAFILEDATA
->m_metafile
= (WXHANDLE
) GetMetaFile(file
);
97 wxMetafile::~wxMetafile()
101 bool wxMetafile::SetClipboard(int width
, int height
)
109 bool alreadyOpen
= wxClipboardOpen();
113 if (!wxEmptyClipboard())
116 bool success
= wxSetClipboardData(wxDF_METAFILE
, this, width
,height
);
124 bool wxMetafile::Play(wxDC
*dc
)
131 if (dc
->GetHDC() && M_METAFILEDATA
->m_metafile
)
133 if ( !::PlayMetaFile(GetHdcOf(*dc
), (HMETAFILE
)
134 M_METAFILEDATA
->m_metafile
) )
136 wxLogLastError(_T("PlayMetaFile"));
145 void wxMetafile::SetHMETAFILE(WXHANDLE mf
)
148 m_refData
= new wxMetafileRefData
;
150 M_METAFILEDATA
->m_metafile
= mf
;
153 void wxMetafile::SetWindowsMappingMode(int mm
)
156 m_refData
= new wxMetafileRefData
;
158 M_METAFILEDATA
->m_windowsMappingMode
= mm
;
161 // ----------------------------------------------------------------------------
162 // Metafile device context
163 // ----------------------------------------------------------------------------
165 // Original constructor that does not takes origin and extent. If you use this,
166 // *DO* give origin/extent arguments to wxMakeMetafilePlaceable.
167 wxMetafileDC::wxMetafileDC(const wxString
& file
)
176 if (!file
.IsNull() && wxFileExists(file
))
179 if (!file
.IsNull() && (file
!= wxEmptyString
))
180 m_hDC
= (WXHDC
) CreateMetaFile(file
);
182 m_hDC
= (WXHDC
) CreateMetaFile(NULL
);
184 m_ok
= (m_hDC
!= (WXHDC
) 0) ;
186 // Actual Windows mapping mode, for future reference.
187 m_windowsMappingMode
= wxMM_TEXT
;
189 SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct)
192 // New constructor that takes origin and extent. If you use this, don't
193 // give origin/extent arguments to wxMakeMetafilePlaceable.
194 wxMetafileDC::wxMetafileDC(const wxString
& file
, int xext
, int yext
, int xorg
, int yorg
)
200 if ( !file
.IsEmpty() && wxFileExists(file
))
202 m_hDC
= (WXHDC
) CreateMetaFile(file
);
206 ::SetWindowOrgEx((HDC
) m_hDC
,xorg
,yorg
, NULL
);
207 ::SetWindowExtEx((HDC
) m_hDC
,xext
,yext
, NULL
);
209 // Actual Windows mapping mode, for future reference.
210 m_windowsMappingMode
= wxMM_ANISOTROPIC
;
212 SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct)
215 wxMetafileDC::~wxMetafileDC()
220 void wxMetafileDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
221 long *descent
, long *externalLeading
, wxFont
*theFont
, bool WXUNUSED(use16bit
)) const
223 wxFont
*fontToUse
= theFont
;
225 fontToUse
= (wxFont
*) &m_font
;
227 HDC dc
= GetDC(NULL
);
231 ::GetTextExtentPoint32(dc
, WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
232 GetTextMetrics(dc
, &tm
);
241 *descent
= tm
.tmDescent
;
242 if ( externalLeading
)
243 *externalLeading
= tm
.tmExternalLeading
;
246 void wxMetafileDC::DoGetSize(int *width
, int *height
) const
248 wxCHECK_RET( m_refData
, _T("invalid wxMetafileDC") );
251 *width
= M_METAFILEDATA
->m_width
;
253 *height
= M_METAFILEDATA
->m_height
;
256 wxMetafile
*wxMetafileDC::Close()
258 SelectOldObjects(m_hDC
);
259 HANDLE mf
= CloseMetaFile((HDC
) m_hDC
);
263 wxMetafile
*wx_mf
= new wxMetafile
;
264 wx_mf
->SetHMETAFILE((WXHANDLE
) mf
);
265 wx_mf
->SetWindowsMappingMode(m_windowsMappingMode
);
271 void wxMetafileDC::SetMapMode(int mode
)
273 m_mappingMode
= mode
;
275 // int pixel_width = 0;
276 // int pixel_height = 0;
278 // int mm_height = 0;
280 float mm2pixelsX
= 10.0;
281 float mm2pixelsY
= 10.0;
287 m_logicalScaleX
= (float)(twips2mm
* mm2pixelsX
);
288 m_logicalScaleY
= (float)(twips2mm
* mm2pixelsY
);
293 m_logicalScaleX
= (float)(pt2mm
* mm2pixelsX
);
294 m_logicalScaleY
= (float)(pt2mm
* mm2pixelsY
);
299 m_logicalScaleX
= mm2pixelsX
;
300 m_logicalScaleY
= mm2pixelsY
;
305 m_logicalScaleX
= (float)(mm2pixelsX
/10.0);
306 m_logicalScaleY
= (float)(mm2pixelsY
/10.0);
312 m_logicalScaleX
= 1.0;
313 m_logicalScaleY
= 1.0;
319 // ----------------------------------------------------------------------------
320 // wxMakeMetafilePlaceable
321 // ----------------------------------------------------------------------------
332 struct mfPLACEABLEHEADER
{
341 struct mfPLACEABLEHEADER
{
352 * Pass filename of existing non-placeable metafile, and bounding box.
353 * Adds a placeable metafile header, sets the mapping mode to anisotropic,
354 * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode.
358 bool wxMakeMetafilePlaceable(const wxString
& filename
, float scale
)
360 return wxMakeMetafilePlaceable(filename
, 0, 0, 0, 0, scale
, false);
363 bool wxMakeMetafilePlaceable(const wxString
& filename
, int x1
, int y1
, int x2
, int y2
, float scale
, bool useOriginAndExtent
)
365 // I'm not sure if this is the correct way of suggesting a scale
366 // to the client application, but it's the only way I can find.
367 int unitsPerInch
= (int)(576/scale
);
369 mfPLACEABLEHEADER header
;
370 header
.key
= 0x9AC6CDD7L
;
372 header
.bbox
.left
= (int)(x1
);
373 header
.bbox
.top
= (int)(y1
);
374 header
.bbox
.right
= (int)(x2
);
375 header
.bbox
.bottom
= (int)(y2
);
376 header
.inch
= unitsPerInch
;
379 // Calculate checksum
381 mfPLACEABLEHEADER
*pMFHead
= &header
;
382 for (p
=(WORD
*)pMFHead
,pMFHead
-> checksum
= 0;
383 p
< (WORD
*)&pMFHead
->checksum
; ++p
)
384 pMFHead
->checksum
^= *p
;
386 FILE *fd
= wxFopen(filename
.fn_str(), _T("rb"));
387 if (!fd
) return false;
389 wxChar tempFileBuf
[256];
390 wxGetTempFileName(wxT("mf"), tempFileBuf
);
391 FILE *fHandle
= wxFopen(wxFNCONV(tempFileBuf
), _T("wb"));
394 fwrite((void *)&header
, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER
), fHandle
);
396 // Calculate origin and extent
399 int extentX
= x2
- x1
;
400 int extentY
= (y2
- y1
);
402 // Read metafile header and write
403 METAHEADER metaHeader
;
404 fread((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fd
);
406 if (useOriginAndExtent
)
407 metaHeader
.mtSize
+= 15;
409 metaHeader
.mtSize
+= 5;
411 fwrite((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fHandle
);
413 // Write SetMapMode, SetWindowOrigin and SetWindowExt records
415 char originBuffer
[10];
416 char extentBuffer
[10];
417 METARECORD
*modeRecord
= (METARECORD
*)&modeBuffer
;
419 METARECORD
*originRecord
= (METARECORD
*)&originBuffer
;
420 METARECORD
*extentRecord
= (METARECORD
*)&extentBuffer
;
422 modeRecord
->rdSize
= 4;
423 modeRecord
->rdFunction
= META_SETMAPMODE
;
424 modeRecord
->rdParm
[0] = MM_ANISOTROPIC
;
426 originRecord
->rdSize
= 5;
427 originRecord
->rdFunction
= META_SETWINDOWORG
;
428 originRecord
->rdParm
[0] = originY
;
429 originRecord
->rdParm
[1] = originX
;
431 extentRecord
->rdSize
= 5;
432 extentRecord
->rdFunction
= META_SETWINDOWEXT
;
433 extentRecord
->rdParm
[0] = extentY
;
434 extentRecord
->rdParm
[1] = extentX
;
436 fwrite((void *)modeBuffer
, sizeof(char), 8, fHandle
);
438 if (useOriginAndExtent
)
440 fwrite((void *)originBuffer
, sizeof(char), 10, fHandle
);
441 fwrite((void *)extentBuffer
, sizeof(char), 10, fHandle
);
455 wxRemoveFile(filename
);
456 wxCopyFile(tempFileBuf
, filename
);
457 wxRemoveFile(tempFileBuf
);
462 #if wxUSE_DRAG_AND_DROP
464 // ----------------------------------------------------------------------------
465 // wxMetafileDataObject
466 // ----------------------------------------------------------------------------
468 size_t wxMetafileDataObject::GetDataSize() const
470 return sizeof(METAFILEPICT
);
473 bool wxMetafileDataObject::GetDataHere(void *buf
) const
475 METAFILEPICT
*mfpict
= (METAFILEPICT
*)buf
;
476 const wxMetafile
& mf
= GetMetafile();
478 wxCHECK_MSG( mf
.GetHMETAFILE(), false, _T("copying invalid metafile") );
480 // doesn't seem to work with any other mapping mode...
481 mfpict
->mm
= MM_ANISOTROPIC
; //mf.GetWindowsMappingMode();
482 mfpict
->xExt
= mf
.GetWidth();
483 mfpict
->yExt
= mf
.GetHeight();
485 // transform the picture size to HIMETRIC units (0.01mm) - as we don't know
486 // what DC the picture will be rendered to, use the default display one
487 PixelToHIMETRIC(&mfpict
->xExt
, &mfpict
->yExt
);
489 mfpict
->hMF
= CopyMetaFile((HMETAFILE
)mf
.GetHMETAFILE(), NULL
);
494 bool wxMetafileDataObject::SetData(size_t WXUNUSED(len
), const void *buf
)
496 const METAFILEPICT
*mfpict
= (const METAFILEPICT
*)buf
;
499 mf
.SetWindowsMappingMode(mfpict
->mm
);
501 LONG w
= mfpict
->xExt
,
503 if ( mfpict
->mm
== MM_ANISOTROPIC
)
505 // in this case xExt and yExt contain suggested size in HIMETRIC units
506 // (0.01 mm) - transform this to something more reasonable (pixels)
507 HIMETRICToPixel(&w
, &h
);
512 mf
.SetHMETAFILE((WXHANDLE
)mfpict
->hMF
);
514 wxCHECK_MSG( mfpict
->hMF
, false, _T("pasting invalid metafile") );
521 #endif // wxUSE_DRAG_AND_DROP
523 #endif // wxUSE_METAFILE