Click here to Skip to main content
15,886,085 members
Articles / Desktop Programming / MFC

EMF Record Rotation for EMR_POLYGON16

Rate me:
Please Sign up or sign in to vote.
2.71/5 (4 votes)
17 Nov 20022 min read 63.4K   1.9K   19  
EMF record rotation for EMR_POLYGON16
// 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;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
Web Developer
Korea (Republic of) Korea (Republic of)
Lazy Programmer since 1998.

Comments and Discussions