|
|
//+---------------------------------------------------------------------
//
// File: dvutils.cxx
//
// Contents: Helper functions for implementing IDataObject and IViewObject
//
//----------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
//
// Globals
//
UINT OleClipFormat[OCF_LAST+1]; // array of OLE standard clipboard formats
// these are the names of the standard OLE clipboard formats that need to
// be registered.
LPTSTR OleClipNames[OCF_LAST+1] = { TEXT("ObjectLink"), TEXT("OwnerLink"), TEXT("Native"), TEXT("FileName"), TEXT("NetworkName"), TEXT("DataObject"), TEXT("Embedded Object"), TEXT("Embed Source"), TEXT("Link Source"), TEXT("Link Source Descriptor"), TEXT("Object Descriptor"), TEXT("OleDraw") };
//+---------------------------------------------------------------
//
// Function: RegisterOleClipFormats
//
// Synopsis: Initializes the OleClipFormat table of standard
// OLE clipboard formats.
//
// Notes: The OleClipFormat table is a table of registered,
// standard, OLE-related clipboard formats. The table
// is indexed by the OLECLIPFORMAT enumeration.
// Before this table can be used it must be initialized
// via this function.
// This function is usually called in the WinMain or
// LibMain of the module using the OleClipFormat table.
//
//----------------------------------------------------------------
void RegisterOleClipFormats(void) { for (int i = 0; i<= OCF_LAST; i++) OleClipFormat[i] = RegisterClipboardFormat(OleClipNames[i]); }
//+---------------------------------------------------------------
//
// Function: IsCompatibleDevice, public
//
// Synopsis: Compares two DEVICETARGET structures and returns
// TRUE if they are compatible.
//
// Arguments: [ptdLeft] -- A pointer to a device target
// [ptdRight] -- Another pointer to a device target
//
// Notes: The target devices are compatible if they are both
// NULL or if they are identical. Otherwise they are
// incompatible.
//
//----------------------------------------------------------------
BOOL IsCompatibleDevice(DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight) { // same address of td; must be same (handles NULL case)
if (ptdLeft == ptdRight) return TRUE;
#if 1
//fix for NTbug 20692 - reason: see bad assumption below
if ((ptdRight == DVTARGETIGNORE) || (ptdLeft == DVTARGETIGNORE)) return TRUE; #endif
// The following is a wrong assumption for device independant formats
// like CF_DIB and CF_METAFILE
// if ones NULL, and the others not then they are incompatible
if ((ptdRight == NULL) || (ptdLeft == NULL)) return FALSE;
// different sizes, not equal
if (ptdLeft->tdSize != ptdRight->tdSize) return FALSE;
return _fmemcmp(ptdLeft, ptdRight, (size_t)ptdLeft->tdSize) == 0; }
//+---------------------------------------------------------------
//
// Function: IsCompatibleFormat, public
//
// Synopsis: Compares two FORMATETC structures and returns
// TRUE if they are compatible.
//
// Arguments: [f1] -- A FORMATETC structure
// [f2] -- Another FORMATETC structure
//
// Notes: This function ignores the lindex member of the
// FORMATETCs.
//
//----------------------------------------------------------------
BOOL IsCompatibleFormat(FORMATETC& f1, FORMATETC& f2) { return f1.cfFormat == f2.cfFormat && IsCompatibleDevice(f1.ptd, f2.ptd) && (f1.dwAspect & f2.dwAspect) != 0L && (f1.tymed & f2.tymed) != 0; }
//+---------------------------------------------------------------
//
// Function: FindCompatibleFormat
//
// Synopsis: Searches a table of FORMATETC structures and
// returns the index of the first entry that is
// compatible with a specified FORMATETC.
//
// Arguments: [FmtTable] -- the table of FORMATETCs
// [iSize] -- the number of entries in the format table
// [formatetc] -- the FORMATETC we are comparing for compatibility
//
// Returns: The index into the table of the compatible format, or
// -1 if no compatible format was found.
//
// Notes: This function is typically used in conjunction with
// IDataObject methods that need to check if a requested format
// is available.
//
//----------------------------------------------------------------
int FindCompatibleFormat(FORMATETC FmtTable[], int iSize, FORMATETC& formatetc) { // look through the table for a compatible format
for (int i = 0; i < iSize; i++) { if (IsCompatibleFormat(formatetc, FmtTable[i])) return i; } return -1; }
//+---------------------------------------------------------------
//
// Function: GetObjectDescriptor
//
// Synopsis: Extracts an OBJECTDESCRIPTOR from an IDataObject,
// if available.
//
// Arguments: [pDataObj] -- data object from which to extract an object descriptor
// [pDescOut] -- object descriptor structure to fill in
//
// Returns: Success iff the object descriptor could be extracted.
// This does not copy out the dwFullUserTypeName or
// dwSrcOfCopy strings.
//
//----------------------------------------------------------------
HRESULT GetObjectDescriptor(LPDATAOBJECT pDataObj, LPOBJECTDESCRIPTOR pDescOut) { HRESULT r; HGLOBAL hglobal = GlobalAlloc(GMEM_SHARE, sizeof(OBJECTDESCRIPTOR)+256); LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hglobal); if (pObjDesc == NULL) { DOUT(TEXT("o2base/dvutils/GetObjectDescriptor failed\r\n")); r = E_OUTOFMEMORY; } else { FORMATETC formatetc = { (WORD)OleClipFormat[OCF_OBJECTDESCRIPTOR], NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmedium; stgmedium.tymed = TYMED_HGLOBAL; stgmedium.hGlobal = hglobal; stgmedium.pUnkForRelease = NULL;
if (OK(r = pDataObj->GetDataHere(&formatetc, &stgmedium))) { if (pDescOut != NULL) { // note: in the future we may wish to copy out the strings
// into two out parameters. This would be used in
// implementing the Paste Special dialog box.
*pDescOut = *pObjDesc; pDescOut->dwFullUserTypeName = 0; pDescOut->dwSrcOfCopy = 0; } } GlobalUnlock(hglobal); GlobalFree(hglobal); } return r; }
//+---------------------------------------------------------------
//
// Function: UpdateObjectDescriptor
//
// Synopsis: Updates the pointl and dwDrawAspects of an OBJECTDESCRIPTOR
// on a data object
//
// Arguments: [pDataObj] -- the data object to update
// [ptl] -- the pointl to update in the object descriptor
// [dwAspect] -- the draw aspect to update in the object descriptor
//
// Returns: Success iff the object descriptor could be updated
//
// Notes: This method is for IDataObjects used in drag-drop.
// The object being dragged supplies the object descriptor but only
// the container knows where the point that the mouse button went
// down relative to the corner of the object, and what aspect
// of the object the container is displaying.
// The container uses this method to fill in that missing information.
// This performs a GetDataHere on the object to get a filled-in
// object descriptor. It then updates the pointl and dwDrawAspect
// fields and uses SetData to update the object.
//
//----------------------------------------------------------------
HRESULT UpdateObjectDescriptor(LPDATAOBJECT pDataObj, POINTL& ptl, DWORD dwAspect) { HRESULT r; HGLOBAL hglobal = GlobalAlloc(GMEM_SHARE, sizeof(OBJECTDESCRIPTOR)+256); LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hglobal); if (pObjDesc == NULL) { DOUT(TEXT("o2base/dvutils/UpdateObjectDescriptor failed\r\n")); r = E_OUTOFMEMORY; } else { FORMATETC formatetc = { (WORD)OleClipFormat[OCF_OBJECTDESCRIPTOR], NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmedium; stgmedium.tymed = TYMED_HGLOBAL; stgmedium.hGlobal = hglobal; stgmedium.pUnkForRelease = NULL;
if (OK(r = pDataObj->GetDataHere(&formatetc, &stgmedium))) { pObjDesc->pointl = ptl; pObjDesc->dwDrawAspect = dwAspect; r = pDataObj->SetData(&formatetc, &stgmedium, FALSE); } GlobalUnlock(hglobal); GlobalFree(hglobal); } return r; }
//+---------------------------------------------------------------
//
// Function: DrawMetafile
//
// Synopsis: Creates a metafile from an IViewObject using the Draw method
//
// Arguments: [pVwObj] -- the view object
// [rc] -- rectangle on the view object to draw
// [dwAspect] -- aspect of the view object to draw, typically
// content or icon
// [pHMF] -- place where handle to the metafile is drawn
//
// Returns: Success iff the metafile was drawn successfully.
//
//----------------------------------------------------------------
HRESULT DrawMetafile(LPVIEWOBJECT pVwObj, RECT& rc, DWORD dwAspect, HMETAFILE FAR* pHMF) { HRESULT hr; HMETAFILE hmf = NULL; HDC hdc;
if ((hdc = CreateMetaFile(NULL)) == NULL) { DOUT(TEXT("o2base/dvutils/DrawMetafile failed to create metafile\r\n")); hr = E_OUTOFMEMORY; } else { SetMapMode(hdc, MM_ANISOTROPIC); SetWindowOrgEx(hdc, 0, 0, NULL); SetWindowExtEx(hdc, rc.right, rc.bottom, NULL);
hr = OleDraw(pVwObj, dwAspect, hdc, &rc);
hmf = CloseMetaFile(hdc);
if (!OK(hr)) { DeleteMetaFile(hmf); hmf = NULL; }
if (hmf == NULL) { DOUT(TEXT("o2base/dvutils/DrawMetafile failed\r\n")); hr = E_OUTOFMEMORY; } } *pHMF = hmf; return hr; }
|