/*
* FIGURE.CPP
* Cosmo Chapter 23
*
* Implementation of the CFigure object for Cosmo.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "cosmo.h"
/*
* CFigure::CFigure
* CFigure::~CFigure
*
* Parameters (Constructor):
* pfnDestroy PFNDESTROYED to call when object is destroyed.
* pDoc PCCosmoDoc we're associated with.
*/
CFigure::CFigure(PFNDESTROYED pfnDestroy, PCCosmoDoc pDoc)
{
m_cRef=0;
m_pfnDestroy=pfnDestroy;
m_pFR=NULL; //We get this later through FrameSet.
m_pDoc=pDoc;
m_pPL=pDoc->m_pPL;
m_fEmbedded=FALSE;
//NULL any contained interfaces initially.
m_pImpIPersistStorage=NULL;
m_pIStorage=NULL;
m_pIStream=NULL;
m_pImpIDataObject=NULL;
m_pIDataAdviseHolder=NULL;
m_pImpIOleObject=NULL;
m_pIOleAdviseHolder=NULL;
m_pIOleClientSite=NULL;
m_clsID=CLSID_CosmoFigure;
m_cf=pDoc->m_cf;
//These are for IDataObject::QueryGetData
m_cfeGet=CFORMATETCGET;
SETDefFormatEtc(m_rgfeGet[0], pDoc->m_cf, TYMED_HGLOBAL);
SETDefFormatEtc(m_rgfeGet[1], pDoc->m_cfEmbedSource
, TYMED_ISTORAGE);
SETDefFormatEtc(m_rgfeGet[2], pDoc->m_cfObjectDescriptor
, TYMED_HGLOBAL);
SETDefFormatEtc(m_rgfeGet[3], CF_METAFILEPICT, TYMED_MFPICT);
SETDefFormatEtc(m_rgfeGet[4], CF_BITMAP, TYMED_GDI);
m_pST=NULL;
m_pImpIPersistFile=NULL;
//We live in the document's lifetime, so no need to AddRef here.
m_pMoniker=m_pDoc->m_pMoniker;
m_dwRegROT=0L;
//CHAPTER23MOD
m_pIOleIPSite=NULL;
m_pIOleIPFrame=NULL;
m_pIOleIPUIWindow=NULL;
m_pImpIOleIPObject=NULL;
m_pImpIOleIPActiveObject=NULL;
m_hMenuShared=NULL;
m_hOLEMenu=NULL;
m_hAccel=NULL;
m_pHW=NULL;
m_pTB=NULL;
m_cyBar=0;
m_fUndoDeactivates=FALSE;
m_fAllowInPlace=TRUE;
m_fForceSave=FALSE;
//End CHAPTER23MOD
return;
}
CFigure::~CFigure(void)
{
ReleaseInterface(m_pIOleClientSite);
ReleaseInterface(m_pIDataAdviseHolder);
ReleaseInterface(m_pIOleAdviseHolder);
//CHAPTER23MOD
if (NULL!=m_pHW)
delete m_pHW;
if (NULL!=m_pST)
delete m_pST;
/*
* Free contained interfaces.
* Container in-place interfaces released during deactivation.
*/
if (NULL!=m_pTB) //Safety-net
delete m_pTB;
DeleteInterfaceImp(m_pImpIOleIPObject);
DeleteInterfaceImp(m_pImpIOleIPActiveObject);
//End CHAPTER23MOD
//Make sure no one thinks we're still running
if (0L!=m_dwRegROT)
INOLE_RevokeAsRunning(&m_dwRegROT);
ReleaseInterface(m_pIStorage)
ReleaseInterface(m_pIStream)
DeleteInterfaceImp(m_pImpIPersistFile);
DeleteInterfaceImp(m_pImpIOleObject)
DeleteInterfaceImp(m_pImpIDataObject)
DeleteInterfaceImp(m_pImpIPersistStorage);
//Free strings.
if (NULL!=m_pST)
delete m_pST;
return;
}
/*
* CFigure::QueryInterface
* CFigure::AddRef
* CFigure::Release
*
* Purpose:
* IUnknown members for CFigure object.
*/
STDMETHODIMP CFigure::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv=this;
if (IID_IPersist==riid || IID_IPersistStorage==riid)
*ppv=m_pImpIPersistStorage;
if (IID_IDataObject==riid)
*ppv=m_pImpIDataObject;
if (IID_IOleObject==riid)
*ppv=m_pImpIOleObject;
if (IID_IPersistFile==riid)
*ppv=m_pImpIPersistFile;
//CHAPTER23MOD
if (IID_IOleWindow==riid || IID_IOleInPlaceObject==riid)
*ppv=m_pImpIOleIPObject;
//End CHAPTER23MOD
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CFigure::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CFigure::Release(void)
{
if (0!=--m_cRef)
return m_cRef;
if (NULL!=m_pfnDestroy)
(*m_pfnDestroy)();
//Document deletes us
return 0;
}
/*
* CFigure::Init
*
* Purpose:
* Performs any initialization of a CFigure that's prone to failure
* that we also use internally before exposing the object outside.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if the function is successful,
* FALSE otherwise.
*/
BOOL CFigure::Init(void)
{
m_pST=new CStringTable(m_pDoc->m_hInst);
if (NULL==m_pST)
return FALSE;
if (!m_pST->Init(IDS_FIGUREMIN, IDS_FIGUREMAX))
return FALSE;
//Allocate contained interfaces.
m_pImpIPersistStorage=new CImpIPersistStorage(this, this);
if (NULL==m_pImpIPersistStorage)
return FALSE;
m_pImpIDataObject=new CImpIDataObject(this, this);
if (NULL==m_pImpIDataObject)
return FALSE;
m_pImpIOleObject=new CImpIOleObject(this, this);
if (NULL==m_pImpIOleObject)
return FALSE;
m_pImpIPersistFile=new CImpIPersistFile(this, this);
if (NULL==m_pImpIPersistFile)
return FALSE;
//CHAPTER23MOD
m_pImpIOleIPObject=new CImpIOleInPlaceObject(this, this);
if (NULL==m_pImpIOleIPObject)
return FALSE;
m_pImpIOleIPActiveObject=new CImpIOleInPlaceActiveObject(this
, this);
if (NULL==m_pImpIOleIPActiveObject)
return FALSE;
m_pHW=new CHatchWin(m_pDoc->m_hInst);
if (NULL==m_pHW)
return FALSE;
//We don't have m_pFR yet from which to get the frame window.
if (!m_pHW->Init(m_pDoc->Window(), ID_HATCHWINDOW, NULL))
return FALSE;
//End CHAPTER23MOD
return TRUE;
}
/*
* CFigure::FrameSet
*
* Purpose:
* Provides the compound document object with access to the frame
* of this application for UI purposes.
*
* Parameters:
* pFR PCCosmoFrame of the frame window.
*
* Return Value:
* None
*/
void CFigure::FrameSet(PCCosmoFrame pFR)
{
m_pFR=pFR;
//CHAPTER23MOD
//We need this in IOleInPlaceActiveObject::ResizeBorder
m_cyBar=m_pFR->m_cyBar;
//We need this in IOleInPlaceActiveObject::TranslateAccelerator
m_hAccel=m_pFR->m_hAccel;
//End CHAPTER23MOD
return;
}
/*
* CFigure::FIsDirty
*
* Purpose:
* Checks if the document is dirty. This can be called from
* IPersistStorage::IsDirty which doesn't have access to CCosmoDoc.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if dirty, FALSE if clean.
*/
BOOL CFigure::FIsDirty(void)
{
//CHAPTER23MOD
//Force a save if we opened after being in-place.
return m_pDoc->m_fDirty || m_fForceSave;
//End CHAPTER23MOD
}
/*
* CFigure::FIsEmbedded
*
* Purpose:
* Answers if the object is embedded or not.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if the object is embedded, FALSE otherwise.
*/
BOOL CFigure::FIsEmbedded(void)
{
return m_fEmbedded;
}
/*
* CFigure::SendAdvise
*
* Purpose:
* Calls the appropriate IOleClientSite or IAdviseSink member
* function for various events such as closure, saving, etc.
*
* Parameters:
* uCode UINT OBJECTCODE_* identifying the notification.
*
* Return Value:
* None
*/
void CFigure::SendAdvise(UINT uCode)
{
switch (uCode)
{
case OBJECTCODE_SAVED:
if (NULL!=m_pIOleAdviseHolder)
m_pIOleAdviseHolder->SendOnSave();
break;
case OBJECTCODE_CLOSED:
if (NULL!=m_pIOleAdviseHolder)
m_pIOleAdviseHolder->SendOnClose();
break;
case OBJECTCODE_RENAMED:
m_pMoniker=m_pDoc->m_pMoniker; //For IOleObject::GetMoniker
m_dwRegROT=m_pDoc->m_dwRegROT;
if (NULL!=m_pIOleAdviseHolder)
m_pIOleAdviseHolder->SendOnRename(m_pMoniker);
break;
case OBJECTCODE_SAVEOBJECT:
if (FIsDirty() && NULL!=m_pIOleClientSite)
m_pIOleClientSite->SaveObject();
break;
case OBJECTCODE_DATACHANGED:
//No flags are necessary here.
if (NULL!=m_pIDataAdviseHolder)
{
m_pIDataAdviseHolder->SendOnDataChange
(m_pImpIDataObject, 0, 0);
}
//Tell the running object table of the change
if (0!=m_dwRegROT)
INOLE_NoteChangeTime(m_dwRegROT, NULL, NULL);
//CHAPTER23MOD
/*
* If this is the first change after activation, tell the
* container to free any undo information it's holding.
*/
if (NULL!=m_pIOleIPSite && m_fUndoDeactivates)
m_pIOleIPSite->DiscardUndoState();
m_fUndoDeactivates=FALSE;
//End CHAPTER23MOD
break;
case OBJECTCODE_SHOWWINDOW:
if (NULL!=m_pIOleClientSite)
m_pIOleClientSite->OnShowWindow(TRUE);
break;
case OBJECTCODE_HIDEWINDOW:
if (NULL!=m_pIOleClientSite)
m_pIOleClientSite->OnShowWindow(FALSE);
break;
case OBJECTCODE_SHOWOBJECT:
if (NULL!=m_pIOleClientSite)
m_pIOleClientSite->ShowObject();
break;
}
return;
}
//CHAPTER23MOD
/*
* CFigure::InPlaceActivate
*
* Purpose:
* Goes through all the steps of activating the Figure as an
* in-place object.
*
* Parameters:
* pActiveSite LPOLECLIENTSITE of the active site we show in.
* fIncludeUI BOOL indicating if we should do UI as well.
*
* Return Value:
* HRESULT Whatever error code is appropriate.
*/
HRESULT CFigure::InPlaceActivate(LPOLECLIENTSITE pActiveSite
, BOOL fIncludeUI)
{
HRESULT hr;
HWND hWnd, hWndHW;
RECT rcPos;
RECT rcClip;
if (NULL==pActiveSite)
return ResultFromScode(E_INVALIDARG);
//If we're already active, do the UI and we're done.
if (NULL!=m_pIOleIPSite)
{
if (fIncludeUI)
UIActivate();
return NOERROR;
}
/*
* 1. Initialization, obtaining interfaces, calling
* OnInPlaceActivate.
*/
hr=pActiveSite->QueryInterface(IID_IOleInPlaceSite
, (PPVOID)&m_pIOleIPSite);
if (FAILED(hr))
return hr;
hr=m_pIOleIPSite->CanInPlaceActivate();
if (NOERROR!=hr)
{
m_pIOleIPSite->Release();
m_pIOleIPSite=NULL;
return ResultFromScode(E_FAIL);
}
m_pIOleIPSite->OnInPlaceActivate();
m_fUndoDeactivates=TRUE;
/*
* 2. Get the window context and create a window or change the
* parent and position of an existing window. Servers are
* required to full cb in the OLEINPLACEFRAMEINFO structure.
*/
m_pIOleIPSite->GetWindow(&hWnd);
m_pFR->m_frameInfo.cb=sizeof(OLEINPLACEFRAMEINFO);
m_pIOleIPSite->GetWindowContext(&m_pIOleIPFrame
, &m_pIOleIPUIWindow, &rcPos, &rcClip
, &m_pFR->m_frameInfo);
/*
* Copy container frame pointer to CCosmoFrame for accelerators.
* No AddRef because frame never messes with it. Note also that
* we don't do anything special with our own accelerators here
* because we just use the same ones as always.
*/
m_pFR->m_pIOleIPFrame=m_pIOleIPFrame;
/*
* We'll use a hatch window as the child of the container and the
* editing window as a child of the hatch window. We already
* created the hatch window, so now all we have to do is put it
* in the right place and stick the Polyline in it.
*/
m_pHW->HwndAssociateSet(m_pFR->Window());
m_pHW->ChildSet(m_pPL->Window()); //Calls SetParent
m_pHW->RectsSet(&rcPos, &rcClip); //Positions polyline
hWndHW=m_pHW->Window();
SetParent(hWndHW, hWnd); //Move the hatch window
ShowWindow(hWndHW, SW_SHOW); //Make us visible.
SendAdvise(OBJECTCODE_SHOWOBJECT);
if (fIncludeUI)
return UIActivate();
return NOERROR;
}
/*
* CFigure::InPlaceDeactivate
*
* Purpose:
* Reverses all the activation steps from InPlaceActivate.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CFigure::InPlaceDeactivate(void)
{
RECT rc;
UIDeactivate();
/*
* When setting the parent back to the normal document,
* reposition the Polyline to be at (8,8) instead of at wherever
* it was in the container's window or our hatch window. This
* is so if we are deactivating to open in our own window the
* Polyline appears in the proper place in the document window.
*/
SetParent(m_pPL->Window(), m_pDoc->m_hWnd);
m_pHW->ChildSet(NULL);
//Make sure the hatch window is invisible and owned by Cosmo
ShowWindow(m_pHW->Window(), SW_HIDE);
SetParent(m_pHW->Window(), m_pDoc->m_hWnd);
GetClientRect(m_pDoc->m_hWnd, &rc);
InflateRect(&rc, -8, -8);
SetWindowPos(m_pPL->Window(), NULL, rc.left, rc.top
, rc.right-rc.left, rc.bottom-rc.top
, SWP_NOZORDER | SWP_NOACTIVATE);
if (NULL!=m_pIOleIPSite)
m_pIOleIPSite->OnInPlaceDeactivate();
m_pFR->m_pIOleIPFrame=NULL;
ReleaseInterface(m_pIOleIPFrame);
ReleaseInterface(m_pIOleIPUIWindow);
ReleaseInterface(m_pIOleIPSite);
return;
}
/*
* CFigure::UIActivate
*
* Purpose:
* Goes through all the steps of activating the user interface of
* the Figure as an in-place object.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR or error code.
*/
HRESULT CFigure::UIActivate(void)
{
//1. Call IOleInPlaceSite::UIActivate
if (NULL!=m_pIOleIPSite)
m_pIOleIPSite->OnUIActivate();
//2. Critical for accelerators to work initially.
SetFocus(m_pHW->Window());
//3. Set the active object
#ifdef WIN32ANSI
OLECHAR szTemp[40];
MultiByteToWideChar(CP_ACP, 0, PSZ(IDS_INPLACETITLE)
, -1, szTemp, 40);
#endif
if (NULL!=m_pIOleIPFrame)
{
m_pIOleIPFrame->SetActiveObject(m_pImpIOleIPActiveObject
#ifdef WIN32ANSI
, szTemp);
#else
, PSZ(IDS_INPLACETITLE));
#endif
}
if (NULL!=m_pIOleIPUIWindow)
{
m_pIOleIPUIWindow->SetActiveObject(m_pImpIOleIPActiveObject
#ifdef WIN32ANSI
, szTemp);
#else
, PSZ(IDS_INPLACETITLE));
#endif
}
//4. Create frame tools
InPlaceToolsCreate();
//5. Create the shared menu.
InPlaceMenuCreate();
return NOERROR;
}
/*
* CFigure::UIDeactivate
*
* Purpose:
* Reverses all the user interface activation steps from
* UIActivate.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CFigure::UIDeactivate(void)
{
//1. Remove the in-place tools
InPlaceToolsDestroy();
//2. Remove the shared menu.
InPlaceMenuDestroy();
//3. Set active obejcts to NULL
if (NULL!=m_pIOleIPFrame)
m_pIOleIPFrame->SetActiveObject(NULL, NULL);
if (NULL!=m_pIOleIPUIWindow)
m_pIOleIPUIWindow->SetActiveObject(NULL, NULL);
//3. Call IOleInPlaceSite::OnUIDeactivate
if (NULL!=m_pIOleIPSite)
m_pIOleIPSite->OnUIDeactivate(FALSE);
return;
}
/*
* CFigure::InPlaceMenuCreate
*
* Purpose:
* Creates and sets a menu for an in-place embedded object.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if everything is well, FALSE on error.
*/
BOOL CFigure::InPlaceMenuCreate(void)
{
HMENU hMenu, hMenuT;
UINT uTemp=MF_BYPOSITION | MF_POPUP;
UINT i;
OLEMENUGROUPWIDTHS mgw;
for (i=0; i<6; i++)
mgw.width[i]=0;
//We already have popup menu handles in m_pFR->m_phMenu[]
//Create the new shared menu and let container do its thing
hMenu=CreateMenu();
m_pIOleIPFrame->InsertMenus(hMenu, &mgw);
/*
* Add our menus remembering that the container has added its
* already.
*/
InsertMenu(hMenu, (UINT)mgw.width[0]
, uTemp, (UINT)m_pFR->m_phMenu[1], PSZ(IDS_MENUEDIT));
/*
* Add the Open item to the edit menu.
* NOTE: If you are a multiple-use server, this sort of code
* will also modify the menu on the server window as well as
* this shared menu in which case you need a separate popup menu
* altogether.
*/
AppendMenu(m_pFR->m_phMenu[1], MF_SEPARATOR, 0, NULL);
AppendMenu(m_pFR->m_phMenu[1], MF_STRING, IDM_EDITOPEN
, PSZ(IDS_MENUOPEN));
InsertMenu(hMenu, (UINT)mgw.width[0]+1+(UINT)mgw.width[2]
, uTemp, (UINT)m_pFR->m_phMenu[2], PSZ(IDS_MENUCOLOR));
InsertMenu(hMenu, (UINT)mgw.width[0]+1+(UINT)mgw.width[2]+1
, uTemp, (UINT)m_pFR->m_phMenu[3], PSZ(IDS_MENULINE));
//Window menu position changes between MDI and SDI
#ifdef MDI
hMenuT=m_pFR->m_phMenu[5];
#else
hMenuT=m_pFR->m_phMenu[4];
#endif
InsertMenu(hMenu, (UINT)mgw.width[0]+1+(UINT)mgw.width[2]+2
+ (UINT)mgw.width[4], uTemp, (UINT)hMenuT
, PSZ(IDS_MENUHELP));
//Tell OLE how many items in each group are ours.
mgw.width[1]=1;
mgw.width[3]=2;
mgw.width[5]=1;
m_hMenuShared=hMenu;
m_hOLEMenu=OleCreateMenuDescriptor(m_hMenuShared, &mgw);
m_pIOleIPFrame->SetMenu(m_hMenuShared, m_hOLEMenu
, m_pFR->Window());
return TRUE;
}
/*
* CFigure::InPlaceMenuDestroy
*
* Purpose:
* Performs opposite actions from InPlaceMenuCreate
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if all is well, FALSE otherwise.
*/
BOOL CFigure::InPlaceMenuDestroy(void)
{
int cItems, i, j;
HMENU hMenuT;
//If we don't have a shared menu, nothing to do.
if (NULL==m_hMenuShared)
return TRUE;
//Stop the container frame from using this menu.
m_pIOleIPFrame->SetMenu(NULL, NULL, NULL);
//Clean up what we got from OleCreateMenuDescriptor.
OleDestroyMenuDescriptor(m_hOLEMenu);
m_hOLEMenu=NULL;
cItems=GetMenuItemCount(m_hMenuShared);
/*
* Walk backwards down the menu. For each popup, see if it
* matches any other popup we know about, and if so, remove
* it from the shared menu.
*/
for (i=cItems; i >=0; i--)
{
hMenuT=GetSubMenu(m_hMenuShared, i);
for (j=0; j <= CMENUS; j++)
{
/*
* If the submenu matches any we have, remove, don't
* delete. Since we're walking backwards this only
* affects the positions of those menus after us so the
* GetSubMenu call above is not affected.
*/
if (hMenuT==m_pFR->m_phMenu[j])
RemoveMenu(m_hMenuShared, i, MF_BYPOSITION);
}
}
/*
* Remove the Open item and separator from the Edit menu.
* NOTE: If you are a multiple-user server, this affects the
* menu on the server window as well as the shared menu in which
* case you need to use a separate popup menu altogether.
*/
RemoveMenu(m_pFR->m_phMenu[1], MPOS_OPEN, MF_BYPOSITION);
RemoveMenu(m_pFR->m_phMenu[1], MPOS_SEP, MF_BYPOSITION);
if (NULL!=m_pIOleIPFrame)
m_pIOleIPFrame->RemoveMenus(m_hMenuShared);
DestroyMenu(m_hMenuShared);
m_hMenuShared=NULL;
return TRUE;
}
/*
* CFigure::InPlaceToolsCreate
*
* Purpose:
* Creates a toolbar for in-place activation and negotiates the
* border space for the toolbar.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if we could allocate the space and create
* the tools. FALSE if we fail, meaning that we
* just do in-place with menus only, since we can
* do without the tools. We could fail and attempt
* to reverse what we might have done already, but
* since we don't really *need* the toolbar, we
* keep going.
*/
BOOL CFigure::InPlaceToolsCreate(void)
{
BORDERWIDTHS bw;
HWND hWnd;
UINT uState=GIZMO_NORMAL;
UINT utCmd =GIZMOTYPE_BUTTONCOMMAND;
UINT utEx =GIZMOTYPE_BUTTONATTRIBUTEEX;
UINT i;
HBITMAP hBmp;
RECT rc;
UINT dxB, dyB;
//We don't need anything on the document, so send zeros.
SetRectEmpty((LPRECT)&bw);
if (NULL!=m_pIOleIPUIWindow)
m_pIOleIPUIWindow->SetBorderSpace(&bw);
if (NULL==m_pIOleIPFrame)
return FALSE;
/*
* 1. Make sure we can reserve space for what we need. If this
* fails then we just do without because the menu has
* everything we really need. A more willing server could
* put tools in popup windows as well.
*/
if (!InPlaceToolsRenegotiate())
{
//If the container doesn't allow us any, don't ask for any.
m_pIOleIPFrame->SetBorderSpace(&bw);
return FALSE;
}
/*
* 2. Create the toolbar window using the container window as
* the parent. In order to get messages from it, we use
* it's AssociateSet ability directly after creation and
* before we add any tools to the bar.
*/
m_pIOleIPFrame->GetWindow(&hWnd);
//If we already have a toolbar, just show it again.
if (NULL!=m_pTB)
{
ShowWindow(m_pTB->Window(), SW_SHOW);
return TRUE;
}
m_pTB=new CToolBar(m_pFR->m_hInst);
if (NULL==m_pTB)
{
SetRectEmpty((LPRECT)&bw);
m_pIOleIPFrame->SetBorderSpace(&bw);
return FALSE;
}
m_pTB->Init(hWnd, ID_GIZMOBAR, m_cyBar);
g_pInPlaceTB=m_pTB;
//Insure the tools are initially invisible
ShowWindow(m_pTB->Window(), SW_HIDE);
//Tell the toolbar who to send messages to.
m_pTB->HwndAssociateSet(m_pFR->m_hWnd);
/*
* Add tools to the bar, setting CFrame::fInit to avoid
* command processing
*/
m_pFR->m_fInit=TRUE;
hBmp=m_pFR->m_hBmp;
dxB=m_pFR->m_dxB;
dyB=m_pFR->m_dyB;
//Edit Undo, Cut, Copy, Paste
m_pTB->Add(utCmd, 1, IDM_EDITUNDO, dxB, dyB, NULL, hBmp, 1, uState);
m_pTB->Add(utCmd, 2, IDM_EDITCUT, dxB, dyB, NULL, NULL, 0, uState);
m_pTB->Add(utCmd, 3, IDM_EDITCOPY, dxB, dyB, NULL, NULL, 1, uState);
m_pTB->Add(utCmd, 4, IDM_EDITPASTE, dxB, dyB, NULL, NULL, 2, uState);
//Separator
m_pTB->Add(GIZMOTYPE_SEPARATOR, 5, 0, 6, dyB, NULL, NULL, 0, uState);
//Color Background and Color Line
m_pTB->Add(utCmd, 6, IDM_COLORBACKGROUND, dxB, dyB, NULL, hBmp, 3
, GIZMO_NORMAL | PRESERVE_BLACK);
m_pTB->Add(utCmd, 7, IDM_COLORLINE, dxB, dyB, NULL, hBmp, 4, uState);
//Separator
m_pTB->Add(GIZMOTYPE_SEPARATOR, 8, 0, 6, dyB, NULL, NULL, 0, uState);
//Line styles.
m_pTB->Add(utEx, 19, IDM_LINESOLID, dxB, dyB, NULL, hBmp, 5, uState);
m_pTB->Add(utEx, 10, IDM_LINEDASH, dxB, dyB, NULL, hBmp, 6, uState);
m_pTB->Add(utEx, 11, IDM_LINEDOT, dxB, dyB, NULL, hBmp, 7, uState);
m_pTB->Add(utEx, 12, IDM_LINEDASHDOT, dxB, dyB, NULL, hBmp, 8
, uState);
m_pTB->Add(utEx, 13, IDM_LINEDASHDOTDOT, dxB, dyB, NULL, hBmp, 9
, uState);
//Check the current line style.
i=m_pPL->LineStyleGet()+IDM_LINEMIN;
m_pTB->Check(i, TRUE);
m_pFR->m_fInit=FALSE;
/*
* Before making the toolbar visible, resize it to the
* container's GetBorder rectangle. By default the toolbar
* sizes itself to the client area of the parent, but we can't
* assume that's the same as GetBorder returns, so we do the
* extra work here.
*/
m_pIOleIPFrame->GetBorder(&rc);
SetWindowPos(m_pTB->Window(), NULL, rc.left, rc.top
, rc.right-rc.left, rc.top+m_cyBar, SWP_NOZORDER);
//3. Make the tools visible.
ShowWindow(m_pTB->Window(), SW_SHOW);
return TRUE;
}
/*
* CFigure::InPlaceToolsDestroy
*
* Purpose:
* Reverses the process of InPlaceToolsCreate
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CFigure::InPlaceToolsDestroy(void)
{
//Nothing to do if we never created anything.
if (NULL==m_pTB)
return TRUE;
/*
* No reason to call SetBorderSpace with an empty rectangle
* since you call IOleInPlaceSite::OnUIDeactivate. The
* container will restore its own tools appropriately.
*/
//Destroy the toolbar.
if (NULL!=m_pTB)
{
delete m_pTB;
m_pTB=NULL;
g_pInPlaceTB=NULL;
}
return TRUE;
}
/*
* CFigure::InPlaceToolsRenegotiate
*
* Purpose:
* Calls IOleInPlaceFrame::RequestBorderSpace and SetBorderSpace
* to reserve space for our toolbar.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if all is well, FALSE otherwise.
*/
BOOL CFigure::InPlaceToolsRenegotiate(void)
{
HRESULT hr;
BORDERWIDTHS bw;
SetRect((LPRECT)&bw, 0, m_pFR->m_cyBar, 0, 0);
hr=m_pIOleIPFrame->RequestBorderSpace(&bw);
if (NOERROR!=hr)
return FALSE;
//Safety net: RequestBorderSpace may modify values in bw
SetRect((LPRECT)&bw, 0, m_pFR->m_cyBar, 0, 0);
m_pIOleIPFrame->SetBorderSpace(&bw);
return TRUE;
}
/*
* CFigure::OpenIntoWindow
*
* Purpose:
* If we're current open in-place, send ourselves the OPEN verb to
* show into a full window.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CFigure::OpenIntoWindow(void)
{
if (NULL!=m_pIOleIPSite)
{
//Make sure we don't try to do this.
m_fUndoDeactivates=FALSE;
/*
* We can get away with passing a lot of NULLs since we know
* how we implemented DoVerb.
*/
m_pImpIOleObject->DoVerb(OLEIVERB_OPEN, NULL
, m_pIOleClientSite, -1, NULL, NULL);
//This makes sure we save ourselves when closing.
m_fForceSave=TRUE;
//Repaint the container immediately
SendAdvise(OBJECTCODE_DATACHANGED);
}
return;
}
/*
* Undo
*
* Purpose:
* If we have not done anything else in this object then call
* IOleInPlaceSite::DeactivateAndUndo and return TRUE, otherwise
* just return FALSE. Note that the m_fUndoDeactivates is set
* to FALSE in CFigure::SendAdvise for OBJECTCODE_DATACHANGED.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if we deactivated, FALSE otherwise.
*/
BOOL CFigure::Undo(void)
{
if (!m_fUndoDeactivates)
return FALSE;
m_fUndoDeactivates=FALSE;
m_pIOleIPSite->DeactivateAndUndo();
return TRUE;
}
//End CHAPTER23MOD