|
|
/****************************** Module Header ******************************\
* Module Name:EMF.C (Extensible Compound Documents - EnhancedMetafile) * * PURPOSE:Handles all API routines for the metafile sub-dll of the ole dll. * * Created: 1990 * * Copyright (c) 1990, 1991 Microsoft Corporation * * History: * cloned mf.c and banged into form curts March 92 * * Comments: * fun, fun, until hockl takes the enhanced metafile api away * \***************************************************************************/
#include <windows.h>
#include "dll.h"
#include "pict.h"
#define RECORD_COUNT 16
OLEOBJECTVTBL vtblEMF = {
ErrQueryProtocol, // check whether the speced protocol is supported
EmfRelease, // Release
ErrShow, // show
ErrPlay, // play
EmfGetData, // Get the object data
ErrSetData, // Set the object data
ErrSetTargetDevice, //
ErrSetBounds, // set viewport bounds
EmfEnumFormat, // enumerate supported formats
ErrSetColorScheme, //
EmfRelease, // delete
ErrSetHostNames, //
EmfSaveToStream, // write to file
EmfClone, // clone object
ErrCopyFromLink, // Create embedded from Lnk
EmfEqual, // compares the given objects for data equality
EmfCopy, // copy to clip
EmfDraw, // draw the object
ErrActivate, // open
ErrExecute, // excute
ErrClose, // stop
ErrUpdate, // Update
ErrReconnect, // Reconnect
ErrObjectConvert, // convert object to specified type
ErrGetUpdateOptions, // update options
ErrSetUpdateOptions, // update options
ObjRename, // Change Object name
ObjQueryName, // Get current object name
ObjQueryType, // Object type
EmfQueryBounds, // QueryBounds
ObjQuerySize, // Find the size of the object
ErrQueryOpen, // Query open
ErrQueryOutOfDate, // query whether object is current
ErrQueryRelease, // release related stuff
ErrQueryRelease, ErrQueryReleaseMethod,
ErrRequestData, // requestdata
ErrObjectLong, // objectLong
EmfChangeData // change data of the existing object
};
OLESTATUS FARINTERNAL EmfRelease (LPOLEOBJECT lpoleobj) { LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj; HOBJECT hobj;
if (lpobj->hemf) { DeleteEnhMetaFile ((HENHMETAFILE)lpobj->hemf); lpobj->hemf = NULL; }
if (lpobj->head.lhclientdoc) DocDeleteObject ((LPOLEOBJECT)lpobj);
if (hobj = lpobj->head.hobj) { lpobj->head.hobj = NULL; GlobalUnlock (hobj); GlobalFree (hobj); }
return OLE_OK; }
OLESTATUS FARINTERNAL SaveEmfAsMfToStream ( LPOLEOBJECT lpoleobj, LPOLESTREAM lpstream ){ DWORD dwFileVer = (DWORD)MAKELONG(wReleaseVer,OS_WIN32); LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj; OLESTATUS retval = OLE_ERROR_MEMORY; HDC hdc = NULL ; LPBYTE lpBytes = NULL ; HANDLE hBytes = NULL ; WIN16METAFILEPICT w16mfp; UINT lSizeBytes;
w16mfp.mm = MM_ANISOTROPIC; w16mfp.xExt = (short)lpobj->head.cx;
if ((short)lpobj->head.cy <0 ) { w16mfp.yExt = -(short)lpobj->head.cy; } else { w16mfp.yExt = (short)lpobj->head.cy; }
if (PutBytes (lpstream, (LPSTR) &dwFileVer, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutStrWithLen(lpstream, (LPSTR)"METAFILEPICT")) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG))) return OLE_ERROR_STREAM;
hdc = GetDC(NULL); if (!(lSizeBytes = GetWinMetaFileBits((HENHMETAFILE)lpobj->hemf, 0, NULL, MM_ANISOTROPIC, hdc)) ) { if (hdc) ReleaseDC(NULL, hdc); return OLE_ERROR_METAFILE; }
if (!(hBytes = GlobalAlloc(GHND, lSizeBytes)) ) goto error;
if (!(lpBytes = (LPBYTE)GlobalLock(hBytes)) ) goto error;
if (GetWinMetaFileBits((HENHMETAFILE)lpobj->hemf, lSizeBytes, lpBytes, MM_ANISOTROPIC, hdc) != lSizeBytes) { retval = OLE_ERROR_METAFILE; goto error; }
lSizeBytes += sizeof(WIN16METAFILEPICT);
if (PutBytes (lpstream, (LPSTR) &lSizeBytes, sizeof(UINT))) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR)&w16mfp, sizeof(WIN16METAFILEPICT))) goto error;
if (!PutBytes (lpstream, (LPSTR)lpBytes, lSizeBytes - sizeof(WIN16METAFILEPICT))) retval = OLE_OK;
error: if (lpBytes) GlobalUnlock(hBytes); if (hBytes) GlobalFree(hBytes);
if (hdc) ReleaseDC(NULL, hdc);
return retval;
}
OLESTATUS FARINTERNAL EmfSaveToStream ( LPOLEOBJECT lpoleobj, LPOLESTREAM lpstream ){ DWORD dwFileVer = GetFileVersion(lpoleobj); LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj; OLESTATUS retval = OLE_ERROR_MEMORY; LPBYTE lpBytes = NULL ; HANDLE hBytes = NULL ;
if (!lpobj->hemf) return OLE_ERROR_BLANK;
if (HIWORD(dwFileVer) == OS_WIN16) if (!SaveEmfAsMfToStream(lpoleobj,lpstream)) return OLE_OK;
if (PutBytes (lpstream, (LPSTR) &dwFileVer, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutStrWithLen(lpstream, (LPSTR)"ENHMETAFILE")) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG))) return OLE_ERROR_STREAM;
if (PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG))) return OLE_ERROR_STREAM;
if (!(hBytes = GlobalAlloc(GHND, lpobj->sizeBytes)) ) goto error;
if (!(lpBytes = (LPBYTE)GlobalLock(hBytes)) ) goto error;
retval = OLE_ERROR_METAFILE;
if (GetEnhMetaFileBits((HENHMETAFILE)lpobj->hemf, lpobj->sizeBytes, lpBytes) != lpobj->sizeBytes ) goto error;
if (!PutBytes (lpstream, (LPSTR)lpBytes, lpobj->sizeBytes)) retval = OLE_OK;
error: if (lpBytes) GlobalUnlock(hBytes); if (hBytes) GlobalFree(hBytes);
return retval;
}
OLESTATUS FARINTERNAL EmfClone ( LPOLEOBJECT lpoleobjsrc, LPOLECLIENT lpclient, LHCLIENTDOC lhclientdoc, OLE_LPCSTR lpobjname, LPOLEOBJECT FAR * lplpoleobj ){ LPOBJECT_EMF lpobjsrc = (LPOBJECT_EMF)lpoleobjsrc; LPOBJECT_EMF lpobjEmf; HENHMETAFILE hemf;
*lplpoleobj = (LPOLEOBJECT)NULL;
if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc)) return OLE_ERROR_HANDLE;
if (!((HENHMETAFILE)hemf = CopyEnhMetaFile ((HENHMETAFILE)lpobjsrc->hemf, NULL))) return OLE_ERROR_MEMORY;
if (lpobjEmf = EmfCreateBlank (lhclientdoc, (LPSTR)lpobjname, lpobjsrc->head.ctype)) { lpobjEmf->sizeBytes = lpobjsrc->sizeBytes; lpobjEmf->head.lpclient = lpclient; lpobjEmf->hemf = hemf; EmfSetExtents (lpobjEmf);
*lplpoleobj = (LPOLEOBJECT)lpobjEmf; return OLE_OK; }
return OLE_ERROR_MEMORY; }
OLESTATUS FARINTERNAL EmfEqual ( LPOLEOBJECT lpoleobj1, LPOLEOBJECT lpoleobj2 ){ LPOBJECT_EMF lpobj1 = (LPOBJECT_EMF)lpoleobj1; HANDLE hBytes1 = NULL; LPBYTE lpBytes1 = NULL; LPOBJECT_EMF lpobj2 = (LPOBJECT_EMF)lpoleobj2; HANDLE hBytes2 = NULL; LPBYTE lpBytes2 = NULL; OLESTATUS retval = OLE_ERROR_MEMORY;
if (lpobj1->sizeBytes != lpobj2->sizeBytes) return OLE_ERROR_NOT_EQUAL;
if (!(hBytes1 = GlobalAlloc(GHND, lpobj1->sizeBytes)) ) goto errMemory;
if (!(lpBytes1 = (LPBYTE)GlobalLock(hBytes1)) ) goto errMemory;
if (!(hBytes2 = GlobalAlloc(GHND, lpobj2->sizeBytes)) ) goto errMemory;
if (!(lpBytes2 = (LPBYTE)GlobalLock(hBytes2)) ) goto errMemory;
if (GetEnhMetaFileBits((HENHMETAFILE)lpobj1->hemf, lpobj1->sizeBytes, lpBytes1) != lpobj1->sizeBytes) goto errMemory;
if (GetEnhMetaFileBits((HENHMETAFILE)lpobj2->hemf, lpobj2->sizeBytes, lpBytes2) != lpobj2->sizeBytes) goto errMemory;
if (CmpGlobals (hBytes1, hBytes2)) retval = OLE_OK; else retval = OLE_ERROR_NOT_EQUAL;
errMemory: if (lpBytes1) GlobalUnlock(lpBytes1); if (hBytes1) GlobalFree(hBytes1);
if (lpBytes2) GlobalUnlock(lpBytes2); if (hBytes2) GlobalFree(hBytes2);
return retval; }
OLESTATUS FARINTERNAL EmfCopy (LPOLEOBJECT lpoleobj) { LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj; HENHMETAFILE hemf;
if (!((HENHMETAFILE)hemf = CopyEnhMetaFile ((HENHMETAFILE)lpobj->hemf, NULL))) return OLE_ERROR_MEMORY;
SetClipboardData(CF_ENHMETAFILE, hemf);
return OLE_OK; }
OLESTATUS FARINTERNAL EmfQueryBounds ( LPOLEOBJECT lpoleobj, LPRECT lpRc ){ LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj;
Puts("EmfQueryBounds");
if (!lpobj->hemf) return OLE_ERROR_BLANK;
// Bounds are given in MM_HIMETRIC mode.
lpRc->left = 0; lpRc->top = 0; lpRc->right = (int) lpobj->head.cx; lpRc->bottom = (int) lpobj->head.cy; return OLE_OK;
}
OLECLIPFORMAT FARINTERNAL EmfEnumFormat ( LPOLEOBJECT lpoleobj, OLECLIPFORMAT cfFormat ){ UNREFERENCED_PARAMETER(lpoleobj);
if (!cfFormat) return CF_ENHMETAFILE;
return 0; }
OLESTATUS FARINTERNAL EmfGetData ( LPOLEOBJECT lpoleobj, OLECLIPFORMAT cfFormat, LPHANDLE lphandle ){ LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj;
if (cfFormat != CF_ENHMETAFILE) return OLE_ERROR_FORMAT;
if (!(*lphandle = lpobj->hemf)) return OLE_ERROR_BLANK;
return OLE_OK; }
LPOBJECT_EMF FARINTERNAL EmfCreateObject ( HANDLE hMeta, LPOLECLIENT lpclient, BOOL fDelete, LHCLIENTDOC lhclientdoc, LPCSTR lpobjname, LONG objType ){ LPOBJECT_EMF lpobj;
if (lpobj = EmfCreateBlank (lhclientdoc, (LPSTR)lpobjname, objType)) { if (EmfChangeData ((LPOLEOBJECT)lpobj, hMeta, lpclient, fDelete) != OLE_OK) { EmfRelease ((LPOLEOBJECT)lpobj); lpobj = NULL; } }
return lpobj; }
// If the routine fails then the object will be left with it's old data.
// If fDelete is TRUE, then hMeta, and the hMF it contains will be deleted
// whether the routine is successful or not.
OLESTATUS FARINTERNAL EmfChangeData ( LPOLEOBJECT lpoleobj, HANDLE hMeta, LPOLECLIENT lpclient, BOOL fDelete ){ LPOBJECT_EMF lpobj = (LPOBJECT_EMF)lpoleobj; DWORD dwSizeBytes; Puts("EmfChangeData");
if (hMeta) { dwSizeBytes = lpobj->sizeBytes; if (lpobj->sizeBytes = GetEnhMetaFileBits(hMeta, 0, NULL)) { if (lpobj->hemf) DeleteEnhMetaFile ((HENHMETAFILE)lpobj->hemf); if (fDelete) lpobj->hemf = hMeta; else (HENHMETAFILE)lpobj->hemf = CopyEnhMetaFile(hMeta,NULL); lpobj->head.lpclient = lpclient; EmfSetExtents (lpobj); return OLE_OK; } else lpobj->sizeBytes = dwSizeBytes; }
return OLE_ERROR_METAFILE;
}
LPOBJECT_EMF FARINTERNAL EmfCreateBlank( LHCLIENTDOC lhclientdoc, LPSTR lpobjname, LONG objType ){ HOBJECT hobj; LPOBJECT_EMF lpobj;
if(!(hobj = GlobalAlloc (GHND, sizeof(OBJECT_EMF)))) return NULL;
if (!(lpobj = (LPOBJECT_EMF) GlobalLock (hobj))){ GlobalFree (hobj); return NULL; }
lpobj->head.objId[0] = 'L'; lpobj->head.objId[1] = 'E'; lpobj->head.ctype = objType; lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblEMF; lpobj->head.iTable = INVALID_INDEX; lpobj->head.hobj = hobj;
if (objType == CT_STATIC) DocAddObject ((LPCLIENTDOC) lhclientdoc, (LPOLEOBJECT) lpobj, lpobjname);
// Unlock will be done at object deletion time.
return lpobj; }
OLESTATUS FARINTERNAL EmfLoadFromStream ( LPOLESTREAM lpstream, LPOLECLIENT lpclient, LHCLIENTDOC lhclientdoc, LPSTR lpobjname, LPOLEOBJECT FAR * lplpobj, LONG objType ){ LPOBJECT_EMF lpobj = NULL; OLESTATUS retval = OLE_ERROR_STREAM; HANDLE hBytes = NULL; LPBYTE lpBytes = NULL;
// Class name would've been read by this time.
*lplpobj = NULL;
if (!(lpobj = EmfCreateBlank (lhclientdoc, lpobjname, objType))) return OLE_ERROR_MEMORY;
lpobj->head.lpclient = lpclient;
if (GetBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG))) goto error;
if (GetBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG))) goto error;
if (GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG))) goto error;
if (!lpobj->sizeBytes) { retval = OLE_ERROR_BLANK; goto error; }
retval = OLE_ERROR_MEMORY; if (!(hBytes = GlobalAlloc (GHND, lpobj->sizeBytes))) goto error;
if (!(lpBytes = (LPBYTE)GlobalLock (hBytes))) goto error;
if (GetBytes (lpstream, (LPSTR)lpBytes, lpobj->sizeBytes)) goto error;
if (!((HENHMETAFILE)lpobj->hemf = SetEnhMetaFileBits (lpobj->sizeBytes,lpBytes)) ) goto error;
EmfSetExtents (lpobj);
*lplpobj = (LPOLEOBJECT) lpobj; GlobalUnlock(hBytes); GlobalFree (hBytes); return OLE_OK;
error: if (lpBytes) GlobalUnlock(hBytes); if (hBytes) GlobalFree (hBytes);
OleDelete ((LPOLEOBJECT)lpobj); return retval; }
OLESTATUS FARINTERNAL EmfPaste ( LPOLECLIENT lpclient, LHCLIENTDOC lhclientdoc, LPSTR lpobjname, LPOLEOBJECT FAR * lplpoleobject, LONG objType ){ HANDLE hMeta;
*lplpoleobject = NULL;
if((hMeta = GetClipboardData (CF_ENHMETAFILE)) == NULL) return OLE_ERROR_MEMORY;
if (!(*lplpoleobject = (LPOLEOBJECT) EmfCreateObject (hMeta, lpclient, FALSE, lhclientdoc, lpobjname, objType))) return OLE_ERROR_MEMORY;
return OLE_OK; }
void FARINTERNAL EmfSetExtents (LPOBJECT_EMF lpobj) { ENHMETAHEADER enhmetaheader;
GetEnhMetaFileHeader((HENHMETAFILE)lpobj->hemf, sizeof(enhmetaheader), &enhmetaheader);
lpobj->head.cx = enhmetaheader.rclFrame.right - enhmetaheader.rclFrame.left; lpobj->head.cy = enhmetaheader.rclFrame.top - enhmetaheader.rclFrame.bottom;
}
|