📄 olesvr2.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#ifdef AFX_OLE4_SEG
#pragma code_seg(AFX_OLE4_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
//////////////////////////////////////////////////////////////////////////////
// COleServerItem implementation
COleServerItem::COleServerItem(COleServerDoc* pServerDoc, BOOL bAutoDelete)
{
if (pServerDoc != NULL)
ASSERT_VALID(pServerDoc);
m_dwRef = 0; // always start in disconnected state
m_bAutoDelete = bAutoDelete;
m_bNeedUnlock = FALSE;
// initially, item does not have an extent
m_sizeExtent.cx = 0;
m_sizeExtent.cy = 0;
// initialize advise holders
m_lpOleAdviseHolder = NULL;
m_lpDataAdviseHolder = NULL;
// add presentation formats to the data source
m_dataSource.m_nGrowBy = 1;
FORMATETC formatEtc;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_CONTENT;
formatEtc.lindex = -1;
// by default, a COleServerItem supports CF_METAFILEPICT
formatEtc.cfFormat = CF_METAFILEPICT;
formatEtc.tymed = TYMED_MFPICT;
m_dataSource.DelayRenderData(0, &formatEtc);
// add item to server document
m_pDocument = NULL;
if (pServerDoc != NULL)
pServerDoc->AddItem(this);
ASSERT(m_pDocument == pServerDoc);
AfxOleLockApp();
}
COleServerItem::~COleServerItem()
{
m_bAutoDelete = FALSE; // no delete during destructor
// release any advise holders
RELEASE(m_lpOleAdviseHolder);
RELEASE(m_lpDataAdviseHolder);
ExternalDisconnect();
// disconnect from the document
COleServerDoc* pDoc = GetDocument();
if (pDoc != NULL)
{
// remove external lock from it
if (m_bNeedUnlock)
{
pDoc->LockExternal(FALSE, TRUE);
m_bNeedUnlock = FALSE;
}
// reset m_pEmbeddedItem if destroying embedded item
if (pDoc->m_pEmbeddedItem == this)
pDoc->m_pEmbeddedItem = NULL;
// remove from list
pDoc->RemoveItem(this);
}
// cleanup any references
AfxOleUnlockApp();
}
BOOL COleServerItem::IsBlank() const
{
// server items are blank in order to keep them from serializing when
// COleDocument::Serialize is called.
return TRUE;
}
BOOL COleServerItem::IsConnected() const
{
// if item is connected in any way, return TRUE
if (m_dwRef != 0)
return TRUE;
// otherwise check if embedded item and document is connected
if (!IsLinkedItem() && GetDocument()->m_lpClientSite != NULL)
return TRUE;
return FALSE; // not connected
}
void COleServerItem::NotifyClient(OLE_NOTIFICATION nCode, DWORD dwParam)
{
switch (nCode)
{
// IDataObject notifications
case OLE_CHANGED:
if (m_lpDataAdviseHolder != NULL)
m_lpDataAdviseHolder->SendOnDataChange(GetDataObject(), dwParam, 0);
break;
// IOleObject notifications
case OLE_SAVED:
if (m_lpOleAdviseHolder != NULL)
m_lpOleAdviseHolder->SendOnSave();
break;
case OLE_CLOSED:
if (m_lpOleAdviseHolder != NULL)
m_lpOleAdviseHolder->SendOnClose();
break;
case OLE_RENAMED:
if (m_lpOleAdviseHolder != NULL)
{
// Note: the moniker should already be updated for this to work
LPMONIKER lpMoniker = (LPMONIKER)dwParam;
m_lpOleAdviseHolder->SendOnRename(lpMoniker);
}
break;
default:
ASSERT(FALSE);
}
}
/////////////////////////////////////////////////////////////////////////////
// Helpers for getting commonly used interfaces through interface map
LPDATAOBJECT COleServerItem::GetDataObject()
{
LPDATAOBJECT lpDataObject =
(LPDATAOBJECT)GetInterface(&IID_IDataObject);
ASSERT(lpDataObject != NULL);
return lpDataObject;
}
LPOLEOBJECT COleServerItem::GetOleObject()
{
LPOLEOBJECT lpOleObject =
(LPOLEOBJECT)GetInterface(&IID_IOleObject);
ASSERT(lpOleObject != NULL);
return lpOleObject;
}
/////////////////////////////////////////////////////////////////////////////
// COleServerItem overrides
BOOL COleServerItem::OnQueryUpdateItems()
{
COleDocument* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// update all of the embedded objects
POSITION pos = pDoc->GetStartPosition();
COleClientItem* pItem;
while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
{
// if any item is out-of-date, then this item is out-of-date
if (pItem->m_lpObject->IsUpToDate() != NULL)
return TRUE; // update needed
}
return FALSE; // update not needed
}
void COleServerItem::OnUpdateItems()
{
COleDocument* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// update all of the embedded objects
POSITION pos = pDoc->GetStartPosition();
COleClientItem* pItem;
while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
{
// update any out-of-date item
if (pItem->m_lpObject->IsUpToDate() != NULL)
pItem->m_lpObject->Update();
}
}
BOOL COleServerItem::OnSetExtent(DVASPECT dwDrawAspect, const CSize& size)
{
ASSERT_VALID(this);
if (dwDrawAspect == DVASPECT_CONTENT)
{
m_sizeExtent = size; // simply remember the extent
return TRUE;
}
return FALSE; // not implemented for that dwDrawAspect
}
BOOL COleServerItem::OnGetExtent(DVASPECT /*dwDrawAspect*/, CSize& rSize)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(&rSize, sizeof(CSize)));
// the default implementation doesn't know what the extent is
rSize.cx = 0;
rSize.cy = 0;
return FALSE;
}
void COleServerItem::OnDoVerb(LONG iVerb)
{
switch (iVerb)
{
// open - maps to OnOpen
case OLEIVERB_OPEN:
case -OLEIVERB_OPEN-1: // allows positive OLEIVERB_OPEN-1 in registry
OnOpen();
break;
// primary, show, and unknown map to OnShow
case OLEIVERB_PRIMARY: // OLEIVERB_PRIMARY is 0 and "Edit" in registry
case OLEIVERB_SHOW:
OnShow();
break;
// hide maps to OnHide
case OLEIVERB_HIDE:
case -OLEIVERB_HIDE-1: // allows positive OLEIVERB_HIDE-1 in registry
OnHide();
break;
default:
// negative verbs not understood should return E_NOTIMPL
if (iVerb < 0)
AfxThrowOleException(E_NOTIMPL);
// positive verb not processed --
// according to OLE spec, primary verb should be executed
// instead.
OnDoVerb(OLEIVERB_PRIMARY);
// also, OLEOBJ_S_INVALIDVERB should be returned.
AfxThrowOleException(OLEOBJ_S_INVALIDVERB);
}
}
BOOL COleServerItem::OnDrawEx(CDC* pDC, DVASPECT nDrawAspect, CSize& rSize)
{
ASSERT_VALID(pDC);
ASSERT(AfxIsValidAddress(&rSize, sizeof(CSize)));
if (nDrawAspect != DVASPECT_CONTENT)
return FALSE;
return OnDraw(pDC, rSize);
}
void COleServerItem::OnShow()
{
ASSERT_VALID(this);
// attempt in place activation (if not supported, fall back on "Open")
COleServerDoc* pDoc = GetDocument();
if (!pDoc->ActivateInPlace())
{
// by default OnShow() maps to OnOpen() if in-place activation
// not supported
OnOpen();
}
}
void COleServerItem::OnOpen()
{
ASSERT_VALID(this);
// default implementation shows the document
COleServerDoc* pDoc = GetDocument();
ASSERT(pDoc != NULL);
pDoc->OnShowDocument(TRUE);
}
void COleServerItem::OnHide()
{
ASSERT_VALID(this);
// default implementation hides the document
COleServerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->OnShowDocument(FALSE);
}
BOOL COleServerItem::GetMetafileData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
ASSERT(lpStgMedium->tymed == TYMED_NULL); // GetDataHere not valid
ASSERT(lpStgMedium->pUnkForRelease == NULL);
// medium must be TYMED_MFPICT -- cannot fill in existing HGLOBAL
if (!(lpFormatEtc->tymed & TYMED_MFPICT) || lpStgMedium->hGlobal != NULL)
return FALSE;
// create appropriate memory metafile DC
CMetaFileDC dc;
if (!dc.Create())
return FALSE;
// create attribute DC according to lpFormatEtc->ptd
HDC hAttribDC = _AfxOleCreateDC(lpFormatEtc->ptd);
if (hAttribDC == NULL)
return FALSE;
dc.SetAttribDC(hAttribDC);
// Paint directly into the metafile.
CSize size(0, 0);
BOOL bResult = OnDrawEx(&dc, (DVASPECT)lpFormatEtc->dwAspect, size);
// attribute DC is no longer necessary
dc.SetAttribDC(NULL);
::DeleteDC(hAttribDC);
if (!bResult)
{
#ifdef _DEBUG
if (afxTraceFlags & traceOle)
TRACE0("calling COleServerItem::OnDrawEx()failed.\n");
#endif
return FALSE;
}
HMETAFILE hMF = dc.Close();
if (hMF == NULL)
return FALSE;
HGLOBAL hPict;
if ((hPict =
::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT))) == NULL)
{
DeleteMetaFile(hMF);
return FALSE;
}
LPMETAFILEPICT lpPict;
if ((lpPict = (LPMETAFILEPICT)::GlobalLock(hPict)) == NULL)
{
DeleteMetaFile(hMF);
::GlobalFree(hPict);
return FALSE;
}
// set the metafile size
lpPict->mm = MM_ANISOTROPIC;
lpPict->hMF = hMF;
if (size.cx == 0 && size.cy == 0 &&
!OnGetExtent((DVASPECT)lpFormatEtc->dwAspect, size))
{
TRACE0("Warning: OnGetExtent failed during OnDrawEx --\n");
TRACE0("\tpresentation metafile may be badly formed!\n");
}
lpPict->xExt = size.cx;
lpPict->yExt = size.cy; // HIMETRIC height
if (lpPict->yExt < 0)
{
TRACE0("Warning: HIMETRIC natural size is negative.\n");
lpPict->yExt = -lpPict->yExt; // backward compatibility fix
}
#ifdef _DEBUG
if (lpPict->xExt == 0 || lpPict->yExt == 0)
{
// usually the natural extent is set to something interesting
TRACE0("Warning: COleServerItem has no natural size --\n");
TRACE0("\twill not work with some apps like MS Write.\n");
}
#endif
// return the medium with the hGlobal to the METAFILEPICT
::GlobalUnlock(hPict);
lpStgMedium->hGlobal = hPict;
lpStgMedium->tymed = TYMED_MFPICT;
return TRUE;
}
BOOL COleServerItem::OnSetColorScheme(const LOGPALETTE* /*lpLogPalette*/)
{
ASSERT_VALID(this);
return FALSE; // default does nothing
}
BOOL COleServerItem::OnInitFromData(
COleDataObject* /*pDataObject*/, BOOL /*bCreation*/)
{
ASSERT_VALID(this);
AfxThrowOleException(E_NOTIMPL);
return FALSE;
}
void COleServerItem::CopyToClipboard(BOOL bIncludeLink)
{
ASSERT_VALID(this);
COleDataSource* pDataSource = OnGetClipboardData(bIncludeLink, NULL, NULL);
// put it on the clipboard
pDataSource->SetClipboard();
}
COleDataSource* COleServerItem::OnGetClipboardData(BOOL bIncludeLink,
LPPOINT lpOffset, LPSIZE lpSize)
{
ASSERT_VALID(this);
COleDataSource* pDataSource = new COleDataSource;
TRY
{
GetClipboardData(pDataSource, bIncludeLink, lpOffset, lpSize);
}
CATCH_ALL(e)
{
delete pDataSource;
THROW_LAST();
}
END_CATCH_ALL
ASSERT_VALID(pDataSource);
return pDataSource;
}
DROPEFFECT COleServerItem::DoDragDrop(LPCRECT lpItemRect, CPoint ptOffset,
BOOL bIncludeLink, DWORD dwEffects, LPCRECT lpRectStartDrag)
{
ASSERT(AfxIsValidAddress(lpItemRect, sizeof(RECT)));
ASSERT_VALID(this);
ASSERT_VALID(this);
DROPEFFECT dropEffect = DROPEFFECT_NONE;
COleDataSource *pDataSource = NULL;
TRY
{
// get clipboard data for this item
CSize sizeItem(
lpItemRect->right - lpItemRect->left,
lpItemRect->bottom - lpItemRect->top);
pDataSource = OnGetClipboardData(bIncludeLink, &ptOffset, &sizeItem);
// add DROPEFFECT_LINK if link source is available
LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
pDataSource->GetInterface(&IID_IDataObject);
ASSERT(lpDataObject != NULL);
FORMATETC formatEtc;
formatEtc.cfFormat = (CLIPFORMAT)_oleData.cfLinkSource;
formatEtc.ptd = NULL;
formatEtc.dwAspect = DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.tymed = (DWORD) -1;
if (lpDataObject->QueryGetData(&formatEtc) == S_OK)
dwEffects |= DROPEFFECT_LINK;
// calculate default sensitivity rectangle
CRect rectDrag;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -