📄 ldte.cpp
字号:
hGlobal = DuplicateHGlobal(hGlobal);
if (hGlobal) {
hresult = DIBToRange(hGlobal, prg, publdr);
} else {
hresult = E_OUTOFMEMORY;
}
}
}
_ped->_pdp->Thaw();
::CloseClipboard();
}
if (FAILED(hresult)) {
_ped->Sound();
}
return hresult;
}
}
}
// Paste an object uses the limit text calculation
_fUseLimit = TRUE;
if(cf == CF_TEXT)
{
FORMATETC fetc = {CF_UNICODETEXT, NULL, 0, -1, TYMED_NULL};
if(pdo->QueryGetData(&fetc) == S_OK)
cf = CF_UNICODETEXT;
}
//Call QueryAcceptData unless caller has specified otherwise
if (!(dwFlags & PDOR_NOQUERY) && precall)
{
CLIPFORMAT cfReq = cf;
HGLOBAL hmeta = NULL;
if (rps)
{
hmeta = (HGLOBAL)((rps->dwAspect == DVASPECT_ICON) ? rps->dwParam : NULL);
}
// Ask the callback if it likes the data object, and cfReq.
hresult = precall->QueryAcceptData(
pdo,
&cfReq,
(dwFlags & PDOR_DROP) ? RECO_DROP : RECO_PASTE,
TRUE,
hmeta);
if(hresult == DATA_S_SAMEFORMATETC)
{
// Allow callback to return DATA_S_SAMEFORMATETC if it only
// wants cf as passed in - we don't really care because
// any non-zero CLIPFORMAT causes us to only accept that format.
hresult = S_OK;
}
if(hresult == S_OK || hresult == E_NOTIMPL)
{
// Callback either liked it or didn't implement the method.
// It may have changed the format while it was at it.
// Treat a change of cf to zero as acceptance of the original.
// In any event, we will try to handle it.
// If a specific CLIPFORMAT was originally requested and the
// callback changed it, don't accept it.
if(cfReq && cf && (cf != cfReq))
{
hresult = DV_E_FORMATETC;
goto Exit;
}
// If a specific CLIPFORMAT was originally requested and the
// callback either left it alone or changed it to zero,
// make sure we use the original. If no CLIPFORMAT was
// originally requested, make sure we use what came back
// from the callback.
if(!cf)
{
cf = cfReq;
}
}
else
{
// Some success other than S_OK && DATA_S_SAMEFORMATETC.
// The callback has handled the paste. OR some error
// was returned.
goto Exit;
}
}
if (_ped->TxGetReadOnly()) // Should check for range protection
{
hresult = E_ACCESSDENIED;
goto Exit;
}
// At this point we freeze the display
fThawDisplay = TRUE;
_ped->_pdp->Freeze();
if( publdr )
{
publdr->StopGroupTyping();
publdr->SetNameID(UID_PASTE);
}
for( i = 0; i < CFETC; i++, pfetc++ )
{
// make sure the format is either 1.) a plain text format
// if we are in plain text mode or 2.) a rich text format
// or 3.) matches the requested format.
if( cf && cf != pfetc->cfFormat )
{
continue;
}
if( _ped->IsRich() || (g_rgDOI[i] & DOI_CANPASTEPLAIN) )
{
// make sure the format is available
if( pdo->QueryGetData(pfetc) != NOERROR )
{
continue;
}
//If we have a format that uses an hGlobal get and lock it
if(i == iRtfFETC || i == iRtfAsTextFETC || i == iAnsiFETC ||
i == iUnicodeFETC || i == iRtfNoObjs || i == iRtfUtf8)
{
if( pdo->GetData(pfetc, &medium) != NOERROR )
continue;
hGlobal = medium.hGlobal;
ptext = (LPTSTR)GlobalLock(hGlobal);
if( !ptext )
{
pReleaseStgMedium(&medium);
hresult = E_OUTOFMEMORY;
goto Exit;
}
// 1.0 COMPATBILITY HACK ALERT! RichEdit 1.0 has a bit of
// "error recovery" for parsing rtf files; if they aren't
// valid rtf, it treats them as just plain text.
// Unfortunately, apps like Exchange depend on this behavior,
// i.e., they give RichEdit plain text data, but call it rich
// text anyway. Accordingly, we emulate 1.0 behavior here by
// checking for an rtf signature.
if( (i == iRtfFETC || i == iRtfNoObjs || i == iRtfUtf8) &&
(GlobalSize(hGlobal) < cbRTFSig ||
memcmp(ptext, szRTFSig, cbRTFSig) != 0 ))
{
// uh-oh, data is not RTF, make it ANSI text
i = iAnsiFETC;
}
}
// Don't delete trail EOP in some cases
prg->AdjustEndEOP(NONEWCHARS);
switch(i)
{
case iRtfNoObjs:
case iRtfFETC:
case iRtfUtf8:
hresult = HGlobalToRange(i, hGlobal, ptext, prg, publdr, bDBCString);
break;
case iRtfAsTextFETC:
case iAnsiFETC: // ANSI plain text
hUnicode = TextHGlobalAtoW(hGlobal, &bDBCString);
ptext = (LPTSTR)GlobalLock(hUnicode);
if(!ptext)
{
hresult = E_OUTOFMEMORY; // Unless out of RAM,
break; // fall thru to
} // Unicode case
case iUnicodeFETC: // Unicode plain text
// Ok to pass in NULL for hglobal since argument won't be used
hresult = HGlobalToRange(i, NULL, ptext, prg, publdr, bDBCString);
if(hUnicode) // For iAnsiFETC case
{
GlobalUnlock(hUnicode);
GlobalFree(hUnicode);
}
break;
case iObtDesc: // Object Descriptor
*(volatile DWORD*)&dwTemp = 0; // Work around compiler bug (#14740)
continue; // to search for a good format.
// the object descriptor hints will be used
// when the format is found.
case iEmbObj: // Embedded Object
case iEmbSrc: // Embed Source
case iLnkSrc: // Link Source
case iMfPict: // Metafile
case iDIB: // DIB
case iBitmap: // Bitmap
case iFilename: // Filename
hresult = CreateOleObjFromDataObj(pdo, prg, rps, i, publdr);
break;
//COMPATIBILITY ISSUE (v-richa) iTxtObj is needed by Exchange and
//as a flag for Wordpad. iRichEdit doesn't seem to be needed by
//anyone but might consider implementing as a flag.
case iRichEdit: // RichEdit
case iTxtObj: // Text with Objects
break;
}
//If we used the hGlobal unlock it and free it.
if(hGlobal)
{
GlobalUnlock(hGlobal);
pReleaseStgMedium(&medium);
}
//Break out of the for loop
break;
}
}
Exit:
if (fThawDisplay)
{
_ped->_pdp->Thaw();
}
if(!pdoSave) // Release data object
pdo->Release(); // used for clipboard
return hresult;
}
/*
* CLightDTEngine::GetDropTarget (ppDropTarget)
*
* @mfunc
* creates an OLE drop target
*
* @rdesc
* HRESULT
*
* @devnote The caller is responsible for AddRef'ing this object
* if appropriate.
*/
HRESULT CLightDTEngine::GetDropTarget(
IDropTarget **ppDropTarget) // @parm outparm for drop target
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::GetDropTarget");
if( !_pdt )
{
_pdt = new CDropTarget(_ped);
// the AddRef done by the constructor will be
// undone by the destructor of this object
}
if( ppDropTarget )
{
*ppDropTarget = _pdt;
}
return _pdt ? NOERROR : E_OUTOFMEMORY;
}
/*
* CLightDTEngine::StartDrag (prg, publdr)
*
* @mfunc
* starts the main drag drop loop
*
*/
HRESULT CLightDTEngine::StartDrag(
CTxtSelection *psel, // @parm Selection to drag from
IUndoBuilder *publdr) // @parm undo builder to receive antievents
{
#ifndef PEGASUS
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::StartDrag");
LONG cch, cch1;
LONG cp1, cpMin, cpMost;
DWORD dwEffect = 0;
HRESULT hr;
IDataObject * pdo = NULL;
IDropSource * pds;
IRichEditOleCallback * precall = _ped->GetRECallback();
// If we're doing drag drop's, we should have our own drop target
// It's possible that _pdt will be NULL at this point--some clients
// will delay instantiation of our drop target until a drop target
// in the parent window decides that ours is needed. However, since
// we need it just to initiate drag drop, go ahead and create one
// here.
if( _pdt == NULL )
{
if( (hr = GetDropTarget(NULL)) != NOERROR )
{
return hr;
}
}
psel->CheckTableSelection();
if(precall)
{
CHARRANGE chrg;
// give the callback a chance to give us its own IDataObject
psel->GetRange(chrg.cpMin, chrg.cpMost);
hr = precall->GetClipboardData(&chrg, RECO_COPY, &pdo);
}
else
{
// we need to build our own data object.
hr = S_FALSE;
}
// If we didn't get an IDataObject from the callback, build our own
if(hr != NOERROR || pdo == NULL)
{ // Don't include trailing EOP
psel->AdjustEndEOP(NONEWCHARS); // in some selection cases
hr = RangeToDataObject(psel, SF_TEXT | SF_RTF, &pdo);
if(hr != NOERROR)
return hr;
}
cch = psel->GetRange(cpMin, cpMost); // NB: prg is the selection
cp1 = psel->GetCp(); // Save active end and signed
cch1 = psel->GetCch(); // length for Undo antievent
CTxtRange rg(_ped, cpMost, cch); // Use range copy to float over
// mods made to backing store
// The floating range that we just created on the stack needs to
// think that it's protected, so it won't change size.
rg.SetDragProtection(TRUE);
pds = new CDropSource();
if( pds == NULL )
{
pdo->Release();
return E_OUTOFMEMORY;
}
// cache some info with our own drop target
_pdt->SetDragInfo(publdr, cpMin, cpMost);
// Set allowable effects
dwEffect = DROPEFFECT_COPY;
if (!_ped->TxGetReadOnly())
dwEffect |= DROPEFFECT_MOVE;
// Let the client decide what it wants.
if (precall)
{
hr = precall->GetDragDropEffect(TRUE, 0, &dwEffect);
}
if (!FAILED(hr) || hr == E_NOTIMPL)
{
// start drag-drop operation
hr = pDoDragDrop(pdo, pds, dwEffect, &dwEffect);
}
// clear drop target
_pdt->SetDragInfo(NULL, -1, -1);
// handle 'move' operations
if( hr == DRAGDROP_S_DROP && (dwEffect & DROPEFFECT_MOVE) )
{
// we're going to delete the dragged range, so turn off protection.
rg.SetDragProtection(FALSE);
if( publdr )
{
LONG cpNext, cchNext;
if(_ped->GetCallMgr()->GetChangeEvent() )
{
cpNext = cchNext = -1;
}
else
{
cpNext = rg.GetCpMin();
cchNext = 0;
}
HandleSelectionAEInfo(_ped, publdr, cp1, cch1, cpNext, cchNext,
SELAE_FORCEREPLACE);
}
// delete the data that was moved. The selection will float
// to the new correct location.
rg.ReplaceRange(0, NULL, publdr, SELRR_IGNORE);
// The update that happens implicitly by the update of the range may
// have the effect of scrolling the window. This in turn may have the
// effect in the drag drop case of scrolling non-inverted text into
// the place where the selection was. The logic in the selection
// assumes that the selection is inverted and so reinverts it to turn
// off the selection. Of course, it is obvious what happens in the
// case where non-inverted text is scrolled into the selection area.
// To simplify the processing here, we just say the whole window is
// invalid so we are guaranteed to get the right painting for the
// selection.
// FUTURE: (ricksa) This solution does have the disadvantage of causing
// a flash during drag and drop. We probably want to come back and
// investigate a better way to update the screen.
_ped->TxInvalidateRect(NULL, FALSE);
// Display is updated via notification from the range
// Update the caret
psel->Update(TRUE);
}
else if( hr == DRAGDROP_S_DROP && _ped->GetCallMgr()->GetChangeEvent() &&
(dwEffect & DROPEFFECT_COPY) && publdr)
{
// if we copied to ourselves, we want to restore the selection to
// the original drag origin on undo
HandleSelectionAEInfo(_ped, publdr, cp1, cch1, -1, -1,
SELAE_FORCEREPLACE);
}
if( SUCCEEDED(hr) )
{
hr = NOERROR;
}
pdo->Release();
pds->Release();
// we do this last since we may have re-used some 'paste' code which
// will stomp the undo name to be UID_PASTE.
if( publdr )
{
publdr->SetNameID(UID_DRAGDROP);
}
if( (_ped->GetEventMask() & ENM_DRAGDROPDONE) )
{
NMHDR hdr;
ZeroMemory(&hdr, sizeof(NMHDR));
_ped->TxNotify(EN_DRAGDROPDONE, &hdr);
}
return hr;
#else
return 0;
#endif
}
/*
* CLightDTEngine::LoadFromEs (prg, lStreamFormat, pes, fTestLimit, publdr)
*
* @mfunc
* Load data from the stream pes into the range prg according to the
* format lStreamFormat
*
* @rdesc
* LONG -- count of characters read
*/
LONG CLightDTEngine::LoadFromEs(
CTxtRange * prg, // @parm range to load into
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -