330 lines
9.9 KiB
C++
330 lines
9.9 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXMetaFile
|
|
// ==========================================================================
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "OXMetaFile.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
COXMetaFile::COXMetaFile()
|
|
{
|
|
m_hDCMeta = NULL;
|
|
m_hEMF = NULL;
|
|
m_lpEnhMetaProc = NULL;
|
|
m_rectBounds.SetRectEmpty();
|
|
m_rectNormalized.SetRectEmpty();
|
|
m_metafileType=OXMETAFILE_NOTDEFINED;
|
|
}
|
|
|
|
COXMetaFile::~COXMetaFile()
|
|
{
|
|
if(m_hEMF)
|
|
DeleteEnhMetaFile(m_hEMF);
|
|
}
|
|
/////////////////////////////////////////
|
|
// fileaccess
|
|
/////////////////////////////////////////
|
|
|
|
// ================== Load File ==================================
|
|
HENHMETAFILE COXMetaFile::LoadFile(int nID, CString strResType)
|
|
{
|
|
LPVOID lpvData;
|
|
HANDLE hResource;
|
|
HRSRC hRsrc = FindResource(AfxGetApp()->m_hInstance,
|
|
MAKEINTRESOURCE(nID), strResType);
|
|
|
|
// Load MetaFile metafile from resource
|
|
hResource = LoadResource(AfxGetApp()->m_hInstance, hRsrc);
|
|
if(!hResource)
|
|
{
|
|
TRACE(_T("MetaFile %d not found in resource\n"), nID);
|
|
return NULL;
|
|
}
|
|
lpvData = LockResource(hResource) ;
|
|
LoadFile(lpvData);
|
|
UnlockResource(hResource) ;
|
|
return m_hEMF;
|
|
}
|
|
|
|
HENHMETAFILE COXMetaFile::LoadFile(CString strFileName)
|
|
{
|
|
HANDLE hFile, hMapFile;
|
|
LPVOID pMapFile;
|
|
BOOL bSuccess = TRUE;
|
|
|
|
// ask for filename, if not given as parameter
|
|
if(! strFileName.GetLength())
|
|
{
|
|
static TCHAR BASED_CODE szFilter[] =
|
|
_T("Windows MetaFile(*.wmf)|*.wmf|Enhanced MetaFile(*.emf)|*.emf||");
|
|
CFileDialog LoadMetaFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);
|
|
if(LoadMetaFile.DoModal() != IDOK)
|
|
return 0L;
|
|
m_strFileName = LoadMetaFile.GetPathName();
|
|
}
|
|
else
|
|
m_strFileName = strFileName;
|
|
|
|
// open file
|
|
if((hFile = ::CreateFile((LPCTSTR) m_strFileName, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL)) ==(HANDLE)-1)
|
|
{
|
|
TRACE(_T("Fileopen Error\n"));
|
|
return 0L;
|
|
}
|
|
// Create a map file of the opened file
|
|
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, _T("MapF"));
|
|
if(hMapFile == NULL)
|
|
{
|
|
TRACE(_T("Error in CreateFileMapping\n"));
|
|
CloseHandle(hFile);
|
|
return 0L;
|
|
}
|
|
// Map a view of the whole file
|
|
pMapFile = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
|
|
if(pMapFile == NULL)
|
|
{
|
|
TRACE(_T("Error in MapViewOfFile\n"));
|
|
bSuccess = FALSE;
|
|
CloseHandle(hMapFile);
|
|
CloseHandle(hFile);
|
|
return 0L;
|
|
}
|
|
// LoadFile does the hard work
|
|
m_hEMF = LoadFile(pMapFile);
|
|
UnmapViewOfFile(pMapFile);
|
|
CloseHandle(hMapFile);
|
|
CloseHandle(hFile);
|
|
return m_hEMF;
|
|
}
|
|
|
|
|
|
// =============== CreateFile & CloseFile
|
|
// ----------------------------------------------
|
|
HDC COXMetaFile::CreateFile(CString strFileName, CString strDescript,
|
|
CString sDefExt/* = _T("emf")*/,
|
|
int nIDFilter/*"EMF Files(*.emf)|*.emf|All Files(*.*)|*.*|"*/)
|
|
{
|
|
m_hDCMeta = NULL;
|
|
CString sFilter;
|
|
VERIFY(sFilter.LoadString(nIDFilter));
|
|
// Dlg
|
|
if(! strFileName.GetLength())
|
|
{
|
|
CString sFileName=_T("*.");
|
|
sFileName+=sDefExt;
|
|
CFileDialog NewMetaFile(FALSE, sDefExt, sFileName,
|
|
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, sFilter);
|
|
if(NewMetaFile.DoModal() != IDOK)
|
|
return NULL;
|
|
|
|
m_strFileName = NewMetaFile.GetPathName();
|
|
}
|
|
else
|
|
m_strFileName = strFileName;
|
|
m_hDCMeta = CreateEnhMetaFile(NULL, m_strFileName, NULL, strDescript) ;
|
|
#ifdef _DEBUG
|
|
if(!m_hDCMeta)
|
|
AfxMessageBox(_T("Error in CreateEnhMetaFile\n")+strDescript);
|
|
#endif
|
|
return m_hDCMeta;
|
|
}
|
|
|
|
void COXMetaFile::CloseFile()
|
|
{
|
|
if(m_hDCMeta)
|
|
m_hEMF=CloseEnhMetaFile(m_hDCMeta);
|
|
if(m_hEMF)
|
|
DeleteEnhMetaFile(m_hEMF);
|
|
m_hDCMeta = NULL;
|
|
m_hEMF = NULL;
|
|
m_rectBounds.SetRectEmpty();
|
|
m_rectNormalized.SetRectEmpty();
|
|
m_metafileType=OXMETAFILE_NOTDEFINED;
|
|
}
|
|
|
|
// ================ PlayFile - PlayRecords =======================
|
|
//
|
|
BOOL COXMetaFile::PlayFile(CDC* pDC)
|
|
{
|
|
CRect cRect(0,0,m_rectBounds.right-m_rectBounds.left,
|
|
m_rectBounds.bottom-m_rectBounds.top);
|
|
return PlayEnhMetaFile(pDC->m_hDC,m_hEMF,&cRect);
|
|
}
|
|
|
|
BOOL COXMetaFile::PlayFile(CDC* pDC, CRect* pClientRect)
|
|
{
|
|
BOOL bReturn;
|
|
CRect rectBounds;
|
|
int nOldMapMode = pDC->GetMapMode();
|
|
CSize OldWndExt, OldViewExt;
|
|
|
|
rectBounds.SetRectEmpty();
|
|
if(pDC->IsPrinting())
|
|
{
|
|
rectBounds.right = pDC->GetDeviceCaps(HORZRES);
|
|
rectBounds.bottom= pDC->GetDeviceCaps(VERTRES);
|
|
}
|
|
else
|
|
rectBounds = * pClientRect;
|
|
ASSERT(rectBounds!=(0,0,0,0));
|
|
if(!m_hEMF)
|
|
return FALSE;
|
|
pDC->SetMapMode(MM_ISOTROPIC);
|
|
// draw the MetaFile
|
|
// Ajust size of Window to MetaFile
|
|
OldWndExt = pDC->SetWindowExt(GetSize());
|
|
OldViewExt = pDC->SetViewportExt(rectBounds.right, rectBounds.bottom);
|
|
bReturn = PlayFile(pDC);
|
|
pDC->SetWindowExt(OldWndExt);
|
|
pDC->SetViewportExt(OldViewExt);
|
|
pDC->SetMapMode(nOldMapMode);
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
BOOL COXMetaFile::PlayRecords(CDC* pDC, CRect crect,
|
|
ENHMFENUMPROC lpEnhMetaProc, LPVOID plData)
|
|
{
|
|
if((!m_lpEnhMetaProc) &&(lpEnhMetaProc))
|
|
m_lpEnhMetaProc = lpEnhMetaProc;
|
|
ASSERT(m_lpEnhMetaProc);
|
|
return EnumEnhMetaFile(pDC->m_hDC, m_hEMF, m_lpEnhMetaProc, plData, crect);
|
|
}
|
|
|
|
|
|
// ========= private helper functions
|
|
// ------------------------------------------
|
|
HENHMETAFILE COXMetaFile::LoadFile(LPVOID lpvData)
|
|
{
|
|
unsigned long lSize;
|
|
ALDUSHEADER* pAldusMF;
|
|
LPENHMETAHEADER pemh =(LPENHMETAHEADER) lpvData;
|
|
ENHMETAHEADER EnhMetaHeader;
|
|
|
|
if(m_hEMF)
|
|
{
|
|
DeleteEnhMetaFile(m_hEMF);
|
|
m_hEMF=NULL;
|
|
}
|
|
|
|
// get size, if it makes sense
|
|
// Obtain a handle to a reference device context
|
|
HDC hdcRef=::GetDC(NULL);
|
|
// Determine the picture frame dimensions.
|
|
// iWidthMM is the display width in millimeters.
|
|
// iHeightMM is the display height in millimeters.
|
|
// iWidthPels is the display width in pixels.
|
|
// iHeightPels is the display height in pixels
|
|
int iWidthMM=GetDeviceCaps(hdcRef,HORZSIZE);
|
|
int iHeightMM=GetDeviceCaps(hdcRef,VERTSIZE);
|
|
int iWidthPels=GetDeviceCaps(hdcRef,HORZRES);
|
|
int iHeightPels=GetDeviceCaps(hdcRef,VERTRES);
|
|
::ReleaseDC(NULL,hdcRef);
|
|
|
|
|
|
// ============== 1) is it an enhanced MetaFile ==================================
|
|
if(pemh->dSignature == META32_SIGNATURE)
|
|
{
|
|
TRACE(_T("it's an Enhanced MetaFile\n"));
|
|
lSize = pemh->nBytes;
|
|
m_hEMF = SetEnhMetaFileBits(lSize,(CONST BYTE*) lpvData) ;
|
|
m_strDescription.Empty();
|
|
// MetaFileHeader lesen
|
|
if(m_hEMF)
|
|
{
|
|
GetEnhMetaFileHeader(m_hEMF,sizeof(EnhMetaHeader),&EnhMetaHeader);
|
|
m_rectNormalized.SetRect(EnhMetaHeader.rclFrame.left,
|
|
EnhMetaHeader.rclFrame.top,EnhMetaHeader.rclFrame.right,
|
|
EnhMetaHeader.rclFrame.bottom);
|
|
m_rectBounds.SetRect((m_rectNormalized.left*iWidthPels)/(iWidthMM*100),
|
|
(m_rectNormalized.top*iHeightPels)/(iHeightMM*100),
|
|
(m_rectNormalized.right*iWidthPels)/(iWidthMM*100),
|
|
(m_rectNormalized.bottom*iHeightPels)/(iHeightMM*100));
|
|
if(EnhMetaHeader.nDescription>0)
|
|
{
|
|
GetEnhMetaFileDescription(m_hEMF, EnhMetaHeader.nDescription,
|
|
m_strDescription.GetBufferSetLength(EnhMetaHeader.nDescription));
|
|
m_strDescription.ReleaseBuffer();
|
|
}
|
|
else
|
|
m_strDescription.Empty();
|
|
|
|
}
|
|
m_metafileType=OXMETAFILE_ENHANCED;
|
|
return m_hEMF;
|
|
}
|
|
|
|
// ===============2) is is an Aldus MetaFile ==================================
|
|
// If it has an ALDUS header skip it
|
|
// Notice: APMSIZE is used instead of sizeof(ALDUSHEAD) because the
|
|
// HANDLE and RECT of the structure
|
|
// depends on the environment and the align value
|
|
if(*((LPDWORD)lpvData) == ALDUS_ID)
|
|
{
|
|
TRACE(_T("It's an Aldus MetaFile\n"));
|
|
pAldusMF =(ALDUSHEADER*) lpvData;
|
|
lSize = *((LPDWORD)((PBYTE)lpvData + APMSIZE + 6));
|
|
// Notice: mtSize is size of the file in word.
|
|
// if LPMETAFILEPICT is NULL
|
|
// MM_ANISOTROPIC mode and default device size will be used.
|
|
m_hEMF=::SetWinMetaFileBits(lSize*2L,(PBYTE)lpvData+APMSIZE,NULL,NULL);
|
|
VERIFY(m_strDescription.LoadString(IDS_OX_METAFILEALDUS)); //"WMF - Aldus Format"
|
|
if(!m_hEMF)
|
|
{
|
|
TRACE(_T("Error in SetWinMetaFileBits in Aldus MetaFile\n"));
|
|
return 0L;
|
|
}
|
|
m_rectNormalized.SetRect(0,0,
|
|
((pAldusMF->right-pAldusMF->left)*2540)/((int)pAldusMF->inch),
|
|
((pAldusMF->bottom-pAldusMF->top)*2540)/((int)pAldusMF->inch));
|
|
m_rectBounds.SetRect((m_rectNormalized.left*iWidthPels)/(iWidthMM*100),
|
|
(m_rectNormalized.top*iHeightPels)/(iHeightMM*100),
|
|
(m_rectNormalized.right*iWidthPels)/(iWidthMM*100),
|
|
(m_rectNormalized.bottom*iHeightPels)/(iHeightMM*100));
|
|
|
|
m_metafileType=OXMETAFILE_ALDUS;
|
|
return m_hEMF;
|
|
}
|
|
// ================== 3) old Windows MetaFile ========================
|
|
TRACE(_T("I try old Windows 3x MetaFile\n"));
|
|
lSize = *((LPDWORD)((PBYTE)lpvData + 6));
|
|
m_hEMF=::SetWinMetaFileBits(lSize*2L,(PBYTE)lpvData , NULL, NULL);
|
|
VERIFY(m_strDescription.LoadString(IDS_OX_METAFILEWINDOWS)) ; //"Windows 3.x MetaFile"
|
|
m_rectBounds.SetRect(0,0,::GetSystemMetrics(SM_CXSCREEN),
|
|
::GetSystemMetrics(SM_CYSCREEN));
|
|
m_rectNormalized.SetRect(0,0,
|
|
(m_rectBounds.Width()*iWidthMM*100)/iWidthPels,
|
|
(m_rectBounds.Height()*iHeightMM*100)/iHeightPels);
|
|
if(!m_hEMF)
|
|
{
|
|
TRACE(_T("Error on SetWinMetaFileBits in old windows MetaFile\n"));
|
|
}
|
|
else
|
|
m_metafileType=OXMETAFILE_WIN16;
|
|
return m_hEMF;
|
|
}
|
|
|
|
|