📄 coleobj.cpp
字号:
SetExtent(SE_ACTIVATING);
}
HRESULT hr;
hr = poo->DoVerb(OLEIVERB_PRIMARY, &msg, (LPOLECLIENTSITE)this, 0, hwnd, &_rcPos);
#ifndef MACPORT
if (FAILED(hr))
{
ENOLEOPFAILED enoleopfailed;
enoleopfailed.iob = _ped->_pobjmgr->FindIndexForCp(GetCp());
enoleopfailed.lOper = OLEOP_DOVERB;
enoleopfailed.hr = hr;
_ped->TxNotify( EN_OLEOPFAILED, &enoleopfailed );
}
#endif
poo->Release();
}
else
{
return FALSE;
}
return TRUE;
}
/*
* COleObject::DeActivateObj
*
* @mfunc Deactivates the object.
*
*/
HRESULT COleObject::DeActivateObj(void)
{
IOleInPlaceObject * pipo;
IOleObject *poo;
MSG msg;
HRESULT hr;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "COleObject::DeActivateObj");
ResetPosRect();
if( _punkobj->QueryInterface(IID_IOleInPlaceObject, (void **)&pipo)
== NOERROR )
{
if( (hr =_punkobj->QueryInterface(IID_IOleObject, (void **)&poo)) ==
NOERROR )
{
// this code is a bit different from 1.0, but seems to
// make things work a bit better. Basically, we've taken a leaf
// from various sample apps and do the most brute force "de-activate"
// possible (you'd think just one call would be enough ;-)
// don't bother with the error return here.
pipo->UIDeactivate();
//fake something
ZeroMemory(&msg, sizeof(MSG));
msg.message = WM_LBUTTONDOWN;
_ped->TxGetWindow(&msg.hwnd);
// again, don't bother checking for errors; we need to
// plow through and get rid of stuff as much as possible.
poo->DoVerb(OLEIVERB_HIDE, &msg, (IOleClientSite *)this,
-1, msg.hwnd, &_rcPos);
// COMPATIBILITY ISSUE (alexgo): the RE1.0 code did some funny
// stuff with undo here, but I don't think it's necessary now
// with our multi-level undo model.
hr = pipo->InPlaceDeactivate();
poo->Release();
}
pipo->Release();
return hr;
}
return NOERROR;
}
/*
* COleObject::Convert
*
* @mfunc Converts the object to the specified class. Does reload
* the object but does NOT force an update (caller must do this).
*
* @rdesc
* HRESULT Success code.
*/
HRESULT COleObject::Convert(
REFCLSID rclsidNew, //@parm the destination clsid
LPCSTR lpstrUserTypeNew) //@parm the new user type name
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::Convert");
CLIPFORMAT cfOld;
CLSID clsidOld;
LPOLESTR szUserTypeOld = NULL;
HRESULT hr;
HRESULT hrLatest;
UsesMakeOLESTR;
// If object has no storage, return
if (!_pstg)
{
return ResultFromScode(E_INVALIDARG);
}
// Read the old class, format, and user type in
if ((hr = pReadClassStg(_pstg, &clsidOld)) ||
(hr = pReadFmtUserTypeStg(_pstg, &cfOld, &szUserTypeOld)))
{
return hr;
}
// Unload the object
Close(OLECLOSE_SAVEIFDIRTY);
_punkobj->Release();
if( IsZombie() )
{
return CO_E_RELEASED;
}
// Write the new class and user type, but old format, into the storage
if ((hr = pWriteClassStg(_pstg, rclsidNew)) ||
(hr = pWriteFmtUserTypeStg(_pstg, cfOld,
(LPOLESTR) MakeOLESTR(lpstrUserTypeNew))) ||
(hr = pSetConvertStg(_pstg, TRUE)) ||
((hr = _pstg->Commit(0)) && (hr = _pstg->Commit(STGC_OVERWRITE))))
{
// Uh oh, we're in a bad state; rewrite the original info
(VOID) pWriteClassStg(_pstg, clsidOld);
(VOID) pWriteFmtUserTypeStg(_pstg, cfOld, szUserTypeOld);
}
if( IsZombie() )
{
return CO_E_RELEASED;
}
// Reload the object and connect. If we can't reload it, delete it.
hrLatest = pOleLoad(_pstg, IID_IOleObject, (LPOLECLIENTSITE) this,
(void **)&_punkobj);
if (hrLatest != NOERROR)
{
CRchTxtPtr rtp(_ped, _cp);
// we don't want the delete of this object to go on the undo
// stack. We use a space so that cp's will work out right for
// other undo actions.
rtp.ReplaceRange(1, 1, L" ", NULL, -1);
}
else
{
ConnectObject();
}
// Free the old
pCoTaskMemFree(szUserTypeOld);
return hr ? hr : hrLatest;
}
/*
* COleObject::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.
*/
HRESULT COleObject::ActivateAs(REFCLSID rclsid, REFCLSID rclsidAs)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::ActivateAs");
HRESULT hr = NOERROR;
IOleObject * poo = NULL;
CLSID clsid;
//Get the clsid of the object.
hr = _punkobj->QueryInterface(IID_IOleObject, (void **)&poo);
if( hr == NOERROR )
{
//NOTE: We are depending on the behavior of GetUserClassID to
//return the current clsid of the object (not the TreatAs id).
//This should hold true as long as long as we haven't reloaded
//it yet. If there are problems with ActivateAs in the future,
//this might be a suspect.
hr = poo->GetUserClassID(&clsid);
poo->Release();
}
if( hr != NOERROR )
{
return hr;
}
if( IsZombie() )
{
return CO_E_RELEASED;
}
//Check to see if the clsid of the object matches the clsid to be
//treated as something else. If it is we need to unload and reload
//the object.
if( IsEqualCLSID(clsid, rclsid) )
{
// Unload the object
Close(OLECLOSE_SAVEIFDIRTY);
_punkobj->Release();
if( IsZombie() )
{
return CO_E_RELEASED;
}
// Reload the object and connect. If we can't reload it, delete it.
hr = pOleLoad(_pstg, IID_IOleObject, (LPOLECLIENTSITE) this,
(void **)&_punkobj);
if (hr != NOERROR)
{
CRchTxtPtr rtp(_ped, _cp);
// We don't want the delete of this object to go on the undo
// stack. We use a space so that cp's will work out right for
// other undo actions.
rtp.ReplaceRange(1, 1, L" ", NULL, -1);
}
else
{
ConnectObject();
}
}
return hr;
}
/*
* COleObject::SetLinkAvailable
*
* @mfunc
* Allows client to tell us whether the link is available or not.
*
* @rdesc
* HRESULT Success code.
*/
HRESULT COleObject::SetLinkAvailable(
BOOL fAvailable) //@parm if TRUE, make object linkable
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::SetLinkAvailable");
// If this is not a link, return
if (!(_pi.dwFlags & REO_LINK))
{
return E_INVALIDARG;
}
// Set the flag as appropriate
if (fAvailable)
{
_pi.dwFlags |= REO_LINKAVAILABLE;
}
else
{
_pi.dwFlags &= ~REO_LINKAVAILABLE;
}
return NOERROR;
}
/*
* COleObject::WriteTextInfoToEditStream
*
* @mfunc
* Used for textize support, Tries to determine the text
* representation for an object and then writes that info
* to the given stream. The only thing this is particularly useful
* for is to support richedit1.0's TEXTIZED data format.
*
* @rdesc
* LONG Number of chras written..
*/
LONG COleObject::WriteTextInfoToEditStream(
EDITSTREAM *pes)
{
LONG cch;
LONG cbWritten = 0;
HRESULT hr;
IOleObject *poo;
IDataObject *pdataobj;
STGMEDIUM med;
char *pch; //we only deal with ANSI data here
HANDLE hGlobal;
if((hr = _punkobj->QueryInterface(IID_IOleObject, (void **)&poo)) == NOERROR )
{
hr = poo->GetClipboardData( 0, &pdataobj);
poo->Release();
}
if(FAILED(hr))
{
hr = _punkobj->QueryInterface(IID_IDataObject, (void **)&pdataobj);
if(FAILED(hr))
{
pes->dwError = (DWORD) E_FAIL;
goto Default;
}
}
med.tymed = TYMED_HGLOBAL;
med.pUnkForRelease = NULL;
med.hGlobal = NULL;
hr = pdataobj->GetData(&g_rgFETC[iAnsiFETC], &med);
if(FAILED(hr))
{
pes->dwError = (DWORD)hr;
}
else
{
hGlobal = med.hGlobal;
pch = (char *)GlobalLock(hGlobal);
if( pch )
{
for (cch = 0; pch[cch]; cch++);
pes->dwError = pes->pfnCallback(pes->dwCookie, (BYTE *)pch, cch,
&cbWritten);
GlobalUnlock(hGlobal);
}
pReleaseStgMedium(&med);
}
Default:
if(cbWritten <= 0)
{
char ch = ' ';
pes->pfnCallback(pes->dwCookie, (BYTE *)&ch, sizeof(char), &cbWritten);
pes->dwError = 0;
}
pdataobj->Release();
return cbWritten;
}
/*
* COleObject::SetDvaspect
*
* @mfunc Allows client to tell us which aspect to use and force us
* to recompute positioning and redraw.
*
*/
void COleObject::SetDvaspect(
DWORD dvaspect) //@parm the aspect to use
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::SetDvaspect");
_pi.dvaspect = dvaspect;
// Cause ourselves to redraw and update
OnViewChange(dvaspect, (DWORD) -1);
}
/*
* COleObject::HandsOffStorage
*
* @mfunc See IPersistStore::HandsOffStorage.
*
*/
void COleObject::HandsOffStorage(void)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::HandsOffStorage");
// Free the storage we currently have, if we have one.
SafeReleaseAndNULL((IUnknown**)&_pstg);
}
/*
* COleObject::SaveCompleted
*
* @mfunc See IPersistStore::SaveCompleted.
*
*/
void COleObject::SaveCompleted(
LPSTORAGE lpstg) //@parm new storage
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::SaveCompleted");
// Did our caller give us a new storage to remember?
if (lpstg)
{
// Free the storage we currently have, if we have one
if (_pstg)
{
SafeReleaseAndNULL((IUnknown**)&_pstg);
}
// Remember the storage we are given, since we are given one
lpstg->AddRef();
_pstg = lpstg;
}
}
/*
* SetAllowedResizeDirections
*
* @func Resizing helper function
*
*/
static void SetAllowedResizeDirections(
const POINT & pt,
const RECT & rc,
LPTSTR lphand,
BOOL & fTop,
BOOL & fBottom,
BOOL & fLeft,
BOOL & fRight
)
{
fTop = abs(pt.y - rc.top) < abs(pt.y - rc.bottom);
fBottom = !fTop;
fLeft = abs(pt.x - rc.left) < abs(pt.x - rc.right);
fRight = !fLeft;
if (lphand == IDC_SIZENS)
{
fLeft = fRight = FALSE;
}
else if (lphand == IDC_SIZEWE)
{
fTop = fBottom = FALSE;
}
return;
}
/*
* SetRestriction.
*
* @func Resizing helper function determines bounding rectangle for resizing.
*
*/
static void SetRestriction(
RECT & rc,
HWND hwnd,
DWORD dwScroll
)
{
GetClientRect(hwnd, &rc);
InflateRect(&rc, -1, -1); // So rectangle is visible
// allow objects to grow larger than the window in the
// directions which have scrollbars
if(dwScroll & WS_HSCROLL)
{
rc.right = MAXLONG;
}
if(dwScroll & WS_VSCROLL)
{
rc.bottom = MAXLONG;
}
return;
}
/*
* Restrict
*
* @func Resizing helper function bounds a point within a rectangle
*
*/
static void Restrict(
POINT &pt,
RECT &rc
)
{
if (pt.x < rc.left)
{
pt.x = rc.left;
}
else if (pt.x > rc.right)
{
pt.x = rc.right;
}
if (pt.y < rc.top)
{
pt.y = rc.top;
}
else if (pt.y > rc.bottom)
{
pt.y = rc.bottom;
}
return;
}
/*
* COleObject::HandleResize
*
* @mfunc Deal with object resizing.
*
*/
BOOL COleObject::HandleResize(const POINT &pt)
{
LPTSTR lphand;
DWORD dwFlags = _pi.dwFlags;
HDC hdc;
HWND hwnd;
RECT rcOld;
RECT rcRestrict;
BOOL fTop, fBottom, fLeft, fRight;
BOOL fEscape;
CDisplay *pdp = _ped->_pdp;
if (!(dwFlags & REO_SELECTED) ||
!(dwFlags & REO_RESIZABLE) ||
(lphand = CheckForHandleHit(pt)) == NULL || !pdp)
{
return FALSE;
}
hdc = pdp->GetDC();
rcOld = _rcPos; // Save old size
_ped->TxGetWindow(&hwnd);
ASSERT(IsWindow(hwnd));
SetCapture(hwnd);
SetRestriction( rcRestrict, hwnd, _ped->TxGetScrollBars() );
SetAllowedResizeDirections(pt, _rcPos, lphand,
fTop, fBottom, fLeft, fRight);
// Erase and redraw frame without handles.
DrawFrame(pdp, hdc, &_rcPos);
_pi.dwFlags = REO_NULL;
DrawFrame(pdp, hdc, &_rcPos);
fEscape = FALSE;
const INT vkey = GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON;
while (GetAsyncKeyState(vkey) & 0x8000)
{
POINT ptLast = pt;
POINT ptCur;
MSG msg;
// Stop if the ESC key has been pressed
if (GetAsyncKeyState(VK_ESCAPE) & 0x0001)
{
fEscape = TRUE;
break;
}
GetCursorPos(&ptCur);
ScreenToClient(hwnd, &ptCur);
// GetCursorPos() isn't supported on WinCE. We have it hacked to
// be GetMessagePos() which unfortunately in this case will cause
// ptCur to never change. By removing this check we end up drawing
// multiple times when the user pauses during a resize.
#ifndef UNDER_CE
// If mouse hasn't moved, try again
if ((ptCur.x == ptLast.x) && (ptCur.y == ptLast.y))
{
continue;
}
#endif
ptLast = ptCur;
Restrict( ptCur, rcRestrict );
// Erase old rectangle, update rectangle, and redraw
DrawFrame(pdp, hdc, &_rcPos);
if (fLeft) _rcPos.left = ptCur.x;
if (fRight) _rcPos.right = ptCur.x;
if (fTop) _rcPos.top = ptCur.y;
if (fBottom) _rcPos.bottom = ptCur.y;
// Keep a minimun width and height
INT xWidthSys = pdp->GetXWidthSys();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -