Knowledge Base Nr: 00304 oleemb.cpp - http://www.swe-kaiser.de

Downloads:

MFC: VS2005: OLE Objekte (Excel, Word, ...) in View einbinden

  
##############
- projekt anpassen:
- in stdafx.h hinzufügen:
#include <afxole.h>
#include <afxodlgs.h>

- rectitem.h/.cpp in projekt einfügen

- zu stringtable hinzufügen:
IDS_PRIVATE_CF_DESCR "MFC 4.0 Container Object\nan MFC 4.0 Container Object"

- zu accelerator hinzufügen:
ID_CANCEL_INPLACE keine VK_ESCAPE VIRTKEY


############## document h-file anpassen:

- eigene COleClientItem forward klassendeclaration hinzufügen
class CRectItem;
- statt von CDocument von COleLinkingDoc ableiten:
class ClulliDoc : public COleLinkingDoc

public:
virtual void Serialize(CArchive& ar); // overridden for document i/o
virtual void OnShowViews(BOOL bVisible);
static CLIPFORMAT m_cfPrivate;
BOOL m_bNeedUpdate;

public:
CRectItem* CreateItem(); // this document only stores CRectItems
void DeleteItem(CRectItem* pItem);
void AdjustItemPosition(CRectItem* pItem);

protected:
afx_msg void OnEditClearAll();
afx_msg void OnUpdateEditClearAll(CCmdUI* pCmdUI);

############## document cpp-file erweitern:

- #include "rectitem.h"
- CLIPFORMAT ClulliDoc::m_cfPrivate = NULL;

- basisklasse anpassen von CDocument nach COleLinkingDoc
IMPLEMENT_DYNCREATE(CtestDoc, COleLinkingDoc)

BEGIN_MESSAGE_MAP(CtestDoc, COleLinkingDoc)

- messagemap erweitern:
ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateEditClearAll)

ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdatePasteMenu)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_LINK, OnUpdatePasteLinkMenu)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, OnUpdateEditLinksMenu)
ON_COMMAND(ID_OLE_EDIT_LINKS, OnEditLinks)
ON_UPDATE_COMMAND_UI(ID_OLE_VERB_FIRST, OnUpdateObjectVerbMenu)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_CHANGE_ICON, OnUpdateEditChangeIcon)
ON_COMMAND(ID_OLE_EDIT_CHANGE_ICON, OnEditChangeIcon)
END_MESSAGE_MAP()

- konstruktor erweitern:
CtestDoc::CtestDoc()
{
EnableCompoundFile();

m_bNeedUpdate = TRUE;
if (m_cfPrivate == NULL)
m_cfPrivate = (CLIPFORMAT)
::RegisterClipboardFormat(_T("MFC OClient Sample"));
}

- statt auf CDocument auf COleLinkingDoc verweisen:
COleLinkingDoc::AssertValid();
COleLinkingDoc::Dump(dc);

- funktionen hunzufügen:

void CtestDoc::AdjustItemPosition(CRectItem* pItem)
{
POSITION pos = GetStartPosition();
while (pos != NULL)
{
CRectItem* pRectItem = (CRectItem*)GetNextItem(pos);
ASSERT_KINDOF(CRectItem, pItem);
if (pRectItem != pItem && pRectItem->GetRect() == pItem->GetRect())
{
pItem->m_ptPos.x += 10;
pItem->m_ptPos.y -= 10;
pos = GetStartPosition();
}
}
}

CRectItem* CtestDoc::CreateItem()
{
return new CRectItem(this, VT_TEST); // does 'AddItem' automatically
}

// safe delete that notifies views
void CtestDoc::DeleteItem(CRectItem* pItem)
{
ASSERT(pItem->GetDocument() == this);

SetModifiedFlag();
UpdateAllViews(NULL, 1, pItem); // pItem will be deleted
pItem->Delete(); // does a 'RemoveItem' & 'delete this' automatically
}

void CtestDoc::OnShowViews(BOOL bVisible)
{
COleLinkingDoc::OnShowViews(bVisible);

if (bVisible && m_bNeedUpdate)
{
// update embedded links in this document before showing the window
COleUpdateDialog dlg(this);
dlg.DoModal();
m_bNeedUpdate = FALSE;
}
}

void CtestDoc::Serialize(CArchive& ar)
{
// NOTE: New easier to use serialization model -- even for OLE objects!
WORD wMagic = 0x0DAF;
if (ar.IsStoring())
{
if (HasBlankItems() &&
AfxMessageBox(L"IDP_SAVEINCOMPLETE", MB_YESNO|MB_ICONEXCLAMATION) != IDYES)
{
TRACE0("Aborting save -- incomplete items found!\n");
AfxThrowArchiveException(CArchiveException::genericException);
}
ar << wMagic;
}
else
{
WORD w;
ar >> w;

if (w != wMagic)
{
TRACE0("invalid magic number at start of file\n");
AfxThrowArchiveException(CArchiveException::genericException);
}
}

// serialize the rest of the document (OLE items)
COleLinkingDoc::Serialize(ar);
}


void CtestDoc::OnEditClearAll()
{
// delete all items in the document (also removes sub-storages)
POSITION pos = GetStartPosition();
while (pos != NULL)
{
CRectItem* pItem = (CRectItem*)GetNextItem(pos);
ASSERT_KINDOF(CRectItem, pItem);
pItem->Delete();
}

// everything is gone now!
SetModifiedFlag();
UpdateAllViews(NULL);
}


void CtestDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI)
{
// Enable ClearAll if there is anything to clear
pCmdUI->Enable(GetStartPosition() != NULL);
}

############## view.h-file anpassen:

public:
virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL);

protected:
BOOL m_bInDrag;
CRectItem* m_pSelection;
COleDropTarget m_dropTarget;
CPoint m_dragPoint;
CSize m_dragSize;
CSize m_dragOffset;
DROPEFFECT m_prevDropEffect;
static CLIPFORMAT m_cfObjectDescriptor;
static CBrush NEAR m_brHatch;

public:
CRectItem* GetSelection() const { return m_pSelection; } // Just the top-most window
// set bSafeSelect to TRUE when there is a chance that an inplace
// active item could be deactivated before finishing
void SetSelection(CRectItem* pNewSel, BOOL bSafeSelect = FALSE);

// Operations
public:
CRectItem* DoPasteItem(BOOL bLink, COleDataObject* pDataObject,
CPoint* pPoint, CLIPFORMAT cfFormat = 0);
void ClientToDoc(CRect &rc);
void DocToClient(CRect &rc);
void ClientToDoc(CPoint &pt);
void DocToClient(CPoint &pt);
void ClientToDoc(CSize &sz);
void DocToClient(CSize &sz);
void UpdateActiveItem();


// Implementation
protected:

CRectItem* GetHitItem(CPoint point);
BOOL GetObjectInfo(COleDataObject* pDataObject,
CSize* pSize, CSize* pOffset);
void DoPasteNative(COleDataObject* pDataObject, CPoint* pPoint,
CRectItem* pItem);
void DoPasteStandard(BOOL bLink, COleDataObject* pDataObject,
CPoint* pPoint, CRectItem* pItem, CLIPFORMAT cfFormat = 0);

// special scroll handling
virtual BOOL OnScrollBy(CSize sizeScroll, BOOL bDoScroll = TRUE);

// drag drop implementation
virtual BOOL OnDrop(COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point);
virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject,
DWORD grfKeyState, CPoint point);
virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject,
DWORD grfKeyState, CPoint point);
virtual void OnDragLeave();

protected:
// OLE Client support
virtual BOOL IsSelected(const CObject* pDocItem) const;
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
BOOL DoCopySelection();
void SetupTracker(CRectTracker* pTracker, CRectItem* pItem,
CRect* pTrueRect = NULL);
void InvalidateItem(CRectItem* pItem);

protected:
afx_msg void OnPaste();
afx_msg void OnPasteLink();
afx_msg void OnInsertObject();
afx_msg void OnUpdateEditMenu(CCmdUI* pCmdUI);
afx_msg void OnEditClear();
afx_msg void OnEditCopy();
afx_msg void OnEditCut();
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnObjectDisplayContent();
afx_msg void OnUpdateObjectDisplayContent(CCmdUI* pCmdUI);
afx_msg void OnObjectDisplayAsIcon();
afx_msg void OnUpdateObjectDisplayAsIcon(CCmdUI* pCmdUI);
afx_msg void OnPasteSpecial();
afx_msg void OnUpdateEditClone(CCmdUI* pCmdUI);
afx_msg void OnEditClone();
afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);
afx_msg void OnObjectResetsize();
afx_msg void OnCancelInplace();
afx_msg void OnDestroy();
afx_msg void OnUpdateOleEditProperties(CCmdUI* pCmdUI);
afx_msg void OnOleEditProperties();
afx_msg void OnUpdateOleChangeSource(CCmdUI* pCmdUI);
afx_msg void OnOleChangeSource();


############## view.cpp-file anpassen:

ON_COMMAND(ID_ZOOM_ZOOMIN, &CtestView::OnZoomZoomin)
ON_COMMAND(ID_ZOOM_ZOOMOUT, &CtestView::OnZoomZoomout)
ON_COMMAND(ID_EDIT_PASTE, OnPaste)
ON_COMMAND(ID_EDIT_PASTE_LINK, OnPasteLink)
ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateEditMenu)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONDOWN()
ON_WM_SETCURSOR()
ON_WM_RBUTTONDOWN()
ON_WM_CHAR()
ON_WM_SETFOCUS()
ON_WM_CREATE()
ON_WM_SIZE()
ON_COMMAND(ID_OBJECT_DISPLAYCONTENT, OnObjectDisplayContent)
ON_UPDATE_COMMAND_UI(ID_OBJECT_DISPLAYCONTENT, OnUpdateObjectDisplayContent)
ON_COMMAND(ID_OBJECT_DISPLAYASICON, OnObjectDisplayAsIcon)
ON_UPDATE_COMMAND_UI(ID_OBJECT_DISPLAYASICON, OnUpdateObjectDisplayAsIcon)
ON_COMMAND(ID_EDIT_PASTE_SPECIAL, OnPasteSpecial)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLONE, OnUpdateEditClone)
ON_COMMAND(ID_EDIT_CLONE, OnEditClone)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_SPECIAL, OnUpdateEditPaste)
ON_COMMAND(ID_OBJECT_RESETSIZE, OnObjectResetsize)
ON_COMMAND(ID_CANCEL_INPLACE, OnCancelInplace)
ON_WM_DESTROY()
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditMenu)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditMenu)
ON_UPDATE_COMMAND_UI(ID_OBJECT_RESETSIZE, OnUpdateEditMenu)
ON_COMMAND(ID_OLE_CHANGE_SOURCE, OnOleChangeSource)
ON_UPDATE_COMMAND_UI(ID_OLE_CHANGE_SOURCE, OnUpdateOleChangeSource)
ON_COMMAND(ID_OLE_EDIT_PROPERTIES, OnOleEditProperties)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_PROPERTIES, OnUpdateOleEditProperties)
///////////////////////////////////////
///////////////////////////////////////
///////////////////////////////////////

END_MESSAGE_MAP()

// CtestView-Erstellung/Zerstörung

CtestView::CtestView()
{
if (m_brHatch.m_hObject == NULL)
m_brHatch.CreateHatchBrush(HS_DIAGCROSS, RGB(0,0,0));
if (m_cfObjectDescriptor == NULL)
m_cfObjectDescriptor =
(CLIPFORMAT)::RegisterClipboardFormat(_T("Object Descriptor"));

m_pSelection = NULL;
m_prevDropEffect = DROPEFFECT_NONE;
m_bInDrag = FALSE;
}

CtestView::~CtestView()
{
}

BOOL CtestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Ändern Sie hier die Fensterklasse oder die Darstellung, indem Sie
// CREATESTRUCT cs modifizieren.

return CScrollView::PreCreateWindow(cs);
}

void CtestView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();

CSize sizeTotal;
sizeTotal.cx = MAXSIZEX;
sizeTotal.cy = MAXSIZEY;
SetScrollSizes(MM_HIMETRIC, sizeTotal);

fScale = 1.0;
}

// CtestView-Zeichnung

void CtestView::OnDraw(CDC* pDC)
{
CtestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;

//font
CFont cfNew;
LOGFONT lf;
CFont* cfOld;

memset(&lf, 0, sizeof(LOGFONT));
lf.lfHeight = Scale(300);
wcscpy(lf.lfFaceName, CString("Arial"));
cfNew.CreateFontIndirect(&lf);

cfOld = pDC->SelectObject(&cfNew);

//seitengröße beim zoomen anpassen
CSize sizeTotal;
sizeTotal.cx = Scale(MAXSIZEX);
sizeTotal.cy = Scale(MAXSIZEY);
SetScrollSizes(MM_HIMETRIC, sizeTotal); //nicht möglich mit MM_ISOTROPIC!!!

CString str;

int x = 0;
int y = 0;
str.Format(CString("Zoom: %.2f - SetWindowOrg(%d/%d)"), fScale, x, y);
pDC->TextOut(Scale(5000), Scale(-(MAXSIZEY - 1000)),str, str.GetLength());

//pDC->ScaleWindowExt(xNum, xDenom, yNum, yDenom); //keine auswirkung mapping mode MM_LOMETRIC!!!

//SetWindowExtEx() nicht mapping mode MM_LOMETRIC!!!
pDC->SetWindowOrg(Scale(x), Scale(y));

for (int i=0; i<30; i++)
{
x = Scale(i*500);
y = Scale(-MAXSIZEY + i*500);
str.Format(CString("%d/%d test test"), x, y);
pDC->TextOut(x, y,str, str.GetLength());

pDC->MoveTo(0, 0);
pDC->LineTo(x, 0);
pDC->LineTo(x, y);
pDC->LineTo(0, y);
pDC->LineTo(0, 0);

CPen pen;
pen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
CPen* pOldPen = pDC->SelectObject(&pen);
pDC->MoveTo(x-25, y-25);
pDC->LineTo(x+25, y+25);
pDC->MoveTo(x-25, y+25);
pDC->LineTo(x+25, y-25);
pDC->SelectObject(pOldPen);
}

pDC->SelectObject(cfOld);
cfNew.DeleteObject();


// Draw all the CRectItems
POSITION pos = pDoc->GetStartPosition();
while (pos != NULL)
{
CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
if (pItem != NULL)
{
CRect rect = pItem->GetRect();

rect.top = Scale(rect.top);
rect.left = Scale(rect.left);
rect.bottom = Scale(rect.bottom);
rect.right = Scale(rect.right);

pItem->Draw(pDC, rect);

if (!pDC->IsPrinting())
{
// draw the tracker
CRectTracker tracker;
CRect rectTrue;
SetupTracker(&tracker, pItem, &rectTrue);
ClientToDoc(rectTrue);
if (pDC->RectVisible(&rectTrue))
tracker.Draw(pDC);
}
}
}
}


// CtestView drucken

BOOL CtestView::OnPreparePrinting(CPrintInfo* pInfo)
{
// Standardvorbereitung
return DoPreparePrinting(pInfo);
}

void CtestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
fOldScale = fScale;
fScale = 1;
}

void CtestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
fScale = fOldScale;
}


// CtestView-Diagnose

#ifdef _DEBUG
void CtestView::AssertValid() const
{
CScrollView::AssertValid();
}

void CtestView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}

CtestDoc* CtestView::GetDocument() const // Nicht-Debugversion ist inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CtestDoc)));
return (CtestDoc*)m_pDocument;
}
#endif //_DEBUG

//////////////////////
//////////////////////
//////////////////////

void CtestView::OnZoomZoomin()
{
fScale += 0.2f;
if (fScale > 3.0)
fScale = 3.0f;
Invalidate();
UpdateWindow();
RedrawWindow();
}

void CtestView::OnZoomZoomout()
{
fScale -= 0.2f;
if (fScale < 0.2)
fScale = 0.2f;
Invalidate();
UpdateWindow();
RedrawWindow();
}

CBrush NEAR CtestView::m_brHatch;
CLIPFORMAT CtestView::m_cfObjectDescriptor=NULL;

void CtestView::DoPasteNative(
COleDataObject* pDataObject, CPoint* pPoint, CRectItem* pItem)
{
// get file refering to clipboard data
CFile* pFile = pDataObject->GetFileData(CtestDoc::m_cfPrivate);
if (pFile == NULL)
{
// if the file failed to open, throw an exception
// to force cleanup in DoPasteItem. the exact
// type of exception thrown here is unimportant...

AfxThrowFileException(CFileException::genericException);
}

CArchive ar(pFile, CArchive::load);
TRY
{
// connect the file to an archive and read the data
ar.m_pDocument = (CtestDoc*)GetDocument(); // for COleClientItem serialize
pItem->Serialize(ar);
}
CATCH_ALL(e)
{
ar.Close();
delete pFile;
THROW_LAST();
}
END_CATCH_ALL

ar.Close();
delete pFile;

// adjust position to that specified by point
if (pPoint != NULL)
pItem->m_ptPos = *pPoint;
}

void CtestView::DoPasteStandard(BOOL bLink, COleDataObject* pDataObject,
CPoint* pPoint, CRectItem* pItem, CLIPFORMAT cfFormat)
{
if (bLink) // paste link
{
if (!pItem->CreateLinkFromData(pDataObject))
AfxThrowMemoryException(); // any exception will do
}
// paste embedded
else if (!pItem->CreateFromData(pDataObject) &&
!pItem->CreateStaticFromData(pDataObject, OLERENDER_DRAW, cfFormat))
{
AfxThrowMemoryException(); // any exception will do
}

// copy the current iconic representation
FORMATETC fmtetc;
fmtetc.cfFormat = CF_METAFILEPICT;
fmtetc.dwAspect = DVASPECT_ICON;
fmtetc.ptd = NULL;
fmtetc.tymed = TYMED_MFPICT;
fmtetc.lindex = 1;
HGLOBAL hObj = pDataObject->GetGlobalData(CF_METAFILEPICT, &fmtetc);
if (hObj != NULL)
{
pItem->SetIconicMetafile(hObj);
// the following code is an easy way to free a metafile pict
STGMEDIUM stgMed;
memset(&stgMed, 0, sizeof(stgMed));
stgMed.tymed = TYMED_MFPICT;
stgMed.hGlobal = hObj;
ReleaseStgMedium(&stgMed);
}

// set the current drawing aspect
hObj = pDataObject->GetGlobalData(m_cfObjectDescriptor);
if (hObj != NULL)
{
ASSERT(hObj != NULL);
// got CF_OBJECTDESCRIPTOR ok. Lock it down and extract size.
LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObj);
ENSURE(pObjDesc != NULL);
pItem->SetDrawAspect((DVASPECT)pObjDesc->dwDrawAspect);
GlobalUnlock(hObj);
GlobalFree(hObj);
}

// set top-left based on point of drop
if (pPoint != NULL)
pItem->m_ptPos = *pPoint;

// get size from drag/drop operation
CSize size;
if (GetObjectInfo(pDataObject, &size, NULL) && size.cx != 0 && size.cy != 0)
{
// use size obtained from object instead of default
size.cx = MulDiv(size.cx, 10, 254);
size.cy = -MulDiv(size.cy, 10, 254);
pItem->SetSize(size);
CSize sizeExtent;
pItem->GetCachedExtent(&sizeExtent);
pItem->SetBaseSize(sizeExtent);
}
else
{
// no extent from CF_OBJECTDESCRIPTOR, use extent from object
pItem->UpdateExtent();
}
}

void CtestView::SetupTracker(CRectTracker* pTracker, CRectItem* pItem,
CRect* pTrueRect)
{
ENSURE(pTracker != NULL);
ENSURE(pItem != NULL);

pTracker->m_rect = pItem->GetRect();
pTracker->m_rect.top = Scale(pTracker->m_rect.top);
pTracker->m_rect.left = Scale(pTracker->m_rect.left);
pTracker->m_rect.bottom = Scale(pTracker->m_rect.bottom);
pTracker->m_rect.right = Scale(pTracker->m_rect.right);

DocToClient(pTracker->m_rect);

// set minimum size for our OLE items
pTracker->m_sizeMin.cx = 8;
pTracker->m_sizeMin.cy = 8;

pTracker->m_nStyle = 0;

// setup resize handles if item is selected
if (pItem == m_pSelection)
pTracker->m_nStyle |= CRectTracker::resizeInside;

// put correct border depending on item type
if (pItem->GetType() == OT_LINK)
pTracker->m_nStyle |= CRectTracker::dottedLine;
else
pTracker->m_nStyle |= CRectTracker::solidLine;

// put hatching over the item if it is currently open
if (pItem->GetItemState() == COleClientItem::openState ||
pItem->GetItemState() == COleClientItem::activeUIState)
{
pTracker->m_nStyle |= CRectTracker::hatchInside;
}

if (pTrueRect != NULL)
pTracker->GetTrueRect(pTrueRect);
}

void CtestView::OnObjectDisplayContent()
{
if (m_pSelection == NULL)
return;
ASSERT_VALID(m_pSelection);
m_pSelection->Invalidate();
m_pSelection->SetDrawAspect(DVASPECT_CONTENT);
m_pSelection->UpdateExtent();
m_pSelection->Invalidate();
}

void CtestView::OnUpdateObjectDisplayContent(CCmdUI* pCmdUI)
{
if (m_pSelection == NULL)
{
pCmdUI->Enable(FALSE);
return;
}
ASSERT_VALID(m_pSelection);
pCmdUI->SetCheck(m_pSelection->GetDrawAspect() == DVASPECT_CONTENT);
pCmdUI->Enable(TRUE);
}

void CtestView::OnObjectDisplayAsIcon()
{
if (m_pSelection == NULL)
return;
ASSERT_VALID(m_pSelection);
m_pSelection->Invalidate();
m_pSelection->SetDrawAspect(DVASPECT_ICON);
m_pSelection->UpdateExtent();
m_pSelection->Invalidate();
}

void CtestView::OnUpdateObjectDisplayAsIcon(CCmdUI* pCmdUI)
{
if (m_pSelection == NULL)
{
pCmdUI->Enable(FALSE);
return;
}
ASSERT_VALID(m_pSelection);
pCmdUI->SetCheck(m_pSelection->GetDrawAspect() == DVASPECT_ICON);
pCmdUI->Enable(TRUE);
}

void CtestView::UpdateActiveItem()
{
// when there is an active item visible, sizing the window may cause
// more/less of the in-place object to become visible.
// (ie. the clipping rectangle changes with the size of the window)
// a container supporting scrolling would also have to do this
// when scrolling the contents of the window.

COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL &&
pActiveItem->GetItemState() == COleClientItem::activeUIState &&
pActiveItem->GetActiveView() == this)
{
// this will update the item rectangles by calling
// OnGetPosRect & OnGetClipRect.
pActiveItem->SetItemRects();
}
}

void CtestView::OnUpdateEditClone(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelection != NULL);
}


void CtestView::OnEditCut()
{
ENSURE(m_pSelection != NULL);
TRY
{
m_pSelection->CopyToClipboard(TRUE);
OnEditClear();
}
CATCH_ALL(e)
{
AfxMessageBox(L"IDP_CLIPBOARD_CUT_FAILED");
}
END_CATCH_ALL
}

void CtestView::OnEditCopy()
{
ENSURE(m_pSelection != NULL);
TRY
{
m_pSelection->CopyToClipboard(TRUE);
}
CATCH_ALL(e)
{
AfxMessageBox(L"IDP_CLIPBOARD_COPY_FAILED");
}
END_CATCH_ALL
}


void CtestView::OnEditClone()
{
if (m_pSelection == NULL)
return;

BeginWaitCursor();

CRectItem* pItem = NULL;
TRY
{
// create item from dialog results
pItem = GetDocument()->CreateItem();
if (!pItem->CreateCloneFrom(m_pSelection))
AfxThrowMemoryException(); // any exception will do

// offset it so we can see the clone easier
CRect rect(20, 20, 0, 0);
ClientToDoc(rect);
pItem->m_ptPos.x += rect.left;
pItem->m_ptPos.y += rect.top;
ASSERT_VALID(pItem);
}
CATCH_ALL(e)
{
// cleanup item, if allocated
if (pItem != NULL)
GetDocument()->DeleteItem(pItem);

AfxMessageBox(L"IDP_FAILED_TO_CREATE");
}
END_CATCH_ALL

EndWaitCursor();
}

void CtestView::OnPasteSpecial()
{
COlePasteSpecialDialog dlg;
dlg.AddFormat(CtestDoc::m_cfPrivate, TYMED_HGLOBAL,
IDS_PRIVATE_CF_DESCR, FALSE, FALSE);
dlg.AddStandardFormats();
if (dlg.DoModal() != IDOK)
return;

CRectItem* pItem = NULL;
TRY
{
// Get the clipboard format of the selected
CLIPFORMAT cf = dlg.m_ps.arrPasteEntries[dlg.m_ps.nSelectedIndex].fmtetc.cfFormat;
if (cf == CtestDoc::m_cfPrivate)
{
BOOL bLink = dlg.GetSelectionType() ==
COlePasteSpecialDialog::pasteLink;
COleDataObject dataObject;
dataObject.Attach(dlg.m_ps.lpSrcDataObj, FALSE);
pItem = DoPasteItem(bLink, &dataObject, NULL, cf);

// try to get initial presentation data
pItem->UpdateLink();
}
else
{
pItem = GetDocument()->CreateItem();
if (!dlg.CreateItem(pItem))
{
TRACE0("Warning: paste special failed to create item.\n");
AfxThrowMemoryException();
}

// try to get initial presentation data
pItem->UpdateLink();

// try to get initial extent
pItem->UpdateExtent();

// allow document to offset item to avoid direct superimposition
GetDocument()->AdjustItemPosition(pItem);

// set the selection with bSafeSelect = TRUE
SetSelection(pItem, TRUE);
GetDocument()->SetModifiedFlag();
GetDocument()->UpdateAllViews(NULL, 0, pItem);
}
}
CATCH_ALL(e)
{
// cleanup item, if allocated
if (pItem != NULL)
GetDocument()->DeleteItem(pItem);
AfxMessageBox(L"IDP_FAILED_TO_CREATE");
return;
}
END_CATCH_ALL
}

void CtestView::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
// determine if private or standard OLE formats are on the clipboard
COleDataObject dataObj;
BOOL bEnable = dataObj.AttachClipboard() &&
(dataObj.IsDataAvailable(CtestDoc::m_cfPrivate) ||
COleClientItem::CanCreateFromData(&dataObj));

// enable command based on availability
pCmdUI->Enable(bEnable);
}


void CtestView::OnOleChangeSource()
{
ASSERT(m_pSelection != NULL && m_pSelection->GetType() == OT_LINK);

COleChangeSourceDialog dlg(m_pSelection);
dlg.DoModal();
}


void CtestView::OnOleEditProperties()
{
ASSERT(m_pSelection != NULL);

//todo: ???
//COlePropertiesEx dlg(m_pSelection);
//dlg.DoModal();
}

void CtestView::OnObjectResetsize()
{
ENSURE(m_pSelection != NULL);
m_pSelection->ResetSize();
}

void CtestView::OnCancelInplace()
{
// deactivate the inplace active item on this frame/view
COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL)
pActiveItem->Deactivate();
ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}


BOOL CtestView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll)
{
// remove drag/drop feedback before scrolling
if (bDoScroll && m_prevDropEffect != DROPEFFECT_NONE)
{
CClientDC dc(this);
dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
// erase previous focus rect
m_prevDropEffect = DROPEFFECT_NONE;
}

// do the scroll
if (!CScrollView::OnScrollBy(sizeScroll, bDoScroll))
return FALSE;

// update the position of any in-place active item
if (bDoScroll)
{
UpdateActiveItem();
UpdateWindow();
}

return TRUE;
}

void CtestView::OnEditClear()
{
if (m_pSelection != NULL)
GetDocument()->DeleteItem(m_pSelection);
}

BOOL CtestView::OnDrop(COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point)
{
ASSERT_VALID(this);

// clean up focus rect
OnDragLeave();

// offset point as appropriate for dragging
GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
//m_dragSize = CSize(Scale(m_dragSize.cx), Scale(m_dragSize.cy));
//m_dragOffset = CSize(Scale(m_dragOffset.cx), Scale(m_dragOffset.cy));

CClientDC dc(NULL);
dc.HIMETRICtoDP(&m_dragSize);
dc.HIMETRICtoDP(&m_dragOffset);
m_dragSize = CSize(Scale(m_dragSize.cx), Scale(m_dragSize.cy));
point -= m_dragOffset;
m_dragOffset = CSize(Scale(m_dragOffset.cx), Scale(m_dragOffset.cy));

// if move within the view
ClientToDoc(point);
if ((dropEffect & DROPEFFECT_MOVE) && m_bInDrag)
{
ASSERT(m_pSelection != NULL);
m_bInDrag = FALSE; // signal drag code that a move happened
// set top-left based on point of drop
CRect rect = m_pSelection->GetRect();
if (rect.TopLeft() != point) // if moved
{
CRect cr(point,rect.Size());
m_pSelection->Move(cr);
GetDocument()->SetModifiedFlag();
}
}
// check and paste link
else if ((dropEffect & DROPEFFECT_LINK) && DoPasteItem(TRUE, pDataObject, &point))
return TRUE;

// paste embedding/static
else if (DoPasteItem(FALSE, pDataObject, &point))
return TRUE;

return FALSE;
}

BOOL CtestView::GetObjectInfo(COleDataObject* pDataObject,
CSize* pSize, CSize* pOffset)
{
ENSURE(pSize != NULL);

// get object descriptor data
HGLOBAL hObjDesc = pDataObject->GetGlobalData(m_cfObjectDescriptor);
if (hObjDesc == NULL)
{
if (pOffset != NULL)
*pOffset = CSize(0, 0); // fill in defaults instead
*pSize = CSize(0, 0);
return FALSE;
}
ASSERT(hObjDesc != NULL);

// otherwise, got CF_OBJECTDESCRIPTOR ok. Lock it down and extract size.
LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObjDesc);
ENSURE(pObjDesc != NULL);
pSize->cx = (int)pObjDesc->sizel.cx;
pSize->cy = (int)pObjDesc->sizel.cy;
if (pOffset != NULL)
{
pOffset->cx = (int)pObjDesc->pointl.x;
pOffset->cy = (int)pObjDesc->pointl.y;
}
GlobalUnlock(hObjDesc);
GlobalFree(hObjDesc);

// successfully retrieved pSize & pOffset info
return TRUE;
}

DROPEFFECT CtestView::OnDragEnter(COleDataObject* pDataObject,
DWORD grfKeyState, CPoint point)
{
ASSERT(m_prevDropEffect == DROPEFFECT_NONE);

GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);

CPoint po = GetScrollPosition();

//todo: korrektur nicht optimal
CSize si = CSize(BackScale(po.x), BackScale(po.y));
m_dragOffset += si;

m_dragSize = CSize(Scale(m_dragSize.cx), Scale(m_dragSize.cy));
m_dragOffset = CSize(Scale(m_dragOffset.cx), Scale(m_dragOffset.cy));

CClientDC dc(NULL);
dc.HIMETRICtoDP(&m_dragSize);
dc.HIMETRICtoDP(&m_dragOffset);

return OnDragOver(pDataObject, grfKeyState, point);
}

DROPEFFECT CtestView::OnDragOver(COleDataObject*,
DWORD grfKeyState, CPoint point)
{
point = CPoint(Scale(point.x), Scale(point.y));
point -= m_dragOffset; // adjust target rect by original cursor offset

// check for point outside logical area -- i.e. in hatched region
// GetTotalSize() returns the size passed to SetScrollSizes
CRect rectScroll(CPoint(0, 0), GetTotalSize());

CRect rectItem(point,m_dragSize);
if (rectItem.IsRectEmpty())
{
// some apps might have a null size in the object descriptor...
rectItem.InflateRect(1,1);
}
rectItem.OffsetRect(GetDeviceScrollPosition());

DROPEFFECT de = DROPEFFECT_NONE;
CRect rectTemp;
if (rectTemp.IntersectRect(rectScroll, rectItem))
{
// check for force link
if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
de = DROPEFFECT_LINK;
// check for force copy
else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
de = DROPEFFECT_COPY;
// check for force move
else if ((grfKeyState & MK_ALT) == MK_ALT)
de = DROPEFFECT_MOVE;
// default -- recommended action is move
else
de = DROPEFFECT_MOVE;
}

if (point == m_dragPoint)
return de;

// otherwise, cursor has moved -- need to update the drag feedback
CClientDC dc(this);
if (m_prevDropEffect != DROPEFFECT_NONE)
{
// erase previous focus rect
//m_dragPoint = CPoint(Scale(m_dragPoint.x), Scale(m_dragPoint.y));
dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
}
m_prevDropEffect = de;
if (m_prevDropEffect != DROPEFFECT_NONE)
{
//point = CPoint(Scale(point.x), Scale(point.y));
m_dragPoint = point;
//point = CPoint(Scale(point.x), Scale(point.y));
dc.DrawFocusRect(CRect(point, m_dragSize));
}
return de;
}

void CtestView::OnDragLeave()
{
CClientDC dc(this);
if (m_prevDropEffect != DROPEFFECT_NONE)
{
dc.DrawFocusRect(CRect(m_dragPoint,m_dragSize)); // erase previous focus rect
m_prevDropEffect = DROPEFFECT_NONE;
}
}


BOOL CtestView::IsSelected(const CObject* pDocItem) const
{
return (pDocItem == m_pSelection);
}

void CtestView::SetSelection(CRectItem* pNewSel, BOOL bSafeSelect)
{
if (pNewSel != NULL && pNewSel == m_pSelection)
return;

// deactivate any in-place active item on this view!
CRectItem* pActiveItem = (CRectItem*)GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL && pNewSel != pActiveItem)
{
if (bSafeSelect)
return;
// if we found one, deactivate it
pActiveItem->Close();
ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}
if (m_pSelection != NULL) // invalidate the old item
InvalidateItem(m_pSelection);
if ((m_pSelection = pNewSel) != NULL) // invalidate the new item
InvalidateItem(m_pSelection);
}


// pHint is the deleted item or NULL if deselect/delete all
void CtestView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
if (pHint == NULL && lHint == 0)
{
// some sort of clear all
m_pSelection = NULL;
}

if (pHint != NULL && pHint->IsKindOf(RUNTIME_CLASS(CRectItem)))
{
// just invalidate the one item
InvalidateItem((CRectItem*)pHint);

// clear selection if pointing to deleted item
if (lHint == 1 && pHint == m_pSelection)
{
// specific case of pHint being deleted
m_pSelection = NULL;
}
}
else if (lHint != 0)
{
// invalidate arbitrary rectangle
InvalidateRect((CRect*)lHint);
}
else
{
// complete update
CScrollView::OnUpdate(pSender, lHint, pHint);
}
}

void CtestView::InvalidateItem(CRectItem* pItem)
{
if (m_nMapMode != 0)
{
CRectTracker tracker;
CRect rect;
SetupTracker(&tracker, pItem, &rect);
InvalidateRect(&rect);
}
}

CRectItem* CtestView::GetHitItem(CPoint point)
{
CtestDoc* pDoc = GetDocument();
CRectItem* pItemHit = NULL;

// Find the item hit by the mouse
POSITION pos = pDoc->GetStartPosition();
while (pos != NULL)
{
CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
if (pItem != NULL)
{
CRectTracker tracker;
SetupTracker(&tracker, pItem);
if (tracker.HitTest(point) >= 0)
{
pItemHit = pItem;
// items later in the list are drawn on top - so keep looking
}
}
}
return pItemHit;
}

void CtestView::DocToClient(CRect& rect)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.LPtoDP(&rect); // convert logical rect to device rect
rect.NormalizeRect();
}

void CtestView::ClientToDoc(CRect& rect)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&rect); // convert device rect to logical rect
}

void CtestView::DocToClient(CSize& size)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.LPtoDP(&size); // convert logical size to device size
size.cx = abs(size.cx);
size.cy = abs(size.cy);
}

void CtestView::ClientToDoc(CSize& size)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&size); // convert device rect to logical rect
size.cx = abs(size.cx);
size.cy = abs(size.cy);
}

void CtestView::DocToClient(CPoint& point)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.LPtoDP(&point); // convert logical point to device point
}

void CtestView::ClientToDoc(CPoint& point)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point); // convert device point to logical point
}


void CtestView::OnLButtonDblClk(UINT, CPoint)
{
// Double click will activate the main verb
if (m_pSelection != NULL)
{
BeginWaitCursor();
LONG iVerb = OLEIVERB_PRIMARY;
if (GetKeyState(VK_CONTROL) < 0)
iVerb = OLEIVERB_OPEN;
m_pSelection->DoVerb(iVerb, this);
EndWaitCursor();
}
}


void CtestView::OnInsertObject()
{
COleInsertDialog dlg;
if (dlg.DoModal() != IDOK)
return;

BeginWaitCursor();

CRectItem* pItem = NULL;
TRY
{
// create item from dialog results
pItem = GetDocument()->CreateItem();
if (!dlg.CreateItem(pItem))
AfxThrowMemoryException(); // any exception will do

// try to get initial presentation data
pItem->UpdateLink();
pItem->UpdateExtent();

// if insert new object -- initially show the object
if (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
pItem->DoVerb(OLEIVERB_SHOW, this);

SetSelection(pItem);
}
CATCH_ALL(e)
{
// cleanup item, if allocated
if (pItem != NULL)
GetDocument()->DeleteItem(pItem);

AfxMessageBox(L"IDP_FAILED_TO_CREATE");
}
END_CATCH_ALL

EndWaitCursor();
}

void CtestView::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
CRectItem* pItemHit = GetHitItem(point);
SetSelection(pItemHit);
if (pItemHit == NULL)
return;

CRect rectLimit;
GetClientRect(rectLimit);

CRectTracker tracker;
SetupTracker(&tracker, pItemHit);

UpdateWindow(); // update before entering the tracker
if (tracker.HitTest(point) == CRectTracker::hitMiddle) // moving, not sizing
{
// determine mouse position offset from the item itself
CRect rect = pItemHit->GetRect();
DocToClient(rect);
CPoint ptOffset(point.x - rect.left, point.y - rect.top);

// determine sensitivity rectangle (determines when drag starts)
CRect rectDrag(rect.left, rect.top, rect.left+1, rect.top+1);

// execute the drag/drop operation
m_bInDrag = TRUE;
ClientToScreen(&rect); // must be in screen co-ordinates
ClientToScreen(&rectDrag);
DROPEFFECT dropEffect = pItemHit->DoDragDrop(rect, ptOffset,
TRUE, DROPEFFECT_COPY|DROPEFFECT_MOVE, &rectDrag);
if (m_bInDrag == FALSE) // move in same window
return;
m_bInDrag = FALSE;

if (dropEffect == DROPEFFECT_MOVE)
{
// the item was moved (essentially a copy w/delete)
pItemHit->Invalidate();
if (m_pSelection == pItemHit)
m_pSelection = NULL;
GetDocument()->DeleteItem(pItemHit);
}
}
else if (tracker.Track(this, point))
{
ClientToDoc(tracker.m_rect);
pItemHit->Move(tracker.m_rect);
GetDocument()->SetModifiedFlag();
}
}

BOOL CtestView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (pWnd == this && m_pSelection != NULL)
{
// give the tracker for the selection a chance
CRectTracker tracker;
SetupTracker(&tracker, m_pSelection);
BOOL ok = tracker.SetCursor(this, nHitTest);
if (ok)
{
::SetCursor(::LoadCursor(NULL, IDC_HAND));
return TRUE;
}
}
return CScrollView::OnSetCursor(pWnd, nHitTest, message);
}

void CtestView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
// set up a reasonable default context
pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));

pDC->SetMapMode(MM_HIMETRIC);
}

/////////////////////////////////////////////////////////////////////////////
// Right mouse for popup context sensitive menu

void CtestView::OnRButtonDown(UINT, CPoint point)
{
// make sure window is active
GetParentFrame()->ActivateFrame();

SetSelection(GetHitItem(point)); // reselect item if appropriate
UpdateWindow();

if (m_pSelection != NULL)
{
CMenu bar;
if (bar.LoadMenu(ID_OBJECT_POPUP_MENU))
{
CMenu& popup = *bar.GetSubMenu(0);
ASSERT(popup.m_hMenu != NULL);

ClientToScreen(&point);
popup.TrackPopupMenu(TPM_RIGHTBUTTON,
point.x, point.y,
AfxGetMainWnd()); // route commands through main window
}
}
}


int CtestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;

// register drop target
m_dropTarget.Register(this);

return 0;
}


void CtestView::OnDestroy()
{
CScrollView::OnDestroy();

// deactivate the inplace active item on this view
COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
{
pActiveItem->Deactivate();
ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}
}

void CtestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
MessageBeep(0); // to test for proper focus transfer

CScrollView::OnChar(nChar, nRepCnt, nFlags);
}

void CtestView::OnSetFocus(CWnd* pOldWnd)
{
COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL &&
pActiveItem->GetItemState() == COleClientItem::activeUIState)
{
// need to set focus to this item if it is in the same view
CWnd* pWnd = pActiveItem->GetInPlaceWindow();
if (pWnd != NULL)
{
pWnd->SetFocus();
return;
}
}

CScrollView::OnSetFocus(pOldWnd);
}

void CtestView::OnSize(UINT nType, int cx, int cy)
{
CScrollView::OnSize(nType, cx, cy);

UpdateActiveItem();
}

// Helper for paste/pastelink
//
// bLink pDataObject pPoint cfFormat
// EditPaste FALSE NULL(clipboard) NULL(default) 0
// Drag/Drop TRUE/FALSE X X 0
// PasteLink TRUE NULL(clipboard) NULL(default) 0
// PasteSpecial TRUE/FALSE X NULL(default) X
CRectItem* CtestView::DoPasteItem(BOOL bLink, COleDataObject* pDataObject,
CPoint* pPoint, CLIPFORMAT cfFormat)
{
BeginWaitCursor();

CRectItem* pItem = GetDocument()->CreateItem();
ASSERT_VALID(pItem);
BOOL bAllowAdjust = (pPoint == NULL) ? TRUE : FALSE;

// use clipboard data if not doing drag/drop
COleDataObject clipboardData;
if (pDataObject == NULL)
{
clipboardData.AttachClipboard();
pDataObject = &clipboardData;
}

TRY
{
if (cfFormat == CtestDoc::m_cfPrivate)
{
// if format specified (i.e. PasteSpecial) then use that one
DoPasteNative(pDataObject, pPoint, pItem);
}
else if (!bLink && cfFormat == 0 &&
pDataObject->IsDataAvailable(CtestDoc::m_cfPrivate))
{
// if we're not pasting a link, cfFormat was unspecified,
// and private format is available use it
DoPasteNative(pDataObject, pPoint, pItem);
}
// otherwise perform a standard paste
else if (bAllowAdjust)
{
CPoint ptDef(10, -10);
DoPasteStandard(bLink, pDataObject, &ptDef, pItem, cfFormat);
}
else
{
DoPasteStandard(bLink, pDataObject, pPoint, pItem, cfFormat);
}

if (bAllowAdjust)
{
// allow document to adjust position of item so that it doesn't
// lay directly over an item of the same size
// this only occurs if the drop point is not specified
GetDocument()->AdjustItemPosition(pItem);
}
}
CATCH_ALL(e)
{
// general cleanup
TRACE0("failed to embed/link an OLE object\n");
pItem->Delete();
pItem = NULL;
}
END_CATCH_ALL

// set the selection with bSafeSelect = TRUE
SetSelection(pItem, TRUE);

// update the document and views
GetDocument()->SetModifiedFlag();
GetDocument()->UpdateAllViews(NULL, 0, pItem); // including this view

EndWaitCursor();

return pItem;
}


void CtestView::OnUpdateOleEditProperties(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelection != NULL);
}

void CtestView::OnUpdateOleChangeSource(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelection != NULL && m_pSelection->GetType() == OT_LINK);
}

void CtestView::OnPaste()
{
if (DoPasteItem(FALSE, NULL, NULL) == NULL)
AfxMessageBox(L"IDP_GET_FROM_CLIPBOARD_FAILED");
}


void CtestView::OnPasteLink()
{
if (DoPasteItem(TRUE, NULL, NULL) == NULL)
AfxMessageBox(L"IDP_GET_FROM_CLIPBOARD_FAILED");
}

void CtestView::OnUpdateEditMenu(CCmdUI* pCmdUI)
{
// most Edit menu commands are enabled only if we have a selection
// and there are no in-place activations for this view
pCmdUI->Enable(m_pSelection != NULL &&
GetDocument()->GetInPlaceActiveItem(this) == NULL);
}