windows-nt/Source/XPSP1/NT/multimedia/media/sndrec32/o2base/dvutils.cxx
2020-09-26 16:20:57 +08:00

337 lines
10 KiB
C++

//+---------------------------------------------------------------------
//
// 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;
}