📄 tenant.cpp
字号:
m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, m_pImpIAdviseSink);
//We need an IOleObject most of the time, so get one here.
m_pIOleObject=NULL;
hr=pObj->QueryInterface(IID_IOleObject
, (PPVOID)&m_pIOleObject);
/*
* Follow up object creation with advises and so forth. If
* we cannot get IOleObject here, then we know we can't do
* any IOleObject actions from here on--object is static.
*/
if (FAILED(hr))
return TRUE;
/*
* Get the MiscStatus bits and check for OLEMISC_ONLYICONIC.
* If set, force dwAspect in m_fe to DVASPECT_ICON so we
* remember to draw it properly and do extents right.
*/
m_pIOleObject->GetMiscStatus(m_fe.dwAspect, &m_grfMisc);
if (OLEMISC_ONLYICONIC & m_grfMisc)
m_fe.dwAspect=DVASPECT_ICON;
/*
* We could pass m_pImpIOleClientSite in an OleCreate* call, but
* since this function could be called after OleLoad, we still
* need to do this here, so it's always done here...
*/
m_pIOleObject->SetClientSite(m_pImpIOleClientSite);
m_pIOleObject->Advise(m_pImpIAdviseSink, &dw);
OleSetContainedObject(m_pIOleObject, TRUE);
/*
* For IOleObject::SetHostNames we need the application name
* and the document name (which is passed in the object
* parameter). The design of Patron doesn't give us nice
* structured access to the name of the document we're in, so
* I grab the parent of the Pages window (the document) and
* send it DOCM_PDOCUMENT which returns us the pointer.
* Roundabout, but it works.
*/
pDoc=(PCDocument)SendMessage(GetParent(m_hWnd), DOCM_PDOCUMENT
, 0, 0L);
if (NULL!=pDoc)
pDoc->FilenameGet(szFile, CCHPATHMAX);
else
szFile[0]=0;
//CHAPTER21MOD
NotifyOfRename(szFile, NULL, NULL);
//End CHAPTER21MOD
/*
* If we're creating an iconic aspect object and we have
* an object from the Insert Object dialog, then we need to
* store that iconic presentation in the cache, handled
* with the utility function INOLE_SwitchDisplayAspect. In
* this case dwData is a handle to the metafile containing
* the icon. If dwData is NULL then we depend on the
* server to provide the aspect, in which case we need
* a view advise.
*/
if (DVASPECT_ICON & m_fe.dwAspect)
{
DWORD dw=DVASPECT_CONTENT;
IAdviseSink *pSink;
pSink=(NULL==dwData) ? NULL : m_pImpIAdviseSink;
INOLE_SwitchDisplayAspect(m_pIOleObject, &dw
, DVASPECT_ICON, (HGLOBAL)(UINT)dwData, FALSE
, (NULL!=dwData), pSink, NULL);
}
return TRUE;
}
/*
* CTenant::Open
*
* Purpose:
* Retrieves the IStorage associated with this tenant. The
* IStorage is owned by the tenant and thus the tenant always
* holds a reference count.
*
* If the storage is already open for this tenant, then this
* function will AddRef it; therefore the caller must always
* match an Open with a Close.
*
* Parameters:
* pIStorage LPSTORAGE above this tenant (which has its
* own storage).
*
* Return Value:
* BOOL TRUE if opening succeeds, FALSE otherwise.
*/
BOOL CTenant::Open(LPSTORAGE pIStorage)
{
HRESULT hr=NOERROR;
DWORD dwMode=STGM_TRANSACTED | STGM_READWRITE
| STGM_SHARE_EXCLUSIVE;
OLECHAR szTemp[32];
if (NULL==m_pIStorage)
{
if (NULL==pIStorage)
return FALSE;
/*
* Attempt to open the storage under this ID. If there is
* none, then create it. In either case we end up with an
* IStorage that we either save in pPage or release.
*/
GetStorageName(szTemp);
hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0
, &m_pIStorage);
if (FAILED(hr))
{
hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0
, &m_pIStorage);
}
}
else
m_pIStorage->AddRef();
if (FAILED(hr))
return FALSE;
m_cOpens++;
//Create these if we don't have them already.
if (NULL==m_pImpIOleClientSite && NULL==m_pImpIAdviseSink)
{
m_pImpIOleClientSite=new CImpIOleClientSite(this, this);
m_pImpIAdviseSink=new CImpIAdviseSink(this, this);
if (NULL==m_pImpIOleClientSite || NULL==m_pImpIAdviseSink)
return FALSE;
}
return TRUE;
}
/*
* CTenant::Close
*
* Purpose:
* Possibly commits the storage, then releases it reversing the
* reference count from Open. If the reference on the storage
* goes to zero, the storage is forgotten. However, the object we
* contain is still held and as long as it's active the storage
* remains alive.
*
* Parameters:
* fCommit BOOL indicating if we're to commit.
*
* Return Value:
* None
*/
void CTenant::Close(BOOL fCommit)
{
if (fCommit)
Update();
if (NULL!=m_pIStorage)
{
m_pIStorage->Release();
/*
* We can't use a zero reference count to know when to NULL
* this since other things might have AddRef'd the storage.
*/
if (0==--m_cOpens)
{
m_pIStorage=NULL;
//Close the object saving if necessary
if (NULL!=m_pIOleObject)
{
m_pIOleObject->Close(OLECLOSE_SAVEIFDIRTY);
ReleaseInterface(m_pIOleObject);
}
//Release all other held pointers
if (NULL!=m_pIViewObject2)
{
m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, NULL);
ReleaseInterface(m_pIViewObject2);
}
//We know we only hold one ref from Create or Load
ReleaseInterface(m_pObj);
}
}
return;
}
/*
* CTenant::Update
*
* Purpose:
* Forces a common on the page if it's open.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if the object is open, FALSE otherwise.
*/
BOOL CTenant::Update(void)
{
LPPERSISTSTORAGE pIPS;
if (NULL!=m_pIStorage)
{
/*
* We need to OleSave again because we might have changed
* the size or position of this tenant. We also need to
* save the rectangle on the page, since that's not known
* to OLE.
*/
m_pObj->QueryInterface(IID_IPersistStorage, (PPVOID)&pIPS);
//This fails for static objects...so we improvise if so
if (FAILED(OleSave(pIPS, m_pIStorage, TRUE)))
{
//This is essentially what OleSave does.
WriteClassStg(m_pIStorage, m_clsID);
pIPS->Save(m_pIStorage, TRUE);
}
pIPS->SaveCompleted(NULL);
pIPS->Release();
m_pIStorage->Commit(STGC_DEFAULT);
}
return FALSE;
}
/*
* CTenant::Destroy
*
* Purpose:
* Removes this page from the given storage. The caller should
* eventually delete this CTenant object to free the object herein.
* Nothing is committed when being destroyed.
*
* Parameters:
* pIStorage LPSTORAGE contianing this page on which to call
* DestroyElement
*
* Return Value:
* None
*/
void CTenant::Destroy(LPSTORAGE pIStorage)
{
OLECHAR szTemp[32];
if (NULL!=pIStorage)
{
if (NULL!=m_pIOleObject)
m_pIOleObject->Close(OLECLOSE_NOSAVE);
if (NULL!=m_pIStorage)
{
//Remove all reference/open counts on this storage.
while (0!=m_cOpens)
{
m_pIStorage->Release();
m_cOpens--;
}
}
GetStorageName(szTemp);
pIStorage->DestroyElement(szTemp);
m_pIStorage=NULL;
}
return;
}
/*
* CTenant::Select
*
* Purpose:
* Selects or deselects the tenant.
*
* Parameters:
* fSelect BOOL indicating the new state of the tenant.
*
* Return Value:
* None
*/
void CTenant::Select(BOOL fSelect)
{
BOOL fWasSelected;
DWORD dwState;
RECT rc;
HDC hDC;
fWasSelected=(BOOL)(TENANTSTATE_SELECTED & m_dwState);
//Nothing to do when there's no change.
if (fWasSelected==fSelect)
return;
dwState=m_dwState & ~TENANTSTATE_SELECTED;
m_dwState=dwState | ((fSelect) ? TENANTSTATE_SELECTED : 0);
/*
* Draw sizing handles to show the selection state. We convert
* things to MM_TEXT since that's what this function expects.
*/
RECTFROMRECTL(rc, m_rcl);
RectConvertMappings(&rc, NULL, TRUE);
OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
hDC=GetDC(m_hWnd);
UIDrawHandles(&rc, hDC, UI_HANDLES_INSIDE
| UI_HANDLES_NOBORDER | UI_HANDLES_USEINVERSE
, CXYHANDLE, !fWasSelected);
ReleaseDC(m_hWnd, hDC);
if (fSelect)
m_pPG->m_fDirty=TRUE;
return;
}
/*
* CTenant::ShowAsOpen
*
* Purpose:
* Draws or removes the hatch pattern over an object.
*
* Parameters:
* fOpen BOOL indicating the open state of this tenant.
*
* Return Value:
* None
*/
void CTenant::ShowAsOpen(BOOL fOpen)
{
BOOL fWasOpen;
DWORD dwState;
RECT rc;
HDC hDC;
fWasOpen=(BOOL)(TENANTSTATE_OPEN & m_dwState);
dwState=m_dwState & ~TENANTSTATE_OPEN;
m_dwState=dwState | ((fOpen) ? TENANTSTATE_OPEN : 0);
//If this was not open, then just hatch, otherwise repaint.
if (!fWasOpen && fOpen)
{
RECTFROMRECTL(rc, m_rcl);
RectConvertMappings(&rc, NULL, TRUE);
OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
hDC=GetDC(m_hWnd);
UIDrawShading(&rc, hDC, UI_SHADE_FULLRECT, 0);
ReleaseDC(m_hWnd, hDC);
}
if (fWasOpen && !fOpen)
Repaint();
return;
}
/*
* CTenant::ShowYourself
*
* Purpose:
* Function that really just implements IOleClientSite::ShowObject.
* Here we first check if the tenant is fully visible, and if so,
* then nothing needs to happen. Otherwise, if the upper left
* corner of the tenant is in the upper left visible quadrant of
* the window, we'll also consider ourselves done. Otherwise
* we'll put the upper left corner of the object at the upper left
* corner of the window.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CTenant::ShowYourself(void)
{
RECTL rcl;
RECT rc;
POINT pt1, pt2;
//Scrolling deals in device units; get our rectangle in those.
RectGet(&rcl, TRUE);
//Get the window rectangle offset for the current scroll pos.
GetClientRect(m_hWnd, &rc);
OffsetRect(&rc, m_pPG->m_xPos, m_pPG->m_yPos);
//Check if the object is already visible. (macro in bookguid.h)
SETPOINT(pt1, (int)rcl.left, (int)rcl.top);
SETPOINT(pt2, (int)rcl.right, (int)rcl.bottom);
if (PtInRect(&rc, pt1) && PtInRect(&rc, pt2))
return;
//Check if the upper left is within the upper left quadrant
if (((int)rcl.left > rc.left
&& (int)rcl.left < ((rc.right+rc.left)/2))
&& ((int)rcl.top > rc.top
&& (int)rcl.top < ((rc.bottom+rc.top)/2)))
return;
//These are macros in INC\BOOK1632.H
SendScrollPosition(m_hWnd, WM_HSCROLL, rcl.left-8);
SendScrollPosition(m_hWnd, WM_VSCROLL, rcl.top-8);
return;
}
/*
* CTenant::AddVerbMenu
*
* Purpose:
* Creates the variable verb menu item for the object in this
* tenant.
*
* Parmeters:
* hMenu HMENU on which to add items.
* iPos UINT position on that menu to add items.
*
* Return Value:
* None
*/
void CTenant::AddVerbMenu(HMENU hMenu, UINT iPos)
{
HMENU hMenuTemp;
LPOLEOBJECT pObj=m_pIOleObject;
//If we're static, say we have no object.
if (TENANTTYPE_STATIC==m_tType)
pObj=NULL;
OleUIAddVerbMenu(pObj, NULL, hMenu, iPos, IDM_VERBMIN
, IDM_VERBMAX, TRUE, IDM_EDITCONVERT, &hMenuTemp);
return;
}
/*
* CTenant::TypeGet
*
* Purpose:
* Returns the type of this tenant
*
* Parameters:
* None
*
* Return Value:
* TENANTTYPE Type of the tenant.
*/
TENANTTYPE CTenant::TypeGet(void)
{
return m_tType;
}
/*
* CTenant::CopyEmbeddedObject
*
* Purpose:
* Copies an embedded object to the given data object (via SetData,
* assuming this is a data transfer object for clipboard/drag-drop)
* if that's what we're holding.
*
* Parameters:
* pIDataObject LPDATAOBJECT in which to store the copy.
* pFE LPFORMATETC into which to copy CFSTR_EMBEDDEDOBJECT
* if we put that in the data object.
* pptl PPOINTL to the pick point (NULL outside of
* drag-drop);
*
* Return Value:
* None
*/
void CTenant::CopyEmbeddedObject(LPDATAOBJECT pIDataObject
, LPFORMATETC pFE, PPOINTL pptl)
{
LPPERSISTSTORAGE pIPS;
STGMEDIUM stm;
FORMATETC fe;
HRESULT hr;
UINT cf;
POINTL ptl;
SIZEL szl;
//Can only copy embeddings.
if (TENANTTYPE_EMBEDDEDOBJECT!=m_tType || NULL==m_pIOleObject)
return;
if (NULL==pptl)
{
SETPOINTL(ptl, 0, 0);
pptl=&ptl;
}
/*
* Create CFSTR_EMBEDDEDOBJECT. This is simply an IStorage with
* a copy of the embedded object in it. The not-so-simple part
* is getting an IStorage to stuff it in. For this operation
* we'll use a temporary compound file.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -