objmgr.cpp
来自「Windows CE 6.0 Word Application 源码」· C++ 代码 · 共 1,028 行 · 第 1/2 页
CPP
1,028 行
{
DWORD i, count;
COleObject *pobj;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::~CObjectMgr");
count = _objarray.Count();
for( i = 0; i < count; i++ )
{
pobj = *_objarray.Elem(i);
// we NULL stuff here to try to protect ourselves
// better in re-entrancy cases.
*_objarray.Elem(i) = NULL;
if( pobj )
{
pobj->Close(OLECLOSE_NOSAVE);
pobj->MakeZombie();
SafeReleaseAndNULL((IUnknown**)&pobj);
}
}
if( _precall )
{
SafeReleaseAndNULL((IUnknown**)&_precall);
}
if( _pszApp )
{
delete _pszApp;
}
if( _pszDoc )
{
delete _pszDoc;
}
}
/*
* CObjectMgr::ReplaceRange
*
* @mfunc handles the deletion of objects from a given range. This
* method _must_ be called before any floating range notifications
* are sent.
*
* @rdesc void
*/
void CObjectMgr::ReplaceRange(
DWORD cp, //@parm the cp starting the deletion
DWORD cchDel, //@parm the number of characters deleted
IUndoBuilder *publdr) //@parm the undo builder for this actions
{
DWORD i;
DWORD iDel = (DWORD)-1,
cDel = 0; // index at which to delete && number of objects
// to delete.
COleObject *pobj;
// nothing deleted, don't bother doing anything.
if( !cchDel )
{
return;
}
// basically, we loop through all of the objects within the
// range of deleted text and ask them to delete themselves.
// We remember the range of objects deleted (the starting index
// and # of objects deleted) so that we can remove them from
// the array all at once.
i = FindIndexForCp(cp);
while( i < _objarray.Count() )
{
pobj = *_objarray.Elem(i);
if( pobj && pobj->GetCp() >= cp)
{
if( pobj->GetCp() < (cp + cchDel) )
{
if( _pobjactive == pobj )
{
// Deactivate the object just to be on the safe side.
_pobjactive->DeActivateObj();
_pobjactive = NULL;
}
if( iDel == (DWORD)-1 )
{
iDel = i;
}
cDel++;
if (_precall)
{
IOleObject *poo;
if (pobj->GetIUnknown()->QueryInterface(IID_IOleObject,
(void **)&poo) == NOERROR)
{
_precall->DeleteObject(poo);
poo->Release();
}
}
// if the object was selected, then it obviously
// can't be anymore!
if( _pobjselect == pobj )
{
_pobjselect = NULL;
}
pobj->Delete(publdr);
*_objarray.Elem(i) = NULL;
pobj->Release();
}
else
{
break;
}
}
i++;
}
if( cDel )
{
_objarray.Remove(iDel, cDel, AF_DELETEMEM);
}
return;
}
/*
* CObjectMgr::ScrollObjects
*
* @mfunc informs all objects that scrolling has occured so they can
* update if necessary
*
* @rdesc void
*/
void CObjectMgr::ScrollObjects(
LONG dx, //@parm change in the x direction
LONG dy, //@parm change in the y direction
LPCRECT prcScroll) //@parm the rect that is being scrolled
{
DWORD i, count;
COleObject *pobj;
count = _objarray.Count();
for( i = 0; i < count; i++ )
{
pobj = *_objarray.Elem(i);
if( pobj )
{
pobj->ScrollObject(dx, dy, prcScroll);
}
}
}
//
// PRIVATE methods
//
/*
* CObjectMgr::FindIndexForCp
*
* @mfunc does a binary search to find the index at which an object
* at the given cp exists or should be inserted.
*
* @rdesc DWORD, an index
*/
DWORD CObjectMgr::FindIndexForCp(DWORD cp)
{
LONG l, r;
COleObject *pobj = NULL;
DWORD i = 0;
l = 0;
r = _objarray.Count() - 1;
while( r >= l )
{
i = (l + r)/2;
pobj = *_objarray.Elem(i);
if( !pobj )
{
TRACEWARNSZ("null entry in object table. Recovering...");
for( i = 0 ; i < _objarray.Count() -1; i++ )
{
pobj = *_objarray.Elem(i);
if( pobj && pobj->GetCp() >= cp )
{
return i;
}
}
return i;
}
if( pobj->GetCp() == cp )
{
return i;
}
else if( pobj->GetCp() < cp )
{
l = i + 1;
}
else
{
r = i - 1;
}
}
// yikes! nothing was found. Fixup i so that
// it points to the correct index for insertion.
Assert(pobj || (!pobj && i == 0));
if( pobj )
{
Assert(pobj->GetCp() != cp);
if( pobj->GetCp() < cp )
{
i++;
}
}
return i;
}
/*
* CObjectMgr::HandleDoubleClick
*
* @mfunc Handles a double click message, potentially activating
* an object.
*
* @rdesc BOOL-- TRUE if double click-processing is completely
* finished.
*/
BOOL CObjectMgr::HandleDoubleClick(
CTxtEdit *ped, //@parm edit context
const POINT &pt,//@parm the point of the click (WM_LBUTTONDBLCLK wparam)
DWORD flags) //@parm flags (lparam)
{
DWORD cp;
COleObject *pobj;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN,
"CObjectMgr::HandleDoubleClick");
cp = ped->_pdp->CpFromPoint(pt, NULL, NULL, NULL, FALSE);
pobj = FindObjectAtPointNearCp(pt, cp);
if (!pobj)
{
return FALSE;
}
if (_pobjactive != pobj)
{
//Deactivate currently active object if any.
if (_pobjactive)
{
_pobjactive->DeActivateObj();
}
return pobj->ActivateObj(WM_LBUTTONDBLCLK, MAKELONG(pt.x, pt.y),
flags);
}
return TRUE;
}
/*
* CObjectMgr::HandleClick
*
* @mfunc
* The position of the caret is changing. We need to
* Deactivate the active object, if any. If the change is
* because of a mouse click and there is an object at this
* cp, we set a new individually selected object. Otherwise
* we set the individually selected object to NULL.
*
* @rdesc returns TRUE if this method set the selection. Otherwise,
* returns FALSE;
*/
ClickStatus CObjectMgr::HandleClick(
CTxtEdit *ped, //@parm the edit context
const POINT &pt)//@parm the point of the mouse click
{
COleObject * pobjnew;//, * pobjold;
CTxtSelection * psel;
DWORD cp;
LONG cpMin, cpMost;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::HandleClick");
if( _pobjactive )
{
_pobjactive->DeActivateObj();
return CLICK_OBJDEACTIVATED;
}
cp = ped->_pdp->CpFromPoint(pt, NULL, NULL, NULL, FALSE);
pobjnew = FindObjectAtPointNearCp(pt, cp);
//If we clicked on an object, set the selection to this object.
//CTxtSelection::UpdateSelection will be called as a result of this
//and will determine the highlighting.
if( pobjnew )
{
cp = pobjnew->GetCp();
psel = ped->GetSel();
if (psel->GetRange(cpMin, cpMost) > 1 &&
cpMin <= (LONG) cp &&
(LONG) cp <= cpMost)
{
// There is more than one character in the selection
// And the object is part of the selection.
// Do not change the selection
return CLICK_SHOULDDRAG;
}
// don't reset the selection if the object is already selected
if( pobjnew != _pobjselect )
{
// Freeze the Display while we handle this click
CFreezeDisplay fd(ped->_pdp);
psel->SetSelection(cp, cp+1);
if (GetSingleSelect())
{
// Note thate the call to SetSelection may have set selected object to NULL !!!!
// This can happen in some strange scenarios where our state is out of whack
AssertSz(GetSingleSelect() == pobjnew, "Object NOT Selected!!");
return CLICK_OBJSELECTED;
}
return CLICK_IGNORED;
}
return CLICK_OBJSELECTED;
}
return CLICK_IGNORED;
}
/*
* CObjectMgr::HandleSingleSelect
*
* @mfunc
* When an object is selected and it is the only thing selected, we do
* not highlight it by inverting it. We Draw a frame and handles around
* it. This function is called either because an object has been
* selected and it is the only thing selected, or because we need to
* check for an object that used to be in this state but may no longer be.
*
*/
void CObjectMgr::HandleSingleSelect(
CTxtEdit *ped, //@parm the edit context
DWORD cp, //@parm cp of object
BOOL fHiLite) //@parm is this a call for hding the selection
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::HandleSingleSelect");
COleObject* pobjnew;
pobjnew = GetObjectFromCp(cp);
//This should only be called when we know we have a singley selected
//object. However, there are boundary cases (such as inserting an object)
//where WCH_EMBEDDING is the backing store yet no object exists. These
//cases are OK; thus, we check for NULL on pobjnew.
if (pobjnew)
{
//The object is the same as the currently selected object (if any)
//we are deselecting it. This works like a toggle unless state is messed up.
//If the object is different, we are replacing the current selected
//object (if any).
if (!fHiLite && _pobjselect)
{
// This covers _pobjselct == pobjnew Normal case
// and _pobjselect != pobjnew Degenerate case.
_pobjselect->SetREOSELECTED(FALSE);
_pobjselect = NULL;
//Remove frame/handles from currently selected object.
ped->_pdp->OnPostReplaceRange(INFINITE, 0, 0, cp, cp + 1);
}
else if (fHiLite && pobjnew != _pobjselect)
{
// Only do this if we are setting a new selection.
_pobjselect = pobjnew;
_pobjselect->SetREOSELECTED(TRUE);
//Draw frame/handles on newly selected object.
ped->_pdp->OnPostReplaceRange(INFINITE, 0, 0, cp, cp + 1);
}
else
{
// We want to hilite the selection but the object is already selected.
// Or we want to undo hilite on the selection but the selected object is NULL.
// Do nothing.
}
}
return;
}
/*
* CObjectMgr::FindObjectAtPointNearCp
*
* @mfunc if an object exists at the given point, return
* it. <p cp> is used to help narrow the search
* of which objects to look for.
*
* @rdesc the object, if found. NULL otherwise
*/
COleObject *CObjectMgr::FindObjectAtPointNearCp(
const POINT &pt,//@parm the point in question
DWORD cp) //@parm hinting cp
{
LONG i, stop;
COleObject *pobj;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN,
"CObjectMgr::FindObjectAtPointNearCp");
// the cp tells us roughly where the object should be in the
// stream; however, it may be one to the left or one to the right.
i = FindIndexForCp(cp);
stop = i + 1;
i--;
for( ; i <= stop ; i++ )
{
if( i >= 0 && i < (LONG)_objarray.Count() )
{
pobj = *_objarray.Elem(i);
if( pobj && PtInRect(pobj->GetPosRect(), pt) &&
(pobj->GetCp() == cp || pobj->GetCp() == cp - 1) )
{
return pobj;
}
}
}
return NULL;
}
/*
* CObjectMgr::ActivateObjectsAs
*
* @mfunc Handles a request by the user to activate all objects of a particular
* class as objects of another class.
*
* @rdesc
* HRESULT Success code.
*/
HRESULT CObjectMgr::ActivateObjectsAs(REFCLSID rclsid, REFCLSID rclsidAs)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CObjectMgr::ActivateObjectsAs");
COleObject * pobj;
DWORD cobj, iobj;
HRESULT hr, hrLatest;
// Tell the system to treat all rclsid objects as rclsidAs
hr = pCoTreatAsClass(rclsid, rclsidAs);
if( hr != NOERROR )
{
return hr;
}
cobj = GetObjectCount();
//Go through the objects, letting them decide if
//they have anything to do for this.
for (iobj = 0; iobj < cobj; iobj++)
{
pobj = GetObjectFromIndex(iobj);
hrLatest = pobj->ActivateAs(rclsid, rclsidAs);
//Make hr the latest hresult unless we have previously
//had an error.
if( hr == NOERROR )
{
hr = hrLatest;
}
}
return hr;
}
#ifdef DEBUG
void CObjectMgr::DbgDump(void)
{
Tracef(TRCSEVNONE, "Object Manager %d objects", _objarray.Count());
for( DWORD i = 0 ; i < _objarray.Count(); i++ )
{
COleObject *pobj = *_objarray.Elem(i);
if( pobj )
{
pobj->DbgDump( i );
}
}
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?