//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This source code is a part of Tangram library.
// You may use, compile or redistribute it as part of your application
// for free. You cannot redistribute it as a part of a software development
// library without the agreement of the author. If the sources are
// distributed along with the application, you should leave the original
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES on your own risk.
//
// For the latest updates to this library, check site:
// http://www.tangramdev.com
//
// sunhui
//*******************************************************************************
// TangramCntrItem.cpp : implementation file
//
#include "stdafx.h"
#include "tangramDoc.h"
#include "TangramServerObj.h"
#include "TangramCntrItem.h"
#include <afxdocob.h>
#include <afxpriv.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CTangramServerObj* g_pTangramServer;
//extern CFrameWnd* m_pMainWnd;
/////////////////////////////////////////////////////////////////////////////
// CTangramCntrItem
IMPLEMENT_SERIAL(CTangramCntrItem, COleClientItem, 0)
BEGIN_INTERFACE_MAP(CTangramCntrItem, COleClientItem)
INTERFACE_PART(CTangramCntrItem, IID_IOleInPlaceSite, OleIPSiteEx)
END_INTERFACE_MAP()
CTangramCntrItem::CTangramCntrItem(COleDocument* pContainer)
: COleClientItem(pContainer)
{
bDesignMode = false;
bSetMenu=false;
bShow = FALSE;
m_pDoc=NULL;
m_pTangramObject = NULL;
m_pTangramObj = NULL;
//m_strObjID = _T("");
m_strObjName = _T("");
nDockingIndex = -1;
m_hWndServer = 0;
m_hParentWnd = 0;
m_pMfcView = NULL;
bDocument=FALSE;
//bWinCtrl = false;
//bAxFrameItem = FALSE;
if(pContainer&&pContainer->IsKindOf(RUNTIME_CLASS(CTangramDoc)))
{
m_pDoc = (CTangramDoc*)pContainer;
}
EnableAutomation();
}
CTangramCntrItem::~CTangramCntrItem()
{
m_pView = NULL;
m_pMfcView = NULL;
}
BOOL CTangramCntrItem::OnDraw(CDC* pDC, CSize& rSize)
{
// Called by the framework to render the OLE item into a metafile.
// The metafile representation of the OLE item is used to display the
// item in the container application. If the container application was
// written with the Microsoft Foundation Class Library, the metafile is
// used by the Draw member function of the corresponding COleClientItem object.
// There is no default implementation. You must override this function to draw
// the item into the device context specified.
ASSERT(FALSE); // remove this after completing the TODO
return TRUE;
}
BEGIN_MESSAGE_MAP(CTangramCntrItem, COleClientItem)
//{{AFX_MSG_MAP(CTangramCntrItem)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTangramCntrItem diagnostics
#ifdef _DEBUG
void CTangramCntrItem::AssertValid() const
{
COleClientItem::AssertValid();
}
void CTangramCntrItem::Dump(CDumpContext& dc) const
{
COleClientItem::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTangramCntrItem serialization
void CTangramCntrItem::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
if (ar.IsStoring())
{
COleDocument* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//if(pDoc->IsKindOf(RUNTIME_CLASS(CDesignerDoc))&&m_lpStorage == NULL)pDoc->OnNewDocument();
LPPERSISTSTORAGE lpPersistStorage = NULL;
HRESULT hr = m_lpObject->QueryInterface(IID_IPersistStorage, (void**) &lpPersistStorage);
ASSERT(FAILED(hr) || lpPersistStorage != NULL);
if (SUCCEEDED(hr) && ((/*ApcGetSameAsLoad(pDoc) && */lpPersistStorage->IsDirty() == S_FALSE) && (!ar.m_bForceFlat)))
{
// call OleSave now and IPersistStorage::SaveCompleted later
hr = ::OleSave(lpPersistStorage, m_lpStorage, true);
if (FAILED(hr)) {
AfxThrowOleException(hr);
}
}
lpPersistStorage->Release();
}
if (ar.IsStoring())
{
ar << m_strObjName;
ar << bDocument;
//
// WORKAROUND: MFC is not calling the initial OleSave if the IPersistStorage
// is not dirty. This results in an error further downstrean when
// IPersistStorage::SaveCompleted is called. <OLECLI1.cpp>
//
// save dirty object
// determine destination storage
}
else
{
ar >> m_strObjName;
ar >> bDocument;
}
COleClientItem::Serialize(ar);
}
/////////////////////////////////////////////////////////////////////////////
// CTangramCntrItem::XOleIPSiteEx implementation
STDMETHODIMP_(ULONG) CTangramCntrItem::XOleIPSiteEx::AddRef()
{
METHOD_PROLOGUE_EX_(CTangramCntrItem, OleIPSiteEx)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CTangramCntrItem::XOleIPSiteEx::Release()
{
//AfxMessageBox("CTangramCntrItem::XOleIPSiteEx::Release()");
METHOD_PROLOGUE_EX_(CTangramCntrItem, OleIPSiteEx)
return pThis->ExternalRelease();
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(CTangramCntrItem, OleIPSiteEx)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::GetWindow(HWND* lphwnd)
{
METHOD_PROLOGUE_EX_(CTangramCntrItem, OleIPSiteEx)
*lphwnd = pThis->m_hParentWnd;
return *lphwnd != NULL ? S_OK : E_FAIL;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::ContextSensitiveHelp(
BOOL fEnterMode)
{
METHOD_PROLOGUE_EX_(CTangramCntrItem, OleIPSiteEx)
if (pThis->m_pInPlaceFrame == NULL)
return E_UNEXPECTED;
// simply delegate to frame window implementation
return pThis->m_pInPlaceFrame->
m_xOleInPlaceFrame.ContextSensitiveHelp(fEnterMode);
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::CanInPlaceActivate()
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
return pThis->CanActivate() ? S_OK : S_FALSE;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::OnInPlaceActivate()
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnActivate();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::OnUIActivate()
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnActivateUI();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::GetWindowContext(
LPOLEINPLACEFRAME* lplpFrame,
LPOLEINPLACEUIWINDOW* lplpDoc,
LPRECT lpPosRect, LPRECT lpClipRect,
LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
*lplpFrame = NULL; // init these in-case of mem-alloc failure
*lplpDoc = NULL;
CFrameWnd* pMainFrame = NULL;
CFrameWnd* pDocFrame = NULL;
SCODE sc = E_UNEXPECTED;
TRY
{
// get position of the item relative to activation view
CRect rect;
pThis->OnGetItemPosition(rect);
::CopyRect(lpPosRect, &rect);
pThis->OnGetClipRect(rect);
::CopyRect(lpClipRect, &rect);
// get the window context information
pThis->m_pView = pThis->m_pMfcView;
if (pThis->OnGetWindowContext(&pMainFrame, &pDocFrame, lpFrameInfo))
{
// hook IOleInPlaceFrame interface to pMainFrame COleFrameHook
if (pThis->m_pInPlaceFrame == NULL)
{
pThis->m_pInPlaceFrame = new CAXDocContFrameHook(pMainFrame, pThis);
//pThis->m_pInPlaceFrame->m_pActiveItem = this;
}
pThis->m_pInPlaceFrame->InternalAddRef();
*lplpFrame = (LPOLEINPLACEFRAME)pThis->m_pInPlaceFrame->
GetInterface(&IID_IOleInPlaceFrame);
// save accel table for IOleInPlaceFrame::TranslateAccelerators
pThis->m_pInPlaceFrame->m_hAccelTable = lpFrameInfo->haccel;
// hook IOleInPlaceUIWindow to pDocFrame
if (pDocFrame != NULL)
{
if (pThis->m_pInPlaceDoc == NULL)
pThis->m_pInPlaceDoc = new CAXDocContFrameHook(pDocFrame, pThis);
pThis->m_pInPlaceDoc->InternalAddRef();
*lplpDoc = (LPOLEINPLACEUIWINDOW)pThis->m_pInPlaceDoc->
GetInterface(&IID_IOleInPlaceUIWindow);
}
sc = S_OK;
}
}
CATCH_ALL(e)
{
// cleanup memory that may be partially allocated
delete *lplpFrame;
ASSERT(*lplpDoc == NULL);
e->Delete();
}
END_CATCH_ALL
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::Scroll(SIZE scrollExtent)
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
if (!pThis->OnScrollBy(CSize(scrollExtent)))
sc = S_FALSE;
else
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::OnUIDeactivate(BOOL fUndoable)
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
pThis->m_pView = pThis->m_pMfcView;
if(pThis->m_pView&&::IsWindow(pThis->m_pView->m_hWnd))
{
TRY
{
pThis->GetDocument();
pThis->OnDeactivateUI(fUndoable);
sc = S_OK;
//pThis->OnDeactivateUI(fUndoable);
//pThis->DoVerb(OLEIVERB_SHOW, pThis->m_pMfcView);
//TRACE0("CTangramCntrItem::XOleIPSiteEx::OnUIDeactivate here\n");
//AfxMessageBox("2'");
//sc = S_OK;
}
END_TRY
}
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::OnInPlaceDeactivate()
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDeactivate();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::DiscardUndoState()
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDiscardUndoState();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::DeactivateAndUndo()
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
pThis->OnDeactivateAndUndo();
sc = S_OK;
}
END_TRY
return sc;
}
STDMETHODIMP CTangramCntrItem::XOleIPSiteEx::OnPosRectChange(
LPCRECT lpPosRect)
{
METHOD_PROLOGUE_EX(CTangramCntrItem, OleIPSiteEx)
ASSERT_VALID(pThis);
SCODE sc = E_UNEXPECTED;
TRY
{
CRect rect;
rect.CopyRect(lpPosRect);
pThis->OnChangeItemPosition(rect);
sc = S_OK;
}
END_TRY
return sc;
}
/////////////////////////////////////////////////////////////////////////////
// CTangramCntrItem commands
void CTangramCntrItem::GetCtrlWndHandle()
{
LPOLEINPLACEOBJECT lpInPlaceObject = NULL;
if (m_lpObject->QueryInterface(IID_IOleInPlaceObject, (LPLP)&lpInPlaceObject) != S_OK)
return ;
ASSERT(lpInPlaceObject != NULL);
//get the HWND for the in-place active object
HWND hWnd;
if (lpInPlaceObject->GetWindow(&hWnd) != S_OK)
hWnd = NULL;
lpInPlaceObject->Release();
m_hWndServer = hWnd;
}
void CTangramCntrItem::Deactivate()
{
if(IsInPlaceActive()==FALSE)return;
/*COleClientItem::Deactivate();*/
ASSERT_VALID(this);
//ASSERT(m_lpObject != NULL);
//ASSERT(IsInPlaceActive());
//if(IsInPlaceActive()) return;
if(m_lpObject==NULL)
{
return;
}
// get IOleInPlaceObject interface
LPOLEINPLACEOBJECT lpInPlaceObject = NULL;
if (m_lpObject->QueryInterface(IID_IOleInPlaceObject, (LPLP)&lpInPlaceObject) != S_OK)
return ;
if (lpInPlaceObject == NULL)
{
Close(); // handle rare failure cases by calling Close
return;
}
// call IOleInPlaceObject::InPlaceDeactivate
m_scLast = lpInPlaceObject->InPlaceDeactivate();
lpInPlaceObject->Release();
if (FAILED(m_scLast))
{
Close(); // handle rare failure cases by calling Close
return;
}
m_nItemState = loadedState; // just in case server has crashed*/
}
void CTangramCntrItem::OnActivate()
{
// TODO: Add your specialized code here and/or call the base class
if(IsInPlaceActive())return;
COleClientItem::OnActivate();
}
void CTangramCntrItem::OnActivateUI()
{
ASSERT_VALID(this);
// notify the item of the state change
if (m_nItemState != activeUIState)
{
OnChange(OLE_CHANGED_STATE, (DWORD)activeUIState);
m_nItemState = activeUIState;
}
//get the HWND for the in-place active object
if(m_hWndServer==0)GetCtrlWndHandle();
// make sure top-level frame is hooked
if (m_pInPlaceFrame != NULL)
{
TRACE("m_pInPlaceFrame:%d\r\n",m_pInPlaceFrame);
ASSERT_VALID(m_pInPlaceFrame->m_pFrameWnd);
m_pInPlaceFrame->m_pFrameWnd->m_pNotifyHook = m_pInPlaceFrame;
}
// make sure doc-level frame is hooked
if (m_pInPlaceDoc != NULL)
{
TRACE("m_pInPlaceDoc:%d\r\n",m_pInPlaceDoc);
ASSERT_VALID(m_pInPlaceDoc->m_pFrameWnd);
m_pInPlaceDoc->m_pFrameWnd->m_pNotifyHook = m_pInPlaceDoc;
}
}
void CTangramCntrItem::OnDeactivate()
{
// TODO: Add your specialized code here and/or call the base class
COleClientItem::OnDeactivate();
}
void CTangramCntrItem::OnDeactivateUI(BOOL bUndoable)
{
// TODO: Add your specialized code here and/or call the base class
if(m_pDoc)
m_pDocument = m_pDoc;
COleClientItem::OnDeactivateUI(bUndoable);
}
void CTangramCntrItem::OnSetMenu(CMenu* pMenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
{
}
BOOL CTangramCntrItem::OnGetWindowContext(CFrameWnd** ppMainFrame, CFrameWnd** ppDocFrame, LPOLEINPLACEFRAMEINFO pFrameInfo)
{
ASSERT(AfxIsValidAddress(ppMainFrame, sizeof(CFrameWnd*)));
ASSERT(AfxIsValidAddress(ppDocFrame, sizeof(CFrameWnd*)));
ASSERT(pFrameInfo == NULL ||
AfxIsValidAddress(pFrameInfo, sizeof(OLEINPLACEFRAMEINFO)));
ASSERT_VALID(this);
m_pView = m_pMfcView;
ASSERT_VALID(m_pView);
// get main window of application
*ppMainFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd;
ASSERT_VALID(*ppMainFrame);
ASSERT_KINDOF(CFrameWnd, *ppMainFrame);
// get document window (if there is one)
CFrameWnd* pDocFrame = m_pView->GetParentFrame();
if (pDocFrame != *ppMainFrame)
{
*ppDocFrame = pDocFrame;
ASSERT_VALID(*ppDocFrame);
ASSERT_KINDOF(CFrameWnd, *ppDocFrame);
}
if (pFrameInfo != NULL)
{
// get accelerator table
if(m_pDoc)
{
CDocTemplate* pTemplate = GetDocument()->GetDocTemplate();
HACCEL hAccel = pTemplate != NULL ? pTemplate->m_hAccelInPlace : NULL;
pFrameInfo->cAccelEntries =
hAccel != NULL ? CopyAcceleratorTable(hAccel, NULL, 0) : 0;
pFrameInfo->haccel = pFrameInfo->cAccelEntries != 0 ? hAccel : NULL;
pFrameInfo->hwndFrame = (*ppMainFrame)->m_hWnd;
pFrameInfo->fMDIApp = *ppDocFrame != NULL;
}
}
return TRUE;
}
void CTangramCntrItem::OnGetClipRect(CRect& rClipRect)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(&rClipRect, sizeof(RECT)));
// default clips rectClip to client area of the active view
ASSERT_VALID(m_pMfcView);
m_pMfcView->GetClientRect(&rClipRect);
}
BOOL CTangramCntrItem::SetItemRects(LPCRECT lpPosRect, LPCRECT lpClipRect)
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
//ASSERT(IsInPlaceActive());
ASSERT(lpPosRect == NULL ||
AfxIsValidAddress(lpPosRect, sizeof(RECT), FALSE));
ASSERT(lpClipRect == NULL ||
AfxIsValidAddress(lpClipRect, sizeof(RECT), FALSE));
// get IOleInPlaceObject interface
LPOLEINPLACEOBJECT lpInPlaceObject;
if (m_lpObject->QueryInterface(IID_IOleInPlaceObject, (LPLP)&lpInPlaceObject) != S_OK)
return FALSE;
// QUERYINTERFACE(m_lpObject, IOleInPlaceObject);
if (lpInPlaceObject == NULL)
return FALSE; // perhaps server crashed?
// use OnGetPosRect if rectangle not specified
CRect rectPos;
if (lpPosRect == NULL)
{
ASSERT(lpClipRect == NULL);
OnGetItemPosition(rectPos);
lpPosRect = &rectPos;
}
// use OnGetClipRect if clipping rectangle not specified
CRect rectClip;
if (lpClipRect == NULL)
{
OnGetClipRect(rectClip);
lpClipRect = &rectClip;
}
ASSERT(lpPosRect != NULL);
ASSERT(lpClipRect != NULL);
// notify the server of the new item rectangles
m_scLast = lpInPlaceObject->SetObjectRects(lpPosRect, lpClipRect);
lpInPlaceObject->Release();
// remember position rectangle as cached position
return !FAILED(m_scLast);
}
void CTangramCntrItem::OnGetItemPosition(CRect& rPosition)
{
ASSERT_VALID(this);
// During in-place activation, CTangramCntrItem::OnGetItemPosition
// will be called to determine the location of this item. The default
// implementation created from AppWizard simply returns a hard-coded
// rectangle. Usually, this rectangle would reflect the current
// position of the item relative to the view used for activation.
// You can obtain the view by calling CTangramCntrItem::GetActiveView.
// TODO: return correct rectangle (in pixels) in rPosition
CView* pView = m_pMfcView;//GetActiveView();
ASSERT_VALID(pView);
pView->GetClientRect(rPosition);
if(pView&&::IsWindow(pView->m_hWnd))
{
CClientDC dc(pView);
pView->OnPrepareDC(&dc, NULL);
dc.DPtoLP(rPosition);
}
}
void CTangramCntrItem::ShowPropertyPage()
{
CComQIPtr<IDispatch, &IID_IDispatch> spControl(m_lpObject);
ASSERT(spControl);
IDispatch* m_pIDispatch = spControl;
ISpecifyPropertyPages *pISPP;
CAUUID caGUID;
HRESULT hr;
if (FAILED(m_pIDispatch->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pISPP)))
{
return;
}
hr=pISPP->GetPages(&caGUID);
pISPP->Release();
if (FAILED(hr))
{
return;
}
if(m_pTangramObject)
hr=OleCreatePropertyFrame(m_pMfcView->m_hWnd, 10, 10, m_pTangramObject->m_strObjID.AllocSysString() , 1, (IUnknown **)&m_pIDispatch, caGUID.cElems , caGUID.pElems, LOCALE_USER_DEFAULT, 0L, NULL);
if (FAILED(hr))
{
//Message(TEXT("OleCreatePropertyFrame failed.")); //Free GUIDs.
}
CoTaskMemFree((void *)caGUID.pElems);
return;
}
void CTangramCntrItem::OnInsertMenus(CMenu* pMenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
// TODO: �ڴ����ר�ô����/����û���
COleClientItem::OnInsertMenus(pMenuShared, lpMenuWidths);
}