📄 object.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
* @doc INTERNAL
*
* @module object.cpp IRichEditOle implementation |
*
* Author: alexgo 8/15/95
*/
#include "_common.h"
#include "_edit.h"
#include "_objmgr.h"
#include "_coleobj.h"
#include "_rtext.h"
#include "_select.h"
#include "_m_undo.h"
// IUnknown is implemented elsewhere
/*
* CTxtEdit::GetClientSite
*
* @mfunc returns the client site
*/
STDMETHODIMP CTxtEdit::GetClientSite(
LPOLECLIENTSITE FAR * lplpolesite) //@parm where to return
//the client site
{
COleObject *pobj;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetClientSite");
if( !lplpolesite )
{
return E_INVALIDARG;
}
pobj = new COleObject(this);
// should start with a ref count of 1.
if( pobj )
{
*lplpolesite = (IOleClientSite *)pobj;
return NOERROR;
}
return E_OUTOFMEMORY;
}
/*
* CTxtEdit::GetObjectCount
*
* @mfunc return the number of objects in this edit instance
*/
STDMETHODIMP_(LONG) CTxtEdit::GetObjectCount()
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetObjectCount");
return _pobjmgr ? _pobjmgr->GetObjectCount() : 0;
}
/*
* CTxtEdit::GetLinkCount
*
* @mfunc return the number of likns in this edit instance
*/
STDMETHODIMP_(LONG) CTxtEdit::GetLinkCount()
{
CObjectMgr *pobjmgr;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetLinkCount");
pobjmgr = GetObjectMgr();
if( pobjmgr )
{
return pobjmgr->GetLinkCount();
}
else
{
return 0;
}
}
/*
* CTxtEdit::GetObject
*
* @mfunc returns an object structure for the indicated object
*/
STDMETHODIMP CTxtEdit::GetObject(
LONG iob, //@parm index of the object
REOBJECT * preobj, //@parm where to put object info
DWORD dwFlags) //@parm flags
{
COleObject *pobj = NULL;
CObjectMgr *pobjmgr;
CTxtSelection *psel;
CCallMgr callmgr(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetObject");
if( !preobj || preobj->cbStruct != sizeof(REOBJECT) )
{
return E_INVALIDARG;
}
pobjmgr = GetObjectMgr();
if( !pobjmgr )
{
return E_OUTOFMEMORY;
}
//
// there are three cases of intestest; get the object at
// an index, at a given cp, or at the selection.
//
if( iob == REO_IOB_USE_CP )
{
pobj = pobjmgr->GetObjectFromCp(preobj->cp);
}
else if( iob == REO_IOB_SELECTION )
{
// use the selection cp
psel = GetSel();
if( psel )
{
pobj = pobjmgr->GetObjectFromCp(psel->GetCpMin());
}
}
else
{
pobj = pobjmgr->GetObjectFromIndex(iob);
}
if( pobj )
{
return pobj->GetObjectData(preobj, dwFlags);
}
//
// This return code is a bit of stretch, but basially
return E_INVALIDARG;
}
/*
* CTxtEdit::InsertObject
*
* @mfunc inserts a new object
*/
STDMETHODIMP CTxtEdit::InsertObject(
REOBJECT * preobj) //@parm object info
{
CTxtSelection *psel;
CObjectMgr *pobjmgr;
COleObject *pobj = NULL;
DWORD cp;
CCallMgr callmgr(this);
CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT);
CRchTxtPtr rtp(this, 0);
WCHAR ch = WCH_EMBEDDING;
HRESULT hr;
CNotifyMgr * pnm; // For notifying of changes
LONG iFormat = -1;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::InsertObject");
// do some boundary case checking
if( !preobj )
{
return E_INVALIDARG;
}
psel = GetSel();
if( !psel )
{
return E_OUTOFMEMORY;
}
// if the insertion of this character would cause
// us to exceed the text limit, fail
if( GetAdjustedTextLength() + 1 > TxGetMaxLength() )
{
// if we're not replacing a selection (or the
// selection is degenerate, then we will have exceeded
// our limit
if( preobj->cp != REO_CP_SELECTION || psel->GetCch() == 0)
{
GetCallMgr()->SetMaxText();
return E_OUTOFMEMORY;
}
}
pobjmgr = GetObjectMgr();
if( pobjmgr )
{
LONG selectRange = 0;
undobldr.StopGroupTyping();
DWORD cpFormat;
if( preobj->cp == REO_CP_SELECTION )
{
LONG a, b;
selectRange = psel->GetRange(a, b);
cp = psel->GetCpMin();
// Get the cp of the active end of the selection from which we
// will obtain the CF for the object.
cpFormat = psel->GetCch() > 0 ? psel->GetCpMost() : cp;
HandleSelectionAEInfo(this, &undobldr, psel->GetCp(), psel->GetCch(),
cp + 1, 0, SELAE_FORCEREPLACE);
}
else
{
cpFormat = cp = preobj->cp;
}
// Get the format for the ReplaceRange: for cp semantics, use format
// at the cp; for selection semantics, use the format at the active
// end of the selection.
CTxtRange rgFormat(this, cpFormat, 0);
iFormat = rgFormat.Get_iCF();
rtp.SetCp(cp);
rtp.ReplaceRange(selectRange, 1, &ch, &undobldr, iFormat);
//Don't want object selected.
psel->SetSelection(cp+1, cp+1);
hr = pobjmgr->InsertObject(cp, preobj, &undobldr);
pobj = (COleObject *)(preobj->polesite);
pobj->EnableGuardPosRect();
if (pnm = GetNotifyMgr()) // Get the notification mgr
{
pnm->NotifyPostReplaceRange(NULL, // Notify interested parties
INFINITE, 0, 0, cp, cp + 1); // of the change.
}
pobj->DisableGuardPosRect();
ReleaseFormats(iFormat, -1);
TxUpdateWindow();
return hr;
}
return E_OUTOFMEMORY;
}
/*
* CTxtEdit::ConvertObject
*
* @mfunc Converts the specified object to the specified class. Does reload
* the object but does NOT force an update (caller must do this).
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::ConvertObject(
LONG iob, //@parm index of the object
REFCLSID rclsidNew, //@parm the destination clsid
LPCSTR lpstrUserTypeNew) //@parm the new user type name
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ConvertObject");
CCallMgr callmgr(this);
COleObject * pobj = NULL;
HRESULT hr;
pobj = ObjectFromIOB(iob);
// If iob was invalid return
if (!pobj)
{
return E_INVALIDARG;
}
//Delegate to the object.
hr = pobj->Convert(rclsidNew, lpstrUserTypeNew);
return hr;
}
/*
* CTxtEdit::ActivateAs
*
* @mfunc Handles a request by the user to activate all objects of a particular
* class as objects of another class.
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::ActivateAs(
REFCLSID rclsid, //@parm clsid which we're going to change
REFCLSID rclsidAs) //@parm clsid to activate as
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ActivateAs");
CCallMgr callmgr(this);
CObjectMgr * pobjmgr = NULL;
pobjmgr = GetObjectMgr();
if( !pobjmgr )
{
return E_OUTOFMEMORY;
}
return pobjmgr->ActivateObjectsAs(rclsid, rclsidAs);
}
/*
* CTxtEdit::SetHostNames
*
* @mfunc Sets the host names for this instance
*/
STDMETHODIMP CTxtEdit::SetHostNames(
LPCSTR lpstrContainerApp, //@parm App name
LPCSTR lpstrContainerDoc) //@parm Container Object (doc) name
{
CObjectMgr *pobjmgr;
CCallMgr callmgr(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetHostNames");
WCHAR *pwsContainerApp = W32->ConvertToWideChar( lpstrContainerApp );
WCHAR *pwsContainerDoc = W32->ConvertToWideChar( lpstrContainerDoc );
pobjmgr = GetObjectMgr();
if( pobjmgr && pwsContainerApp && pwsContainerDoc)
{
HRESULT hr = pobjmgr->SetHostNames(pwsContainerApp, pwsContainerDoc);
delete pwsContainerApp;
delete pwsContainerDoc;
return hr;
}
return E_OUTOFMEMORY;
}
/*
* CTxtEdit::SetLinkAvailable
*
* @mfunc
* Allows client to tell us whether the link is available or not.
*/
STDMETHODIMP CTxtEdit::SetLinkAvailable(
LONG iob, //@parm index of the object
BOOL fAvailable) //@parm if TRUE, make object linkable
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetLinkAvailable");
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj)
{
return E_INVALIDARG;
}
// Delegate this to the object.
return pobj->SetLinkAvailable(fAvailable);
}
/*
* CTxtEdit::SetDvaspect
*
* @mfunc Allows client to tell us which aspect to use and force us
* to recompute positioning and redraw.
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::SetDvaspect(
LONG iob, //@parm index of the object
DWORD dvaspect) //@parm the aspect to use
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetDvaspect");
CCallMgr callmgr(this);
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj)
{
return E_INVALIDARG;
}
// Delegate this to the object.
pobj->SetDvaspect(dvaspect);
return NOERROR;
}
/*
* CTxtEdit::HandsOffStorage
*
* @mfunc see IPersistStorage::HandsOffStorage
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::HandsOffStorage(
LONG iob) //@parm index of the object
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::HandsOffStorage");
CCallMgr callmgr(this);
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj)
{
return E_INVALIDARG;
}
// Delegate this to the object.
pobj->HandsOffStorage();
return NOERROR;
}
/*
* CTxtEdit::SaveCompleted
*
* @mfunc see IPersistStorage::SaveCompleted
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::SaveCompleted(
LONG iob, //@parm index of the object
LPSTORAGE lpstg) //@parm new storage
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SaveCompleted");
CCallMgr callmgr(this);
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj)
{
return E_INVALIDARG;
}
// Delegate this to the object.
pobj->SaveCompleted(lpstg);
return NOERROR;
}
/*
* CTxtEdit::InPlaceDeactivate
*
* @mfunc Deactivate
*/
STDMETHODIMP CTxtEdit::InPlaceDeactivate()
{
COleObject *pobj;
CObjectMgr *pobjmgr;
HRESULT hr = NOERROR;
CCallMgr callmgr(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::InPlaceDeactivate");
pobjmgr = GetObjectMgr();
if( pobjmgr )
{
pobj = pobjmgr->GetInPlaceActiveObject();
if( pobj )
{
hr = pobj->DeActivateObj();
}
}
return hr;
}
/*
* CTxtEdit::ContextSensitiveHelp
*
* @mfunc enter/leave ContextSensitiveHelp mode
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::ContextSensitiveHelp(
BOOL fEnterMode) //@parm enter/exit mode
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ContextSensitiveHelp");
COleObject * pobj = NULL;
CObjectMgr * pobjmgr = NULL;
HRESULT hr = NOERROR;
IOleWindow * pow;
CCallMgr callmgr(this);
pobjmgr = GetObjectMgr();
if( !pobjmgr )
{
return E_OUTOFMEMORY;
}
// if the mode changes
if( pobjmgr->GetHelpMode() != fEnterMode )
{
pobjmgr->SetHelpMode(fEnterMode);
pobj = pobjmgr->GetInPlaceActiveObject();
if (pobj)
{
hr = pobj->GetIUnknown()->QueryInterface(IID_IOleWindow,
(void **)&pow);
if( hr == NOERROR )
{
hr = pow->ContextSensitiveHelp(fEnterMode);
pow->Release();
}
}
}
return hr;
}
/*
* CTxtEdit::GetClipboardData
*
* @mfunc return an data transfer object for the indicated
* range
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::GetClipboardData(
CHARRANGE *lpchrg, //@parm the range of text to use
DWORD reco, //@parm operation the data is for
LPDATAOBJECT *lplpdataobj) //@parm where to put the data object
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetClipboardData");
CCallMgr callmgr(this);
HRESULT hr;
LONG cpMin, cpMost;
CLightDTEngine * pldte = GetDTE();
//Make sure cpMin and cpMost are within the current text limits.
//Interpret neg. value for cpMin as the beginning of the text,
//and neg. value for cpMax as the end of the text. If a char range
//is not given use the current selection.
if(lpchrg)
{
LONG cchText;
cchText = (LONG)GetTextLength();
cpMin = max(0, lpchrg->cpMin);
cpMin = min(cchText, lpchrg->cpMin);
cpMost = lpchrg->cpMost;
if(lpchrg->cpMost < 0 || lpchrg->cpMost > cchText)
cpMost = cchText;
}
else
{
CTxtSelection * psel = GetSel();
if(!psel)
{
return E_OUTOFMEMORY;
}
psel->GetRange(cpMin, cpMost);
}
//Make sure this is a valid range.
if(cpMin >= cpMost)
{
*lplpdataobj = NULL;
return cpMin == cpMost
? NOERROR
: ResultFromScode(E_INVALIDARG);
}
CTxtRange rg(this, cpMin, cpMin-cpMost);
//We don't use reco for anything.
hr = pldte->RangeToDataObject(&rg, SF_RTF, lplpdataobj);
#ifdef DEBUG
if(hr != NOERROR)
TRACEERRSZSC("GetClipboardData", E_OUTOFMEMORY);
#endif
return hr;
}
/*
* CTxtEdit::ImportDataObject
*
* @mfunc morally equivalent to paste, but with a data object
*
* @rdesc
* HRESULT Success code.
*/
STDMETHODIMP CTxtEdit::ImportDataObject(
LPDATAOBJECT lpdataobj, //@parm the data object to use
CLIPFORMAT cf, //@parm the clibpoard format to use
HGLOBAL hMetaPict) //@parm the metafile to use
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ImportDataObject");
CCallMgr callmgr(this);
CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT);
REPASTESPECIAL rps;
rps.dwAspect = DVASPECT_CONTENT;
rps.dwParam = NULL;
if (hMetaPict)
{
rps.dwAspect = DVASPECT_ICON;
rps.dwParam = (DWORD) (LPVOID) hMetaPict;
}
return PasteDataObjectToRange(lpdataobj, GetSel(), cf,
&rps, &undobldr, PDOR_NOQUERY);
}
/*
* CTxtEdit::ObjectFromIOB
*
* @mfunc Gets an object based on an IOB type index.
*
* @rdesc:
* pointer to COleObject or NULL if none.
*/
COleObject * CTxtEdit::ObjectFromIOB(LONG iob)
{
COleObject * pobj = NULL;
CObjectMgr * pobjmgr = NULL;
pobjmgr = GetObjectMgr();
if (!pobjmgr)
{
return NULL;
}
// Figure out the index of the selection
if (iob == REO_IOB_SELECTION)
{
CTxtSelection * psel = GetSel();
if(!psel)
{
return NULL;
}
pobj = pobjmgr->GetFirstObjectInRange(psel->GetCpMin(),
psel->GetCpMost());
}
else
{
// Make sure the IOB is in range
if ((0 <= iob) && (iob < GetObjectCount()))
{
pobj = pobjmgr->GetObjectFromIndex(iob);
}
}
return pobj;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -