📄 rtfread2.cpp
字号:
// Create another object site for the new object
_ped->GetClientSite(&reobj.polesite) ;
if (!reobj.polesite )
{
goto Cleanup;
}
if (FAILED(pOleLoad(reobj.pstg, IID_IOleObject, reobj.polesite,
(LPVOID *) &reobj.poleobj)))
{
goto Cleanup;
}
if(!fGotClsid) {
// we weren't able to obtain a clsid from the progid
// in the \objclass RTF tag
reobj.poleobj->GetUserClassID(&reobj.clsid);
}
reobj.cbStruct = sizeof(REOBJECT);
reobj.cp = _prg->GetCp();
reobj.sizel.cx = HimetricFromTwips(_prtfObject->xExt)
* _prtfObject->xScale / 100;
reobj.sizel.cy = HimetricFromTwips(_prtfObject->yExt)
* _prtfObject->yScale / 100;
// Read any container flags which may have been previously saved
if (!ObjectReadSiteFlags(&reobj))
{
// If no flags, make best guess
reobj.dwFlags = REO_RESIZABLE;
}
reobj.dvaspect = DVASPECT_CONTENT; // OLE 1 forces DVASPECT_CONTENT
// Ask the cache if it knows what to display
if (SUCCEEDED(reobj.poleobj->QueryInterface(IID_IOleCache, (void**)&polecache)) &&
SUCCEEDED(polecache->EnumCache(&penumstatdata)))
{
// Go look for the best cached presentation CF_METAFILEPICT
while (penumstatdata->Next(1, &statdata, NULL) == S_OK)
{
if (statdata.formatetc.cfFormat == CF_METAFILEPICT)
{
LPDATAOBJECT pdataobj = NULL;
STGMEDIUM med;
BOOL fUpdate;
ZeroMemory(&med, sizeof(STGMEDIUM));
if (SUCCEEDED(polecache->QueryInterface(IID_IDataObject, (void**)&pdataobj)) &&
SUCCEEDED(pdataobj->GetData(&statdata.formatetc, &med)))
{
HANDLE hGlobal;
hGlobal = med.hGlobal;
if( FIsIconMetafilePict(hGlobal) )
{
// BUGBUG: was !OleStdSwitchDisplayAspect(...)
OleStdSwitchDisplayAspect(reobj.poleobj, &reobj.dvaspect,
DVASPECT_ICON, med.hGlobal,
TRUE, FALSE, NULL, &fUpdate);
}
}
pReleaseStgMedium(&med);
if (pdataobj)
{
pdataobj->Release();
}
break;
}
}
polecache->Release();
penumstatdata->Release();
}
// This code is borrowed from RichEdit1.0; Word generates
// bogus objects, so we need to compensate.
if( reobj.dvaspect == DVASPECT_CONTENT )
{
IStream *pstm = NULL;
BYTE bT;
BOOL fUpdate;
if (SUCCEEDED(reobj.pstg->OpenStream(OLESTR("\3ObjInfo"), 0, STGM_READ |
STGM_SHARE_EXCLUSIVE, 0, &pstm)) &&
SUCCEEDED(pstm->Read(&bT, sizeof(BYTE), NULL)) &&
(bT & 0x40))
{
_fNeedIcon = TRUE;
_fNeedPres = TRUE;
_pobj = (COleObject *)reobj.polesite;
OleStdSwitchDisplayAspect(reobj.poleobj, &reobj.dvaspect, DVASPECT_ICON,
NULL, TRUE, FALSE, NULL, &fUpdate);
}
if( pstm )
{
pstm->Release();
}
}
// Since we are loading an object, it shouldn't be blank
reobj.dwFlags &= ~REO_BLANK;
_prg->Set_iCF(-1);
_prg->ReplaceRange(1, &ch, NULL, SELRR_IGNORE);
hr = ObjectMgr->InsertObject(reobj.cp, &reobj, NULL);
if (FAILED(hr))
{
goto Cleanup;
}
// Word doesn't give us objects with presenation
// caches; as a result, we can't draw them! In order to get around this,
// we check to see if there is a presentation cache (via the same way
// RE1.0 did) using a GetExtent call. If that fails, we'll just use
// the presentation stored in the RTF.
//
// COMPATIBILITY ISSUE: RE1.0, instead of using the presenation stored
// in RTF, would instead call IOleObject::Update. There are two _big_
// drawbacks to this approach: 1. it's incredibly expensive (potentially,
// MANY SECONDS per object), and 2. it doesn't work if the object server
// is not installed on the machine.
SIZE sizeltemp;
if( reobj.poleobj->GetExtent(reobj.dvaspect, &sizeltemp) != NOERROR )
{
_fNeedPres = TRUE;
_pobj = (COleObject *)reobj.polesite;
}
fRet = TRUE;
Cleanup:
if (reobj.pstg) reobj.pstg->Release();
if (reobj.polesite) reobj.polesite->Release();
if (reobj.poleobj) reobj.poleobj->Release();
return fRet;
}
/*
* ObHBuildMetafilePict(prtfobject, hBits)
*
* Purpose:
* Build a METAFILEPICT from RTFOBJECT and the raw data.
*
* Arguments:
* RTFOBJECT * The details we picked up from RTF
* HGLOBAL A handle to the raw data
*
* Returns:
* HGLOBAL Handle to a METAFILEPICT
*/
HGLOBAL ObHBuildMetafilePict(RTFOBJECT *prtfobject, HGLOBAL hBits)
{
#ifndef NOMETAFILES
HGLOBAL hmfp = NULL;
LPMETAFILEPICT pmfp = NULL;
SCODE sc = E_OUTOFMEMORY;
LPBYTE pbBits;
ULONG cbBits;
// Allocate the METAFILEPICT structure
hmfp = GlobalAlloc(GHND, sizeof(METAFILEPICT));
if (!hmfp)
goto Cleanup;
// Lock it down
pmfp = (LPMETAFILEPICT) GlobalLock(hmfp);
if (!pmfp)
goto Cleanup;
// Put in the header information
pmfp->mm = prtfobject->sPictureType;
pmfp->xExt = prtfobject->xExt;
pmfp->yExt = prtfobject->yExt;
// Set the metafile bits
pbBits = (LPBYTE) GlobalLock(hBits);
cbBits = GlobalSize(hBits);
pmfp->hMF = SetMetaFileBitsEx(cbBits, pbBits);
// We can throw away the data now since we don't need it anymore
GlobalUnlock(hBits);
GlobalFree(hBits);
if (!pmfp->hMF)
goto Cleanup;
GlobalUnlock(hmfp);
sc = S_OK;
Cleanup:
if (sc && hmfp)
{
if (pmfp)
GlobalUnlock(hmfp);
GlobalFree(hmfp);
hmfp = NULL;
}
TRACEERRSZSC("ObHBuildMetafilePict", sc);
return hmfp;
#else
return NULL;
#endif
}
/*
* ObHBuildBitmap
*
* Purpose:
* Build a BITMAP from RTFOBJECT and the raw data
*
* Arguments:
* RTFOBJECT * The details we picked up from RTF
* HGLOBAL A handle to the raw data
*
* Returns:
* HGLOBAL Handle to a BITMAP
*/
HGLOBAL ObHBuildBitmap(RTFOBJECT *prtfobject, HGLOBAL hBits)
{
HBITMAP hbm = NULL;
LPVOID pvBits = GlobalLock(hBits);
if (!pvBits)
goto Cleanup;
hbm = CreateBitmap(prtfobject->xExt, prtfobject->yExt,
prtfobject->cColorPlanes, prtfobject->cBitsPerPixel,
pvBits);
Cleanup:
GlobalUnlock(hBits);
GlobalFree(hBits);
return hbm;
}
/*
* ObHBuildDib
*
* Purpose:
* Build a DIB from RTFOBJECT and the raw data
*
* Arguments:
* RTFOBJECT * The details we picked up from RTF
* HGLOBAL A handle to the raw data
*
* Returns:
* HGLOBAL Handle to a DIB
*/
HGLOBAL ObHBuildDib(RTFOBJECT *prtfobject, HGLOBAL hBits)
{
// Apparently DIB's are just a binary dump
return hBits;
}
/*
* CRTFRead::StaticObjectReadFromEditstream
*
* Purpose:
* Reads an picture from the RTF output stream.
*
* Returns:
* BOOL TRUE on success, FALSE on failure.
*/
#define cbBufferMax 16384
#define cbBufferStep 1024
#define cbBufferMin 1024
BOOL CRTFRead::StaticObjectReadFromEditStream(int cb)
{
HRESULT hr;
BOOL fRet = FALSE;
LPPERSISTSTORAGE pperstg = NULL;
LPOLECACHE polecache = NULL;
REOBJECT reobj = { 0 };
LPSTREAM pstm = NULL;
LPBYTE pbBuffer = NULL;
LONG cbRead;
LONG cbBuffer;
FORMATETC formatetc;
STGMEDIUM stgmedium;
DWORD dwConn;
HGLOBAL hBits = NULL;
HGLOBAL (*pfnBuildPict)(RTFOBJECT *, HGLOBAL) = NULL;
LPRICHEDITOLECALLBACK precall ;
DWORD dwAdvf;
WCHAR ch = WCH_EMBEDDING;
CObjectMgr *ObjectMgr = _ped->GetObjectMgr();
if (! ObjectMgr)
goto Cleanup;
// precall may end up being null (e.g. Windows CE).
precall = ObjectMgr->GetRECallback();
// Initialize various data structures
formatetc.ptd = NULL;
formatetc.dwAspect = DVASPECT_CONTENT;
formatetc.lindex = -1;
switch (_prtfObject->sType)
{
case ROT_Metafile:
reobj.clsid = CLSID_StaticMetafile;
formatetc.cfFormat = CF_METAFILEPICT;
formatetc.tymed = TYMED_MFPICT;
pfnBuildPict = ObHBuildMetafilePict;
break;
case ROT_Bitmap:
reobj.clsid = CLSID_StaticDib;
formatetc.cfFormat = CF_BITMAP;
formatetc.tymed = TYMED_GDI;
pfnBuildPict = ObHBuildBitmap;
break;
case ROT_DIB:
reobj.clsid = CLSID_StaticDib;
formatetc.cfFormat = CF_DIB;
formatetc.tymed = TYMED_HGLOBAL;
pfnBuildPict = ObHBuildDib;
break;
default:
AssertSz(0, "Bad ObjectType in CRTFRead::StaticObjectReadFromEditStream");
goto Cleanup;
}
reobj.sizel.cx = (LONG) HimetricFromTwips(_prtfObject->xExtGoal)
* _prtfObject->xScale / 100;
reobj.sizel.cy = (LONG) HimetricFromTwips(_prtfObject->yExtGoal)
* _prtfObject->yScale / 100;
stgmedium.tymed = formatetc.tymed;
stgmedium.pUnkForRelease = NULL;
if (precall)
{
if( !_fNeedPres )
{
// Get storage for the object from the application
if (FAILED(precall->GetNewStorage(&reobj.pstg)))
{
goto Cleanup;
}
}
// Let's create a stream on HGLOBAL
if (FAILED(hr = pCreateStreamOnHGlobal(NULL, FALSE, &pstm)))
{
goto Cleanup;
}
// Allocate a buffer, preferably a big one
for (cbBuffer = cbBufferMax;
cbBuffer >= cbBufferMin;
cbBuffer -= cbBufferStep)
{
pbBuffer = (unsigned char *)PvAlloc(cbBuffer, 0);
if (pbBuffer)
break;
}
}
else
{
cbBuffer = cb;
if (!cb)
{
// this means we didn't understand the picture type; so just
// skip it without failing.
fRet = TRUE;
goto Cleanup;
};
hBits = GlobalAlloc(GMEM_FIXED, cb);
pbBuffer = (BYTE *) GlobalLock(hBits);
}
if (!pbBuffer)
{
goto Cleanup;
}
// Copy the data from RTF into our HGLOBAL
while ((cbRead = RTFReadOLEStream.lpstbl->Get(&RTFReadOLEStream,pbBuffer,cbBuffer)) > 0)
{
if (pstm && (hr = pstm->Write( pbBuffer, cbRead, NULL)))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: Write", GetScode(hr));
goto Cleanup;
}
}
if (hBits)
{
Assert(!precall);
GlobalUnlock(hBits);
pbBuffer = NULL; // To avoid free below
}
if (pstm && (hr = pGetHGlobalFromStream(pstm, &hBits)))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: no hglobal from stm", GetScode(hr));
goto Cleanup;
}
// Build the picture
if( pfnBuildPict )
{
stgmedium.hGlobal = pfnBuildPict(_prtfObject, hBits);
}
else
{
// this means we didn't understand the picture type; so just
// skip it without failing.
fRet = TRUE;
goto Cleanup;
}
if( precall && !stgmedium.hGlobal )
goto Cleanup;
if( precall )
{
if( !_fNeedPres )
{
// Create the default handler
hr = pOleCreateDefaultHandler(reobj.clsid, NULL, IID_IOleObject,(void **) &reobj.poleobj);
if (FAILED(hr))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: no def handler", GetScode(hr));
goto Cleanup;
}
// Get the IPersistStorage and initialize it
if ((FAILED(hr = reobj.poleobj->QueryInterface(IID_IPersistStorage,(void **)&pperstg))) ||
(FAILED(hr = pperstg->InitNew(reobj.pstg))))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: InitNew", GetScode(hr));
goto Cleanup;
}
dwAdvf = ADVF_PRIMEFIRST;
}
else
{
Assert(_pobj);
_pobj->GetIUnknown()->QueryInterface(IID_IOleObject, (void **)&(reobj.poleobj));
dwAdvf = ADVF_NODATA;
formatetc.dwAspect = _fNeedIcon ? DVASPECT_ICON : DVASPECT_CONTENT;
}
// Get the IOleCache and put the picture data there
if (FAILED(hr = reobj.poleobj->QueryInterface(IID_IOleCache,(void **)&polecache)))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: QI: IOleCache", GetScode(hr));
goto Cleanup;
}
if (FAILED(hr = polecache->Cache(&formatetc, dwAdvf, &dwConn)))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: Cache", GetScode(hr));
goto Cleanup;
}
if (FAILED(hr = polecache->SetData(&formatetc, &stgmedium, TRUE)))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: SetData", GetScode(hr));
goto Cleanup;
}
}
if( !_fNeedPres )
{
// Create another object site for the new object
_ped->GetClientSite(&reobj.polesite) ;
if (!reobj.polesite )
{
goto Cleanup;
}
// Set the client site
if (reobj.poleobj && (hr = reobj.poleobj->SetClientSite(reobj.polesite)))
{
TRACEERRSZSC("ObFReadStaticFromEditstream: SetClientSite", GetScode(hr));
goto Cleanup;
}
else if (!reobj.poleobj)
{
// Windows CE static object Save the data and mark it.
COleObject *pobj = (COleObject *)reobj.polesite;
COleObject::ImageInfo *pimageinfo = new COleObject::ImageInfo;
pobj->SetHdata(hBits);
pimageinfo->xScale = _prtfObject->xScale;
pimageinfo->yScale = _prtfObject->yScale;
pimageinfo->xExtGoal = _prtfObject->xExtGoal;
pimageinfo->yExtGoal = _prtfObject->yExtGoal;
pimageinfo->cBytesPerLine = _prtfObject->cBytesPerLine;
pobj->SetImageInfo(pimageinfo);
}
// Put object into the edit control
reobj.cbStruct = sizeof(REOBJECT);
reobj.cp = _prg->GetCp();
reobj.dvaspect = DVASPECT_CONTENT;
reobj.dwFlags = REO_RESIZABLE;
// Since we are loading an object, it shouldn't be blank
reobj.dwFlags &= ~REO_BLANK;
_prg->Set_iCF(-1);
_prg->ReplaceRange(1, &ch, NULL, SELRR_IGNORE);
hr = ObjectMgr->InsertObject(reobj.cp, &reobj, NULL);
if (FAILED(hr))
{
goto Cleanup;
}
}
else
{
// the new presentation may have a different idea about how big the
// object is supposed to be. Make sure the object stays the correct
// size.
_pobj->ResetSizel(reobj.sizel);
}
fRet = TRUE;
Cleanup:
// V-GUYB:
// If we failed to stream in the object, then set the oom error here.
// Note, the above code can fail for other reasons, but oom is most
// likely. By setting the error here, the user will see the oom message
// and the stream in will be aborted.
if(!fRet)
{
_ped->GetCallMgr()->SetOutOfMemory();
_ecParseError = ecNoMemory;
}
if (polecache) polecache->Release() ;
if (reobj.pstg) reobj.pstg->Release();
if (reobj.polesite) reobj.polesite->Release();
if (reobj.poleobj) reobj.poleobj->Release();
if (pperstg) pperstg->Release();
if (pstm) pstm->Release();
FreePv(pbBuffer);
_fNeedIcon = FALSE;
_fNeedPres = FALSE;
_pobj = NULL;
return fRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -