📄 dxfrobj.cpp
字号:
if(IsZombie()) // Check for range zombie
return CO_E_RELEASED;
CLIPFORMAT cf = pformatetcIn->cfFormat;
HRESULT hr = DV_E_FORMATETC;
if( (cf == cf_EMBEDDEDOBJECT ||
cf == cf_EMBEDSOURCE) &&
(pformatetcIn->tymed & TYMED_ISTORAGE))
{
_pObjStg = GetDataForEmbeddedObject( _pOleObj, pmedium->pstg );
pmedium->tymed = TYMED_ISTORAGE;
hr = _pObjStg != NULL ? NOERROR : hr;
return hr;
}
if( cf == cf_OBJECTDESCRIPTOR &&
(pformatetcIn->tymed & TYMED_HGLOBAL) &&
_hObjDesc)
{
pmedium->hGlobal = DuplicateHGlobal(_hObjDesc);
pmedium->tymed = TYMED_HGLOBAL;
return NOERROR;
}
if( cf == CF_METAFILEPICT )
{
pmedium->hMetaFilePict = pOleDuplicateData(_hMFPict, CF_METAFILEPICT, 0);
pmedium->tymed = TYMED_MFPICT;
return NOERROR;
}
if( cf == CF_DIB )
{
if( _ped->HasObjects() && _cch == 1 )
{
COleObject *pobj = _ped->_pobjmgr->GetObjectFromCp(_cpMin);
if (pobj)
{
HGLOBAL hdib = pobj->GetHdata();
if (hdib)
{
pmedium->hGlobal = DuplicateHGlobal(hdib);
pmedium->tymed = TYMED_HGLOBAL;
}
}
}
return NOERROR;
}
// now handle 'native' richedit formats.
if( cf && pformatetcIn->tymed & TYMED_HGLOBAL )
{
if( cf == CF_UNICODETEXT )
pmedium->hGlobal = DuplicateHGlobal(TextToHglobal(_hPlainText, tPlain));
else if(cf == CF_TEXT)
pmedium->hGlobal = TextHGlobalWtoA(TextToHglobal(_hPlainText, tPlain));
else if(cf == cf_RTF || cf == cf_RTFASTEXT || cf == cf_RTFNOOBJS)
pmedium->hGlobal = DuplicateHGlobal(TextToHglobal(_hRtfText, tRtf));
else if(cf == cf_RTFUTF8)
pmedium->hGlobal = DuplicateHGlobal(TextToHglobal(_hRtfUtf8, tRtfUtf8));
else
return DV_E_FORMATETC;
hr = E_OUTOFMEMORY; // Default not enuf RAM
if( pmedium->hGlobal ) // Succeeded
{
pmedium->tymed = TYMED_HGLOBAL;
hr = NOERROR;
}
}
return hr;
}
/*
* CDataTransferObj::GetDataForEmbeddedObject (pformatetc, lpstgdest)
*
* @mfunc
* retrieves data for embedded object
*
* @rdesc
* LPSTORAGE
*
*/
LPSTORAGE CDataTransferObj::GetDataForEmbeddedObject(
LPOLEOBJECT pOleObj,
LPSTORAGE lpstgdest)
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::GetDataForEmbeddedObject");
HRESULT hr, hr1;
LPPERSISTSTORAGE pperstg;
if (_pObjStg != NULL && lpstgdest != NULL)
{
// We saved the data previously. Copy it to destination.
hr = _pObjStg->CopyTo(0, NULL, NULL, lpstgdest);
if (hr == NOERROR)
{
lpstgdest->Commit(STGC_DEFAULT);
return _pObjStg;
}
return NULL;
}
if (_pObjStg != NULL && lpstgdest == NULL)
{
// We saved the data previously. Return a reference
_pObjStg->AddRef();
return _pObjStg;
}
// We don't have a saved copy. Create One.
hr = pOleObj->QueryInterface( IID_IPersistStorage, (void **) &pperstg );
if (hr != NOERROR)
{
return NULL;
}
if (lpstgdest == NULL)
{
// It is null. We have to create our own.
LPLOCKBYTES lpLockBytes = NULL;
hr = pCreateILockBytesOnHGlobal(NULL, TRUE, // delete on release
(LPLOCKBYTES *)&lpLockBytes);
if (hr != NOERROR)
{
pperstg->Release();
return NULL;
}
hr = pStgCreateDocfileOnILockBytes(
lpLockBytes,
STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
0, // reserved
&lpstgdest
);
lpLockBytes->Release();
if (hr != NOERROR)
{
pperstg->Release();
return NULL;
}
_pObjStg = lpstgdest;
}
else
{
// Force the data to be saved
_pObjStg = GetDataForEmbeddedObject( _pOleObj, NULL );
pperstg->Release();
return GetDataForEmbeddedObject( _pOleObj, lpstgdest );
}
// OLE2NOTE: even if OleSave returns an error you should still call
// SaveCompleted.
hr = pOleSave( pperstg, lpstgdest, FALSE /* fSameAsLoad */ );
hr1 = pperstg->SaveCompleted(NULL);
if (hr != NOERROR || hr1 != NOERROR) // Should we use SUCCEED macros ????
{
lpstgdest = NULL;
}
pperstg->Release();
return _pObjStg;
}
/*
* CDataTransferObj::GetDataorObjectDescriptor (pformatetc, pmedium)
*
* @mfunc
* retrieves data for embedded object descriptor
*
* @rdesc
* HRESULT
*
*/
HGLOBAL CDataTransferObj::GetDataForObjectDescriptor(
LPOLEOBJECT pOleObj,
DWORD dwAspect
)
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::GetDataForObjectDescriptor");
POINTL ptl = {0};
SIZEL sizel = {0};
if (_hObjDesc == NULL)
{
_hObjDesc = OleGetObjectDescriptorDataFromOleObject(
pOleObj,
dwAspect,
ptl,
&sizel
);
}
return _hObjDesc;
}
/*
* CDataTransferObj::GetDataHere (pformatetc, pmedium)
*
* @mfunc
* retrieves data of the specified format into the given medium
*
* @rdesc
* HRESULT = E_NOTIMPL
*
* @devnote (alexgo): technically, we're supposed to support transfers
* into hglobals, but I'd rather not at the moment.
*/
STDMETHODIMP CDataTransferObj::GetDataHere(
FORMATETC *pformatetc,
STGMEDIUM *pmedium)
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::GetDataHere");
CLIPFORMAT cf = pformatetc->cfFormat;
HRESULT hr = DV_E_FORMATETC;
if(IsZombie()) // Check for range zombie
return CO_E_RELEASED;
if( (cf == cf_EMBEDDEDOBJECT ||
cf == cf_EMBEDSOURCE) &&
(pformatetc->tymed & TYMED_ISTORAGE))
{
// For some reason the NT4.0 and Win95 Shell
// ask for the EMBEDSOURCE format.
_pObjStg = GetDataForEmbeddedObject( _pOleObj, pmedium->pstg );
pmedium->tymed = TYMED_ISTORAGE;
hr = pmedium->pstg != NULL ? NOERROR : hr;
return hr;
}
if( cf == cf_OBJECTDESCRIPTOR &&
(pformatetc->tymed & TYMED_HGLOBAL) &&
_hObjDesc)
{
pmedium->hGlobal = DuplicateHGlobal(_hObjDesc);
pmedium->tymed = TYMED_HGLOBAL;
return NOERROR;
}
return E_NOTIMPL;
}
/*
* CDataTransferObj::QueryGetData (pformatetc)
*
* @mfunc
* Queries whether the given format is available in this data object
*
* @rdesc
* HRESULT
*/
STDMETHODIMP CDataTransferObj::QueryGetData(
FORMATETC *pformatetc ) // @parm FETC to look for
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::QueryGetData");
if(IsZombie()) // Check for range zombie
return CO_E_RELEASED;
DWORD cFETC = _cTotal;
while (cFETC--) // Maybe faster to search from start
{
if( pformatetc->cfFormat == _prgFormats[cFETC].cfFormat &&
(pformatetc->tymed & _prgFormats[cFETC].tymed) )
{
return NOERROR;
}
}
return DV_E_FORMATETC;
}
/*
* CDataTransferObj::SetData (pformatetc, pmedium, fRelease)
*
* @mfunc
* allows data to be set into this data object
*
* @rdesc
* HRESULT = E_FAIL
*
* @devnote
* as we are a data transfer object with a "snapshot" of data,
* we do not allow it to be replaced
*/
STDMETHODIMP CDataTransferObj::SetData(
FORMATETC *pformatetc,
STGMEDIUM *pmedium,
BOOL fRelease)
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::SetData");
return E_FAIL;
}
/*
* CDataTransferObj::OnPreReplaceRange
*
* @mfunc implementation of ITxNotify::OnPreReplaceRange
* called before changes are made to the backing store
*
* @rdesc void
*/
void CDataTransferObj::OnPreReplaceRange(
DWORD cp, //@parm cp of the changes
DWORD cchDel, //@parm #of chars deleted
DWORD cchNew, //@parm # of chars added
DWORD cpFormatMin, //@parm min cp of formatting changes
DWORD cpFormatMax) //@parm max cp of formatting changes
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::OnPreReplaceRange");
if (CONVERT_TO_PLAIN != cp && INFINITE != cp)
{
if ((LONG) cp > _cpMin + _cch)
{
// Change beyond our extent
return;
}
if ((LONG) (cp + cchDel) < _cpMin)
{
// Change before our extent
_cpMin += (cchNew - cchDel);
return;
}
}
// FUTURE (murrays): save only one master format (UTF8 RTF or better
// CTxtStory) and generate individual ones in GetData and GetDataHere.
_hPlainText = TextToHglobal(_hPlainText, tPlain);
_hRtfText = TextToHglobal(_hRtfText, tRtf);
_hRtfUtf8 = TextToHglobal(_hRtfUtf8, tRtfUtf8);
}
/*
* CDataTransferObj::OnPostReplaceRange
*
* @mfunc implementation of ITxNotify::OnPostReplaceRange
* called after changes are made to the backing store
*
* @rdesc void
*
* @comm we use this method to keep our cp's up-to-date
*/
void CDataTransferObj::OnPostReplaceRange(
DWORD cp, //@parm cp of the changes
DWORD cchDel, //@parm #of chars deleted
DWORD cchNew, //@parm # of chars added
DWORD cpFormatMin, //@parm min cp of formatting changes
DWORD cpFormatMax) //@parm max cp of formatting changes
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::OnPostReplaceRange");
// Nothing to do
return;
}
/*
* CDataTransferObj::Zombie ()
*
* @mfunc
* Turn this object into a zombie
*/
void CDataTransferObj::Zombie ()
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CDataTransferObj::Zombie");
_ped = NULL;
}
/*
* CDataTransferObj::Create(ped)
*
* @mfunc
* static function to create CDataTransferObj. Used to force users
* not to create this object on the stack, which would break OLE's
* liveness rules.
*
* @rdesc
* new CDataTransferObj *
*/
CDataTransferObj *CDataTransferObj::Create(
CTxtEdit *ped, // @parm ped to which this DataObject belongs
CTxtRange *prg, // @parm range for the data object
LONG lStreamFormat) // @parm stream format to use in Rtf conversion
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CDataTransferObj::Create");
Assert(CFETC == ARRAY_SIZE(g_rgFETC) && CFETC == ARRAY_SIZE(g_rgDOI));
LONG ch;
CNotifyMgr *pnm;
CDataTransferObj *pdo = new CDataTransferObj(ped);
if( !pdo )
{
ped->GetCallMgr()->SetOutOfMemory();
return NULL;
}
pdo->_hPlainText = NULL;
pdo->_hRtfText = NULL;
pdo->_hRtfUtf8 = NULL;
pdo->_pOleObj = NULL;
pdo->_hObjDesc = NULL;
pdo->_pObjStg = NULL;
pdo->_hMFPict = NULL;
pdo->_cch = abs(prg->GetCch());
pdo->_cpMin = prg->GetCpMin();
pdo->_lStreamFormat = lStreamFormat;
pnm = ped->GetNotifyMgr();
if( pnm )
{
pnm->Add( (ITxNotify *) pdo );
}
//Set the object count.
pdo->_cObjs = 0;
if( ped->HasObjects() )
{
pdo->_cObjs = ped->_pobjmgr->CountObjectsInRange(prg->GetCpMin(),
prg->GetCpMost());
}
pdo->_cTotal = ped->IsRich() ? 6 : 2;
pdo->_prgFormats = new FORMATETC[pdo->_cTotal];
if( !pdo->_prgFormats )
{
pdo->_cTotal = 0;
pdo->Release();
ped->GetCallMgr()->SetOutOfMemory();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -