]>
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 and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "metafile.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
42 #include "wx/metafile.h"
43 #include "wx/clipbrd.h"
44 #include "wx/msw/private.h"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 IMPLEMENT_DYNAMIC_CLASS(wxMetafile
, wxObject
)
54 IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC
, wxDC
)
56 // ============================================================================
58 // ============================================================================
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
66 * Currently, the only purpose for making a metafile is to put
67 * it on the clipboard.
70 wxMetafileRefData::wxMetafileRefData()
73 m_windowsMappingMode
= wxMM_ANISOTROPIC
;
74 m_width
= m_height
= 0;
77 wxMetafileRefData::~wxMetafileRefData()
81 DeleteMetaFile((HMETAFILE
) m_metafile
);
86 // ----------------------------------------------------------------------------
88 // ----------------------------------------------------------------------------
90 wxMetafile::wxMetafile(const wxString
& file
)
92 m_refData
= new wxMetafileRefData
;
94 M_METAFILEDATA
->m_windowsMappingMode
= wxMM_ANISOTROPIC
;
95 M_METAFILEDATA
->m_metafile
= 0;
96 if (!file
.IsNull() && (file
.Cmp(wxT("")) == 0))
97 M_METAFILEDATA
->m_metafile
= (WXHANDLE
) GetMetaFile(file
);
100 wxMetafile::~wxMetafile()
104 bool wxMetafile::SetClipboard(int width
, int height
)
109 bool alreadyOpen
= wxClipboardOpen();
113 if (!wxEmptyClipboard())
116 bool success
= wxSetClipboardData(wxDF_METAFILE
, this, width
,height
);
123 bool wxMetafile::Play(wxDC
*dc
)
130 if (dc
->GetHDC() && M_METAFILEDATA
->m_metafile
)
131 PlayMetaFile(GetHdcOf(*dc
), (HMETAFILE
) M_METAFILEDATA
->m_metafile
);
138 void wxMetafile::SetHMETAFILE(WXHANDLE mf
)
141 m_refData
= new wxMetafileRefData
;
143 M_METAFILEDATA
->m_metafile
= mf
;
146 void wxMetafile::SetWindowsMappingMode(int mm
)
149 m_refData
= new wxMetafileRefData
;
151 M_METAFILEDATA
->m_windowsMappingMode
= mm
;
154 // ----------------------------------------------------------------------------
155 // Metafile device context
156 // ----------------------------------------------------------------------------
158 // Original constructor that does not takes origin and extent. If you use this,
159 // *DO* give origin/extent arguments to wxMakeMetafilePlaceable.
160 wxMetafileDC::wxMetafileDC(const wxString
& file
)
169 if (!file
.IsNull() && wxFileExists(file
))
172 if (!file
.IsNull() && (file
!= wxT("")))
173 m_hDC
= (WXHDC
) CreateMetaFile(file
);
175 m_hDC
= (WXHDC
) CreateMetaFile(NULL
);
177 m_ok
= (m_hDC
!= (WXHDC
) 0) ;
179 // Actual Windows mapping mode, for future reference.
180 m_windowsMappingMode
= wxMM_TEXT
;
182 SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct)
185 // New constructor that takes origin and extent. If you use this, don't
186 // give origin/extent arguments to wxMakeMetafilePlaceable.
187 wxMetafileDC::wxMetafileDC(const wxString
& file
, int xext
, int yext
, int xorg
, int yorg
)
193 if ( !!file
&& wxFileExists(file
))
195 m_hDC
= (WXHDC
) CreateMetaFile(file
);
199 ::SetWindowOrgEx((HDC
) m_hDC
,xorg
,yorg
, NULL
);
200 ::SetWindowExtEx((HDC
) m_hDC
,xext
,yext
, NULL
);
202 // Actual Windows mapping mode, for future reference.
203 m_windowsMappingMode
= wxMM_ANISOTROPIC
;
205 SetMapMode(wxMM_TEXT
); // NOTE: does not set HDC mapmode (this is correct)
208 wxMetafileDC::~wxMetafileDC()
213 void wxMetafileDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
214 long *descent
, long *externalLeading
, wxFont
*theFont
, bool use16bit
) const
216 wxFont
*fontToUse
= theFont
;
218 fontToUse
= (wxFont
*) &m_font
;
220 HDC dc
= GetDC(NULL
);
224 GetTextExtentPoint(dc
, WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
225 GetTextMetrics(dc
, &tm
);
234 *descent
= tm
.tmDescent
;
235 if ( externalLeading
)
236 *externalLeading
= tm
.tmExternalLeading
;
239 wxMetafile
*wxMetafileDC::Close()
241 SelectOldObjects(m_hDC
);
242 HANDLE mf
= CloseMetaFile((HDC
) m_hDC
);
246 wxMetafile
*wx_mf
= new wxMetafile
;
247 wx_mf
->SetHMETAFILE((WXHANDLE
) mf
);
248 wx_mf
->SetWindowsMappingMode(m_windowsMappingMode
);
254 void wxMetafileDC::SetMapMode(int mode
)
256 m_mappingMode
= mode
;
258 // int pixel_width = 0;
259 // int pixel_height = 0;
261 // int mm_height = 0;
263 float mm2pixelsX
= 10.0;
264 float mm2pixelsY
= 10.0;
270 m_logicalScaleX
= (float)(twips2mm
* mm2pixelsX
);
271 m_logicalScaleY
= (float)(twips2mm
* mm2pixelsY
);
276 m_logicalScaleX
= (float)(pt2mm
* mm2pixelsX
);
277 m_logicalScaleY
= (float)(pt2mm
* mm2pixelsY
);
282 m_logicalScaleX
= mm2pixelsX
;
283 m_logicalScaleY
= mm2pixelsY
;
288 m_logicalScaleX
= (float)(mm2pixelsX
/10.0);
289 m_logicalScaleY
= (float)(mm2pixelsY
/10.0);
295 m_logicalScaleX
= 1.0;
296 m_logicalScaleY
= 1.0;
304 // ----------------------------------------------------------------------------
305 // wxMakeMetafilePlaceable
306 // ----------------------------------------------------------------------------
317 struct mfPLACEABLEHEADER
{
326 struct mfPLACEABLEHEADER
{
337 * Pass filename of existing non-placeable metafile, and bounding box.
338 * Adds a placeable metafile header, sets the mapping mode to anisotropic,
339 * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode.
343 bool wxMakeMetafilePlaceable(const wxString
& filename
, float scale
)
345 return wxMakeMetafilePlaceable(filename
, 0, 0, 0, 0, scale
, FALSE
);
348 bool wxMakeMetafilePlaceable(const wxString
& filename
, int x1
, int y1
, int x2
, int y2
, float scale
, bool useOriginAndExtent
)
350 // I'm not sure if this is the correct way of suggesting a scale
351 // to the client application, but it's the only way I can find.
352 int unitsPerInch
= (int)(576/scale
);
354 mfPLACEABLEHEADER header
;
355 header
.key
= 0x9AC6CDD7L
;
357 header
.bbox
.left
= (int)(x1
);
358 header
.bbox
.top
= (int)(y1
);
359 header
.bbox
.right
= (int)(x2
);
360 header
.bbox
.bottom
= (int)(y2
);
361 header
.inch
= unitsPerInch
;
364 // Calculate checksum
366 mfPLACEABLEHEADER
*pMFHead
= &header
;
367 for (p
=(WORD
*)pMFHead
,pMFHead
-> checksum
= 0;
368 p
< (WORD
*)&pMFHead
->checksum
; ++p
)
369 pMFHead
->checksum
^= *p
;
371 FILE *fd
= fopen(filename
.fn_str(), "rb");
372 if (!fd
) return FALSE
;
374 wxChar tempFileBuf
[256];
375 wxGetTempFileName(wxT("mf"), tempFileBuf
);
376 FILE *fHandle
= fopen(wxConvFile
.cWX2MB(tempFileBuf
), "wb");
379 fwrite((void *)&header
, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER
), fHandle
);
381 // Calculate origin and extent
384 int extentX
= x2
- x1
;
385 int extentY
= (y2
- y1
);
387 // Read metafile header and write
388 METAHEADER metaHeader
;
389 fread((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fd
);
391 if (useOriginAndExtent
)
392 metaHeader
.mtSize
+= 15;
394 metaHeader
.mtSize
+= 5;
396 fwrite((void *)&metaHeader
, sizeof(unsigned char), sizeof(metaHeader
), fHandle
);
398 // Write SetMapMode, SetWindowOrigin and SetWindowExt records
400 char originBuffer
[10];
401 char extentBuffer
[10];
402 METARECORD
*modeRecord
= (METARECORD
*)&modeBuffer
;
404 METARECORD
*originRecord
= (METARECORD
*)&originBuffer
;
405 METARECORD
*extentRecord
= (METARECORD
*)&extentBuffer
;
407 modeRecord
->rdSize
= 4;
408 modeRecord
->rdFunction
= META_SETMAPMODE
;
409 modeRecord
->rdParm
[0] = MM_ANISOTROPIC
;
411 originRecord
->rdSize
= 5;
412 originRecord
->rdFunction
= META_SETWINDOWORG
;
413 originRecord
->rdParm
[0] = originY
;
414 originRecord
->rdParm
[1] = originX
;
416 extentRecord
->rdSize
= 5;
417 extentRecord
->rdFunction
= META_SETWINDOWEXT
;
418 extentRecord
->rdParm
[0] = extentY
;
419 extentRecord
->rdParm
[1] = extentX
;
421 fwrite((void *)modeBuffer
, sizeof(char), 8, fHandle
);
423 if (useOriginAndExtent
)
425 fwrite((void *)originBuffer
, sizeof(char), 10, fHandle
);
426 fwrite((void *)extentBuffer
, sizeof(char), 10, fHandle
);
440 wxRemoveFile(filename
);
441 wxCopyFile(tempFileBuf
, filename
);
442 wxRemoveFile(tempFileBuf
);
447 #if wxUSE_DRAG_AND_DROP
449 // ----------------------------------------------------------------------------
450 // wxMetafileDataObject
451 // ----------------------------------------------------------------------------
453 size_t wxMetafileDataObject::GetDataSize() const
455 return sizeof(METAFILEPICT
);
458 bool wxMetafileDataObject::GetDataHere(void *buf
) const
460 METAFILEPICT
*mfpict
= (METAFILEPICT
*)buf
;
461 const wxMetafile mf
= GetMetafile();
462 mfpict
->mm
= mf
.GetWindowsMappingMode();
463 mfpict
->xExt
= mf
.GetWidth();
464 mfpict
->yExt
= mf
.GetHeight();
465 mfpict
->hMF
= (HMETAFILE
)mf
.GetHMETAFILE();
467 wxCHECK_MSG( mfpict
->hMF
, FALSE
, _T("copying invalid metafile") );
472 bool wxMetafileDataObject::SetData(size_t WXUNUSED(len
), const void *buf
)
474 const METAFILEPICT
*mfpict
= (const METAFILEPICT
*)buf
;
477 mf
.SetWindowsMappingMode(mfpict
->mm
);
478 mf
.SetWidth(mfpict
->xExt
);
479 mf
.SetHeight(mfpict
->yExt
);
480 mf
.SetHMETAFILE((WXHANDLE
)mfpict
->hMF
);
482 wxCHECK_MSG( mfpict
->hMF
, FALSE
, _T("pasting invalid metafile") );
489 #endif // wxUSE_DRAG_AND_DROP
491 #endif // wxUSE_METAFILE