// CntrItem.cpp : implementation of the CItem class
//
#include "stdafx.h"
#include "MROT.h"
#include "MROTDoc.h"
#include "MROTView.h"
#include "CntrItem.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// static member definition...
EnumProperty CItem::enumProp;
CItem* CItem::stWrap;
BOOL CItem::Rotate;
double CItem::r;
ENHMETAHEADER CItem::Hdr;
POINT CItem::worg;
SIZE CItem::wext;
POINT CItem::vorg;
SIZE CItem::vext;
IMPLEMENT_SERIAL(CItem, COleClientItem, 0)
CItem::CItem(CMROTDoc* pContainer)
: COleClientItem(pContainer)
{
R = 0;
x = 100;
y = 100;
cx = 0;
cy = 0;
}
CItem::~CItem()
{
}
void CItem::OnChange(OLE_NOTIFICATION nCode, DWORD dwParam)
{
ASSERT_VALID(this);
COleClientItem::OnChange(nCode, dwParam);
GetDocument()->UpdateAllViews(NULL);
}
BOOL CItem::OnChangeItemPosition(const CRect& rectPos)
{
ASSERT_VALID(this);
if (!COleClientItem::OnChangeItemPosition(rectPos))
return FALSE;
return TRUE;
}
void CItem::OnGetItemPosition(CRect& rPosition)
{
ASSERT_VALID(this);
rPosition.SetRect(10, 10, 210, 210);
}
void CItem::OnActivate()
{
CMROTView* pView = GetActiveView();
ASSERT_VALID(pView);
COleClientItem* pItem = GetDocument()->GetInPlaceActiveItem(pView);
if (pItem != NULL && pItem != this)
pItem->Close();
COleClientItem::OnActivate();
}
void CItem::OnDeactivateUI(BOOL bUndoable)
{
COleClientItem::OnDeactivateUI(bUndoable);
DWORD dwMisc = 0;
m_lpObject->GetMiscStatus(GetDrawAspect(), &dwMisc);
if (dwMisc & OLEMISC_INSIDEOUT)
DoVerb(OLEIVERB_HIDE, NULL);
}
void CItem::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
COleClientItem::Serialize(ar);
if (ar.IsStoring())
{
}
else
{
}
}
#ifdef _DEBUG
void CItem::AssertValid() const
{
COleClientItem::AssertValid();
}
void CItem::Dump(CDumpContext& dc) const
{
COleClientItem::Dump(dc);
}
#endif
COleDataObject* CItem::CustomizeItem(CDC *pRefDC, CItem *cthis, LPSIZE size)
{
SIZE ext;
cthis->GetExtent(&ext);
if(ext.cx <= ext.cy) {
ext.cx = ext.cx * 300 / ext.cy;
ext.cy = 300;
} else {
ext.cy = ext.cy * 300 / ext.cx;
ext.cx = 300;
}
int cx = ext.cx;
int cy = ext.cy;
cthis->cx = cx;
cthis->cy = cy;
size->cx = cx;
size->cy = cy;
UINT szEMF;
COleDataObject* dataObject = NULL;
CMetaFileDC* metaDC = new CMetaFileDC();
metaDC->CreateEnhanced(pRefDC, NULL, NULL, "BEFORE");
metaDC->SetAttribDC(pRefDC->m_hAttribDC);
cthis->Draw(metaDC, CRect(cthis->x, cthis->y, cthis->x+cx, cthis->y+cy));
HENHMETAFILE hMF = metaDC->CloseEnhanced();
GetEnhMetaFileHeader(hMF, sizeof(CItem::Hdr), &CItem::Hdr);
vorg.x = 0;
vorg.y = 0;
worg.x = 0;
worg.y = 0;
vext.cx = 0;
vext.cy = 0;
wext.cx = 0;
wext.cy = 0;
CMetaFileDC* aDC = new CMetaFileDC();
aDC->CreateEnhanced(pRefDC, NULL, NULL, "AFTER");
aDC->SetAttribDC(pRefDC->m_hAttribDC);
BOOL ret = EnumEnhMetaFile(aDC->GetSafeHdc() , hMF, (ENHMFENUMPROC)CItem::ConvertEMF, NULL, CRect(0, 0, cx, cy));
if(ret == TRUE) {
HENHMETAFILE aMF = aDC->CloseEnhanced();
szEMF = GetEnhMetaFileBits(aMF, 0, NULL);
HANDLE bcache = GlobalAlloc(GHND, szEMF);
LPBYTE cache = (LPBYTE)GlobalLock(bcache);
GetEnhMetaFileBits(aMF, szEMF, cache);
CSharedFile globFile;
CArchive ar(&globFile, CArchive::store);
ar.Write(cache, szEMF);
ar.Close();
HGLOBAL hData = globFile.Detach();
COleDataSource *pOleDataSource = new COleDataSource;
pOleDataSource->FlushClipboard();
tagSTGMEDIUM * data = new tagSTGMEDIUM;
data->tymed = TYMED_ENHMF;
data->hEnhMetaFile = aMF;
pOleDataSource->CacheData(CF_ENHMETAFILE, data);
pOleDataSource->SetClipboard();
dataObject = new COleDataObject();
dataObject->AttachClipboard();
delete data;
} else AfxMessageBox("Error");
delete aDC;
delete metaDC;
return dataObject;
}
int CALLBACK CItem::ConvertEMF(HDC hDC, LPHANDLETABLE lpHTable, LPENHMETARECORD lpEMFR, int nObj, LPARAM lpData) {
UINT width = Hdr.rclBounds.right - Hdr.rclBounds.left;
UINT height = Hdr.rclBounds.bottom - Hdr.rclBounds.top;
POINT cnt;
cnt.x = width/2;
cnt.y = height/2;
if(lpEMFR->iType == EMR_POLYGON16 || lpEMFR->iType == EMR_POLYLINE16) {
HANDLE hMem = GlobalAlloc(GHND, lpEMFR->nSize);
PEMRPOLYGON16 eG = (PEMRPOLYGON16)GlobalLock(hMem);
memcpy(eG, lpEMFR, lpEMFR->nSize);
int xmin = 999999;
int xmax = -999999;
int ymin = 999999;
int ymax = -999999;
for( int i = 0 ; i < (int)eG->cpts ; i++) {
POINT t1;
t1.x = eG->apts[i].x; t1.y = eG->apts[i].y;
if(wext.cx < 0) t1.x = worg.x + worg.x - t1.x;
if(wext.cy < 0) t1.y = worg.y + worg.y - t1.y;
eG->apts[i].x = (short)t1.x; eG->apts[i].y = (short)t1.y;
if(eG->apts[i].x < xmin) xmin = eG->apts[i].x;
if(eG->apts[i].x > xmax) xmax = eG->apts[i].x;
if(eG->apts[i].y < ymin) ymin = eG->apts[i].y;
if(eG->apts[i].y < ymax) ymax = eG->apts[i].y;
}
eG->rclBounds.left = xmin;
eG->rclBounds.top = ymin;
eG->rclBounds.right = xmax;
eG->rclBounds.bottom = ymax;
PlayEnhMetaFileRecord(hDC, lpHTable, (PENHMETARECORD)eG, nObj);
GlobalUnlock(hMem);
GlobalFree(hMem);
} else {
switch(lpEMFR->iType) {
case EMR_SETVIEWPORTEXTEX:
case EMR_SETWINDOWEXTEX:
{
PEMRSETVIEWPORTEXTEX eG;
HANDLE hMem = GlobalAlloc(GHND, lpEMFR->nSize);
eG = (PEMRSETVIEWPORTEXTEX)GlobalLock(hMem);
memcpy(eG, lpEMFR, lpEMFR->nSize);
if(lpEMFR->iType == EMR_SETVIEWPORTEXTEX) {
vext.cx = eG->szlExtent.cx;
vext.cy = eG->szlExtent.cy;
} else {
wext.cx = eG->szlExtent.cx;
wext.cy = eG->szlExtent.cy;
if(eG->szlExtent.cx < 0) eG->szlExtent.cx *= -1;
if(eG->szlExtent.cy < 0) eG->szlExtent.cy *= -1;
}
PlayEnhMetaFileRecord(hDC, lpHTable, (PENHMETARECORD)eG, nObj);
GlobalUnlock(hMem);
GlobalFree(hMem);
}
break;
case EMR_SETVIEWPORTORGEX:
case EMR_SETWINDOWORGEX:
{
PEMRSETVIEWPORTORGEX eG;
HANDLE hMem = GlobalAlloc(GHND, lpEMFR->nSize);
eG = (PEMRSETVIEWPORTORGEX)GlobalLock(hMem);
memcpy(eG, lpEMFR, lpEMFR->nSize);
if(lpEMFR->iType == EMR_SETVIEWPORTORGEX) {
vorg.x = eG->ptlOrigin.x;
vorg.y = eG->ptlOrigin.y;
} else {
worg.x = eG->ptlOrigin.x;
worg.y = eG->ptlOrigin.y;
}
PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, nObj);
GlobalUnlock(hMem);
GlobalFree(hMem);
}
break;
default:
PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, nObj);
break;
}
}
return 1;
}
int CALLBACK CItem::EnhMetaFileProc(HDC hDC, HANDLETABLE FAR *lpHTable, ENHMETARECORD* lpEMFR, int nObj, LPARAM lpData) {
if(lpEMFR->iType == EMR_POLYGON16 || lpEMFR->iType == EMR_POLYLINE16) {
PEMRPOLYGON16 eG;
HANDLE hMem = GlobalAlloc(GHND, lpEMFR->nSize);
eG = (PEMRPOLYGON16)GlobalLock(hMem);
memcpy(eG, lpEMFR, lpEMFR->nSize);
POINT * polygon = (POINT *)malloc(eG->cpts * sizeof(POINT));
POINT rgn;
rgn.x = (Hdr.rclBounds.right-Hdr.rclBounds.left) / 2 + CItem::stWrap->x;
rgn.y = (Hdr.rclBounds.bottom-Hdr.rclBounds.top) / 2 + CItem::stWrap->y;
DPtoLP(hDC, &rgn, 1);
for( int i = 0 ; i < (int)eG->cpts ; i++) {
POINT t1;
t1.x = eG->apts[i].x;
if(CItem::enumProp.winOrg.negX) t1.x = t1.x * -1;
t1.x -= rgn.x;
t1.y = eG->apts[i].y;
if(CItem::enumProp.winOrg.negY) t1.y = t1.y * -1;
t1.y -= rgn.y;
if(CItem::Rotate == TRUE) {
double pi = 3.1415926535;
double r = pi / 180 * CItem::enumProp.R;
polygon[i].x = (long)((t1.x * cos(r) - t1.y * sin(r)) * CItem::r + rgn.x);
polygon[i].y = (long)((t1.x * sin(r) + t1.y * cos(r)) * CItem::r + rgn.y);
} else {
polygon[i].x = t1.x + rgn.x;
polygon[i].y = t1.y + rgn.y;
}
}
if(lpEMFR->iType == EMR_POLYGON16) Polygon(hDC, polygon, eG->cpts);
else Polyline(hDC, polygon, eG->cpts);
free(polygon);
GlobalUnlock(hMem);
GlobalFree(hMem);
} else {
PlayEnhMetaFileRecord(hDC, lpHTable, lpEMFR, nObj);
}
return 1;
}
void CItem::DrawObject(CDC *pRefDC, CDC *pOutputDC)
{
CItem::stWrap = this;
CMetaFileDC * metaDC = new CMetaFileDC();
RECT bounds = {0, 0, cx, cy};
metaDC->CreateEnhanced(pRefDC, NULL, NULL, "temp");
metaDC->SetAttribDC(pRefDC->m_hAttribDC);
Draw(metaDC, &bounds);
HENHMETAFILE hMF = metaDC->CloseEnhanced();
GetEnhMetaFileHeader(hMF, sizeof(CItem::Hdr), &CItem::Hdr);
bounds.left = x;
bounds.top = y;
bounds.right = x+cx;
bounds.bottom = y+cy;
CMetaFileDC * rDC = new CMetaFileDC();
rDC->CreateEnhanced(pRefDC, NULL, NULL, "ROTATE");
rDC->SetAttribDC(pRefDC->m_hAttribDC);
CItem::r = 0.5;
CItem::Rotate = TRUE;
CItem::enumProp.R = R;
EnumEnhMetaFile(
rDC->GetSafeHdc(),
hMF,
(ENHMFENUMPROC)CItem::EnhMetaFileProc,
NULL,
&bounds
);
HENHMETAFILE rMF = rDC->CloseEnhanced();
POINT center;
center.x = (bounds.left + bounds.right) / 2;
center.y = (bounds.top + bounds.bottom) / 2;
UINT szEMFH = GetEnhMetaFileHeader(rMF, 0, NULL);
LPBYTE header = (LPBYTE)malloc(sizeof(BYTE) * szEMFH);
GetEnhMetaFileHeader(rMF, szEMFH, (LPENHMETAHEADER)header);
LPENHMETAHEADER phead = (LPENHMETAHEADER)header;
bounds.left = phead->rclBounds.left;
bounds.right = phead->rclBounds.right;
bounds.top = phead->rclBounds.top;
bounds.bottom = phead->rclBounds.bottom;
CItem::ExpandDoubleRect(&bounds, center);
CItem::r = 1;
CItem::Rotate = FALSE;
EnumEnhMetaFile(
pOutputDC->GetSafeHdc(),
rMF,
(ENHMFENUMPROC)CItem::EnhMetaFileProc,
NULL,
&bounds
);
::DeleteEnhMetaFile(hMF);
::DeleteEnhMetaFile(rMF);
free(header);
delete metaDC;
delete rDC;
}
void CItem::ExpandDoubleRect(LPRECT rect, POINT ct)
{
rect->left = (rect->left - ct.x) * 2 + ct.x;
rect->right = (rect->right - ct.x) * 2 + ct.x;
rect->top = (rect->top - ct.y) * 2 + ct.y;
rect->bottom = (rect->bottom - ct.y) * 2 + ct.y;
}