📄 coleobj.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 COLEOBJ.CPP OLE Object management class implemenation |
*
* Author: alexgo 10/24/95
*
* Note: Much of this code is a port from Richedit1.0 sources
* (cleaned up a bit, ported to C++, etc.) So if there's any
* bit of strangeness, it's probably there for a reason.
*
*/
#include "_common.h"
#include "_edit.h"
#include "_coleobj.h"
#include "_objmgr.h"
#include "_select.h"
#include "_rtext.h"
#include "_disp.h"
#include "_dispprt.h"
#include "_antievt.h"
#include "_dxfrobj.h"
ASSERTDATA
//
// data private to this file
//
static const OLECHAR szSiteFlagsStm[] = OLESTR("RichEditFlags");
//
// EXCEL clsid's. We have to make some special purpose hacks
// for XL.
const CLSID rgclsidExcel[] =
{
{ 0x00020810L, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} }, // Excel Worksheet
{ 0x00020811L, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} }, // Excel Chart
{ 0x00020812L, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} }, // Excel App1
{ 0x00020841L, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} }, // Excel App2
};
const INT cclsidExcel = sizeof(rgclsidExcel) / sizeof(rgclsidExcel[0]);
//
// WordArt CLSID for more special purpose hacks.
//
const GUID CLSID_WordArt =
{ 0x000212F0L, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46} };
const GUID CLSID_PaintbrushPicture =
{ 0x0003000AL, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
const GUID CLSID_BitmapImage =
{ 0xD3E34B21L, 0x9D75, 0x101A, { 0x8C, 0x3D, 0x00, 0xAA, 0x00, 0x1A, 0x16, 0x52 } };
#define dxyHandle (6) // Object frame handle size
#define dxyFrameDefault (1) // Object frame width
//
// utility functions
//
/*
* IsExcelCLSID
*
* @func checks to see if the given clsid is one of XL's
*
* @rdesc TRUE/FALSE
*
*/
BOOL IsExcelCLSID(REFGUID clsid)
{
DWORD i;
for( i = 0; i < cclsidExcel; i++ )
{
if (IsEqualCLSID(clsid, rgclsidExcel[i]))
{
return TRUE;
}
}
return FALSE;
}
//
// PUBLIC methods
//
/*
* COleObject::QueryInterface
*
* @mfunc the standard OLE QueryInterface
*
* @rdesc NOERROR <nl>
* E_NOINTERFACE
*
*/
STDMETHODIMP COleObject::QueryInterface(
REFIID riid, //@parm the requested interface ID
void ** ppv) //@parm out param for the result
{
HRESULT hr = NOERROR;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::QueryInterface");
if( IsZombie() )
{
return CO_E_RELEASED;
}
if( !ppv )
{
return E_INVALIDARG;
}
else
{
*ppv = NULL;
}
if( IsEqualIID(riid, IID_IUnknown) )
{
*ppv = (IUnknown *)(IOleClientSite *)this;
}
else if( IsEqualIID(riid, IID_IOleClientSite) )
{
*ppv = (IOleClientSite *)this;
}
else if( IsEqualIID(riid, IID_IOleInPlaceSite) )
{
*ppv = (IOleInPlaceSite *)this;
}
else if( IsEqualIID(riid, IID_IAdviseSink) )
{
*ppv = (IAdviseSink *)this;
}
else if( IsEqualIID(riid, IID_IOleWindow) )
{
*ppv = (IOleWindow *)this;
}
else if( IsEqualIID(riid, IID_IRichEditOleCallback) )
{
//
// NB!! Returning this pointer in our QI is
// phenomenally bogus; it breaks fundamental COM
// identity rules (granted, not many understand them!).
// Anyway, RichEdit 1.0 did this, so we better.
//
TRACEWARNSZ("Returning IRichEditOleCallback interface, COM "
"identity rules broken!");
*ppv = _ped->GetRECallback();
}
else
{
hr = E_NOINTERFACE;
}
if( *ppv )
{
(*(IUnknown **)ppv)->AddRef();
}
return hr;
}
/*
* COleObject::AddRef
*
* @mfunc increments the reference count
*
* @rdesc the new reference count
*
*/
STDMETHODIMP_(ULONG) COleObject::AddRef(void)
{
ULONG cRef;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::AddRef");
cRef = SafeAddRef();
return cRef;
}
/*
* COleObject::Release
*
* @mfunc decrements the reference count
*
* @rdesc the new reference count
*
*/
STDMETHODIMP_(ULONG) COleObject::Release(void)
{
ULONG cRef;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::Release");
cRef = SafeRelease();
return cRef;
}
/*
* COleObject::SaveObject
*
* @mfunc implemtenation of IOleClientSite::SaveObject
*
* @rdesc HRESULT
*
*/
STDMETHODIMP COleObject::SaveObject(void)
{
IPersistStorage *pps;
HRESULT hr;
CCallMgr callmgr(_ped);
CStabilize stabilize(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::SaveObject");
if( !_punkobj || !_pstg )
{
TRACEWARNSZ("SaveObject called on invalid object");
return E_UNEXPECTED;
}
if( IsZombie() )
{
return CO_E_RELEASED;
}
hr = _punkobj->QueryInterface(IID_IPersistStorage, (void **)&pps);
TESTANDTRACEHR(hr);
if( hr == NOERROR )
{
if( IsZombie() )
{
return CO_E_RELEASED;
}
SavePrivateState();
if( IsZombie() )
{
return CO_E_RELEASED;
}
hr = pOleSave(pps, _pstg, TRUE);
if( IsZombie() )
{
return CO_E_RELEASED;
}
TESTANDTRACEHR(hr);
// note that SaveCompleted is called even if OleSave fails.
// If both OleSave and SaveCompleted succeed, then go ahead
// and commit the changes
if( pps->SaveCompleted(NULL) == NOERROR && hr == NOERROR )
{
if( IsZombie() )
{
return CO_E_RELEASED;
}
hr = _pstg->Commit(STGC_DEFAULT);
TESTANDTRACEHR(hr);
}
pps->Release();
}
return hr;
}
/*
* COleObject::GetMoniker
*
* @mfunc implementation of IOleClientSite::GetMoniker
*
* @rdesc E_NOTIMPL
*
*/
STDMETHODIMP COleObject::GetMoniker(
DWORD dwAssign, //@parm force an assignment?
DWORD dwWhichMoniker, //@parm kind of moniker to get
IMoniker **ppmk) //@parm out param for result
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::GetMoniker");
TRACEWARNSZ("method not implemented!");
if( ppmk )
{
*ppmk = NULL;
}
return E_NOTIMPL;
}
/*
* COleObject::GetContainer
*
* @mfunc implementation of IOleClientSite::GetContainer
*
* @rdesc E_NOINTERFACE
*/
STDMETHODIMP COleObject::GetContainer(
IOleContainer **ppcont) //@parm out parm for the result
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::GetContainer");
TRACEWARNSZ("method not implemented!");
if( ppcont )
{
*ppcont = NULL;
}
// richedit 1.0 returns E_NOINTERFACE instead of E_NOTIMPL. Do
// the same.
return E_NOINTERFACE;
}
/*
* COleObject::ShowObject
*
* @mfunc Implementation of IOleClientSite::ShowObject.
*
* @rdesc E_NOTIMPL
*
*/
STDMETHODIMP COleObject::ShowObject(void)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::ShowObject");
TRACEWARNSZ("method not implemented!");
return E_NOTIMPL;
}
/*
* COleObject::OnShowWindow
*
* @mfunc implementation of IOleClientSite::OnShowWindow -- notifies
* the client site that the object is or is not being shown in it's
* own application window. This govens whether or not hatching should
* appear around the object in richedit.
*
* @rdesc HRESULT
*
*/
STDMETHODIMP COleObject::OnShowWindow(
BOOL fShow) //@parm if TRUE, the object is being drawn in it's
//own window
{
DWORD dwFlags = _pi.dwFlags;
CCallMgr callmgr(_ped);
CStabilize stabilize(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::OnShowWindow");
if( IsZombie() )
{
return CO_E_RELEASED;
}
if( fShow )
{
_pi.dwFlags |= REO_OPEN;
}
else
{
_pi.dwFlags &= ~REO_OPEN;
}
// if something changed, redraw the object
if( dwFlags != _pi.dwFlags )
{
// invalidate the rect that we're in.
_ped->TxInvalidateRect(&_rcPos, FALSE);
// We're not allowed to call invalidate rect by itself
// without terminating it with a call to update window.
// However, we don't care at this point if things are
// redrawn right away.
_ped->TxUpdateWindow();
// COMPATIBILITY ISSUE: (alexgo) the RE1.0 code did some funny
// stuff with undo here. I don't believe it's necessary to
// repeat that code with our multi-level undo model,
}
return NOERROR;
}
/*
* COleObject::RequestNewObjectLayout
*
* @mfunc Implementation of IOleClientSite::RequestNewObjectLayout
*
* @rdesc E_NOTIMPL
*/
STDMETHODIMP COleObject::RequestNewObjectLayout(void)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN,
"COleObject::RequestNewObjectLayout");
TRACEWARNSZ("method not implemented!");
return E_NOTIMPL;
}
/*
* COleObject::GetWindow
*
* @mfunc Implementation of IOleInPlaceSite::GetWindow
*
* @rdesc HRESULT
*/
STDMETHODIMP COleObject::GetWindow(
HWND *phwnd) //@parm where to put the window
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::GetWindow");
// NB! this method is not stabilized.
if( IsZombie() )
{
return CO_E_RELEASED;
}
if( phwnd )
{
return _ped->TxGetWindow(phwnd);
}
return E_INVALIDARG;
}
/*
* COleObject::ContextSensitiveHelp
*
* @mfunc Implemenation of IOleInPlaceSite::ContextSensitiveHelp
*
* @rdesc HRESULT
*/
STDMETHODIMP COleObject::ContextSensitiveHelp(
BOOL fEnterMode) //@parm, if TRUE, then we're in help mode
{
IRichEditOleCallback *precall;
CCallMgr callmgr(_ped);
CStabilize stabilize(this);
CObjectMgr *pCObM = NULL;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN,
"COleObject::ContextSensitiveHelp");
if( IsZombie() )
{
return CO_E_RELEASED;
}
// if the mode changes
if (pCObM = _ped->GetObjectMgr())
{
if( pCObM->GetHelpMode() != fEnterMode )
{
pCObM->SetHelpMode(fEnterMode);
precall = _ped->GetRECallback();
if( precall )
{
return precall->ContextSensitiveHelp(fEnterMode);
}
}
}
return NOERROR;
}
/*
* COleObject::CanInPlaceActivate
*
* @mfunc implementation of IOleInPlaceSite::CanInPlaceActivate
*
* @rdesc NOERROR or S_FALSE
*/
STDMETHODIMP COleObject::CanInPlaceActivate(void)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN,
"COleObject::CanInPlaceActivate");
if( IsZombie() )
{
return CO_E_RELEASED;
}
// if we have a callback && the object is willing to show
// content, then we can in-place activate
if( _ped->GetRECallback() &&
_pi.dvaspect == DVASPECT_CONTENT )
{
return NOERROR;
}
else
{
return S_FALSE;
}
}
/*
* COleObject::OnInPlaceActivate
*
* @mfunc implementation of IOleInPlaceSite::OnInPlaceActivate
*
* @rdesc noerror
*/
STDMETHODIMP COleObject::OnInPlaceActivate(void)
{
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::OnInPlaceActivate");
// assume that in-place objects can never be blank.
_pi.dwFlags &= ~REO_BLANK;
_fInPlaceActive = TRUE;
return NOERROR;
}
/*
* COleObject::OnUIActivate
*
* @mfunc implementation of IOleInPlaceSite::OnUIActivate. Notifies
* the container that the object is about to be activated in
* place with UI elements suchs as merged menus
*
* @rdesc HRESULT
*/
STDMETHODIMP COleObject::OnUIActivate(void)
{
IRichEditOleCallback *precall;
CTxtSelection *psel;
CCallMgr callmgr(_ped);
CStabilize stabilize(this);
CObjectMgr *pobjmgr;
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "COleObject::OnUIActivate");
if( IsZombie() )
{
return CO_E_RELEASED;
}
pobjmgr = _ped->GetObjectMgr();
if(!pobjmgr)
{
return E_OUTOFMEMORY;
}
precall = pobjmgr->GetRECallback();
if( precall )
{
precall->ShowContainerUI(FALSE);
if( IsZombie() )
{
return CO_E_RELEASED;
}
// this is an optimization for activating multiple
pobjmgr->SetShowUIPending(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -