📄 helpers.cpp
字号:
/*
* HELPERS.CPP
*
* Utility functions for drawing various graphical effects
* as well as coordinate conversion functions.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "inoledll.h"
/*
* INOLE_MetafilePictIconFree
*
* Purpose:
* Deletes the metafile contained in a METAFILEPICT structure and
* frees the memory for the structure itself.
*
* Parameters:
* hMetaPict HGLOBAL metafilepict structure created in
* OleMetafilePictFromIconAndLabel
*
* Return Value:
* None
*/
STDAPI_(void) INOLE_MetafilePictIconFree(HGLOBAL hMetaPict)
{
LPMETAFILEPICT pMF;
if (NULL==hMetaPict)
return;
pMF=(LPMETAFILEPICT)GlobalLock(hMetaPict);
if (NULL!=pMF)
{
if (NULL!=pMF->hMF)
DeleteMetaFile(pMF->hMF);
}
GlobalUnlock(hMetaPict);
GlobalFree(hMetaPict);
return;
}
/*
* INOLE_SwitchDisplayAspect
*
* Purpose:
* Switch the currently cached display aspect between DVASPECT_ICON
* and DVASPECT_CONTENT. When setting up icon aspect, any currently
* cached content cache is discarded and any advise connections for
* content aspect are broken.
*
* Parameters:
* pObj IUnknown * to the object in question
* pdwCurAspect DWORD * containing the current aspect which
* will contain the new aspect on output.
* dwNewAspect DWORD with the aspect to switch to.
* hMetaPict HGLOBAL containing the CF_METAFILEPICT with
* the icon.
* fDeleteOld BOOL indicating if we're to delete the old
* aspect from the cache.
* fViewAdvise BOOL indicating if we're to establish an
* advise with the object for this new aspect.
* pSink IAdviseSink * to the notification sink.
* pfMustUpdate BOOL * in which to return whether or not
* an update from a running server is necessary.
*
* Return Value:
* HRESULT NOERROR or an error code in which case the cache
* remains unchanged.
*/
STDAPI INOLE_SwitchDisplayAspect(IUnknown *pObj, LPDWORD pdwCurAspect
, DWORD dwNewAspect, HGLOBAL hMetaPict, BOOL fDeleteOld
, BOOL fViewAdvise, IAdviseSink *pSink, BOOL *pfMustUpdate)
{
IOleCache *pCache=NULL;
FORMATETC fe;
STGMEDIUM stm;
DWORD dwAdvf;
DWORD dwNewConnection;
DWORD dwOldAspect=*pdwCurAspect;
HRESULT hr;
if (pfMustUpdate)
*pfMustUpdate=FALSE;
hr=pObj->QueryInterface(IID_IOleCache, (void **)&pCache);
if (FAILED(hr))
return ResultFromScode(E_FAIL);
//Establish new cache with the new aspect
SETFormatEtc(fe, 0, dwNewAspect, NULL, TYMED_NULL, -1);
/*
* If we are using a custom icon for the display aspect then
* we won't want to establish notifications with the data
* source, that is, we don't want to change the icon. Otherwise
* we link up the given advise sink.
*/
if (DVASPECT_ICON==dwNewAspect && NULL!=hMetaPict)
dwAdvf=ADVF_NODATA;
else
dwAdvf=ADVF_PRIMEFIRST;
hr=pCache->Cache(&fe, dwAdvf, &dwNewConnection);
if (FAILED(hr))
{
pCache->Release();
return hr;
}
*pdwCurAspect=dwNewAspect;
/*
* Stuff the custom icon into the cache, or force an update
* from the server.
*/
if (DVASPECT_ICON==dwNewAspect && NULL!=hMetaPict)
{
SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
, TYMED_MFPICT, -1);
stm.tymed=TYMED_MFPICT;
stm.hGlobal=hMetaPict;
stm.pUnkForRelease=NULL;
hr=pCache->SetData(&fe, &stm, FALSE);
}
else
{
if (pfMustUpdate)
*pfMustUpdate=TRUE;
}
if (fViewAdvise && pSink)
{
IViewObject *pView=NULL;
hr=pObj->QueryInterface(IID_IViewObject, (void **)&pView);
if (SUCCEEDED(hr))
{
pView->SetAdvise(dwNewAspect, 0, pSink);
pView->Release();
}
}
/*
* Remove existing caches for the old display aspect to cut
* down on needless storage overhead. If you want to switch
* frequently between icon and content aspects, then it is
* best to actually keep both presentations in the cache.
*/
if (fDeleteOld)
{
IEnumSTATDATA *pEnum=NULL;
STATDATA sd;
hr=pCache->EnumCache(&pEnum);
while(NOERROR==hr)
{
hr=pEnum->Next(1, &sd, NULL);
if (NOERROR==hr)
{
//Remove old aspect caches
if (sd.formatetc.dwAspect==dwOldAspect)
pCache->Uncache(sd.dwConnection);
}
}
if (NULL!=pEnum)
pEnum->Release();
}
pCache->Release();
return NOERROR;
}
/*
* INOLE_SetIconInCache
*
* Purpose:
* Stores an iconic presentation metafile in the cache.
*
* Parameters:
* pObj IUnknown * of the object.
* hMetaPict HGLOBAL containing the presentation.
*
* Return Value:
* HRESULT From IOleCache::SetData.
*/
STDAPI INOLE_SetIconInCache(IUnknown *pObj, HGLOBAL hMetaPict)
{
IOleCache *pCache;
FORMATETC fe;
STGMEDIUM stm;
HRESULT hr;
if (NULL==hMetaPict)
return ResultFromScode(E_INVALIDARG);
if (FAILED(pObj->QueryInterface(IID_IOleCache, (void **)&pCache)))
return ResultFromScode(E_NOINTERFACE);
SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
, TYMED_MFPICT, -1);
stm.tymed=TYMED_MFPICT;
stm.hGlobal=hMetaPict;
stm.pUnkForRelease=NULL;
hr=pCache->SetData(&fe, &stm, FALSE);
pCache->Release();
return hr;
}
/*
* INOLE_GetUserTypeOfClass
*
* Purpose:
* Returns the user type (human readable class name) of the
* specified class as stored in the registry.
*
* Parameters:
* clsID CLSID in question
* iName UINT index to the name to retrieve, where
* zero is the name found as the value of
* of the CLSID, anything else tries
* AuxUserType\iName.
* pszUserType LPTSTR in which to return the type
* cch UINT length of pszUserType
*
* Return Value:
* UINT Number of characters in returned string.
* 0 on error.
*/
STDAPI_(UINT) INOLE_GetUserTypeOfClass(REFCLSID clsID, UINT iName
, LPTSTR pszUserType, UINT cch)
{
LPTSTR pszCLSID;
LPTSTR pszProgID;
TCHAR szKey[300];
LONG dw;
LONG lRet;
if (!pszUserType)
return 0;
*pszUserType='\0';
//Get a string containing the class name
StringFromCLSID(clsID, &pszCLSID);
if (0==iName)
wsprintf(szKey, TEXT("CLSID\\%s"), pszCLSID);
else
{
wsprintf(szKey, TEXT("CLSID\\%s\\AuxUserType\\%u")
, pszCLSID, iName);
}
CoTaskMemFree(pszCLSID);
dw=cch;
lRet=RegQueryValue(HKEY_CLASSES_ROOT, szKey, pszUserType, &dw);
if (ERROR_SUCCESS!=lRet)
{
lstrcpyn(pszUserType, TEXT("Unknown"), cch);
if (CoIsOle1Class(clsID))
{
//Try to get ProgID value for OLE 1 class
ProgIDFromCLSID(clsID, &pszProgID);
dw=cch;
lRet=RegQueryValue(HKEY_CLASSES_ROOT, pszProgID
, pszUserType, &dw);
CoTaskMemFree(pszProgID);
if (ERROR_SUCCESS!=lRet)
dw=0;
}
}
return (UINT)dw;
}
/*
* INOLE_DoConvert
*
* Purpose:
* Convert an embedded or linked object to another type, working
* in conjunection with OleUIConvert.
*
* Parameters:
* pIStorage IStorage * to the object's data.
* clsID CLSID to which we convert the object.
*
* Return Value:
* HRESULT The usual.
*/
STDAPI INOLE_DoConvert(IStorage *pIStorage, REFCLSID clsID)
{
HRESULT hr;
CLSID clsIDOrg;
CLIPFORMAT cfOrg;
LPTSTR pszOrg=NULL;
TCHAR szNew[256];
if (FAILED(ReadClassStg(pIStorage, &clsIDOrg)))
return ResultFromScode(E_FAIL);
//Read original format/user type
hr=ReadFmtUserTypeStg(pIStorage, &cfOrg, &pszOrg);
//Get new user type
if (0==INOLE_GetUserTypeOfClass(clsID, 0, szNew, 256))
lstrcpy(szNew, TEXT(""));
//Write new class into the storage
if (SUCCEEDED(WriteClassStg(pIStorage, clsID)))
{
if (SUCCEEDED(WriteFmtUserTypeStg(pIStorage, cfOrg
, szNew)))
{
SetConvertStg(pIStorage, TRUE);
CoTaskMemFree((void *)pszOrg);
return NOERROR;
}
//Failed to write new type, restore the old class
WriteClassStg(pIStorage, clsIDOrg);
}
CoTaskMemFree((void *)pszOrg);
return ResultFromScode(E_FAIL);
}
/*
* INOLE_CopyString
*
* Purpose:
* Copies a string allocated with CoTaskMemAlloc.
*
* Parameters:
* pszSrc LPTSTR to the string to copy.
*
* Return Value:
* LPTSTR New string or a NULL.
*/
STDAPI_(LPTSTR) INOLE_CopyString(LPTSTR pszSrc)
{
IMalloc *pIMalloc;
LPTSTR pszDst;
UINT cch;
cch=lstrlen(pszSrc);
if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
return NULL;
pszDst=(LPTSTR)pIMalloc->Alloc((cch+1)*sizeof(TCHAR));
if (NULL!=pszDst)
lstrcpy(pszDst, pszSrc);
pIMalloc->Release();
return pszDst;
}
/*
* INOLE_ObjectDescriptorFromOleObject
*
* Purpose:
* Fills and returns an OBJECTDESCRIPTOR structure. Information
* for the structure is obtained from an IOleObject instance.
*
* Parameters:
* pObj IOleObject * from which to retrieve information.
* dwAspect DWORD with the display aspect
* ptl POINTL from upper-left corner of object where
* mouse went down for use with Drag & Drop.
* pszl LPSIZEL (optional) if the object is being scaled in
* its container, then the container should pass the
* extents that it is using to display the object.
*
* Return Value:
* HBGLOBAL Handle to OBJECTDESCRIPTOR structure.
*/
STDAPI_(HGLOBAL) INOLE_ObjectDescriptorFromOleObject
(IOleObject *pObj, DWORD dwAspect, POINTL ptl, LPSIZEL pszl)
{
CLSID clsID;
LPTSTR pszName=NULL;
LPTSTR pszSrc=NULL;
BOOL fLink=FALSE;
IOleLink *pLink;
TCHAR szName[512];
DWORD dwMisc=0;
SIZEL szl;
HGLOBAL hMem;
HRESULT hr;
#ifdef WIN32ANSI
//#ifndef UNICODE
LPWSTR pszw;
char szTemp[512];
#endif
if (SUCCEEDED(pObj->QueryInterface(IID_IOleLink
, (void **)&pLink)))
fLink=TRUE;
if (FAILED(pObj->GetUserClassID(&clsID)))
clsID=CLSID_NULL;
//Get user string, expand to "Linked %s" if this is link
#ifndef WIN32ANSI
//#ifdef UNICODE
pObj->GetUserType(USERCLASSTYPE_FULL, &pszName);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -