629 lines
15 KiB
C++
629 lines
15 KiB
C++
|
//**********************************************************************
|
||
|
// File name: DOC.CPP
|
||
|
//
|
||
|
// Implementation file for CSimpleDoc.
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// See DOC.H for Class Definition
|
||
|
//
|
||
|
// Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved.
|
||
|
//**********************************************************************
|
||
|
|
||
|
#include "pre.h"
|
||
|
#include "iocs.h"
|
||
|
#include "ias.h"
|
||
|
#include "ioipf.h"
|
||
|
#include "ioips.h"
|
||
|
#include "app.h"
|
||
|
#include "site.h"
|
||
|
#include "doc.h"
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::Create
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Creation for the CSimpleDoc Class
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// CSimpleApp FAR * lpApp - Pointer to the CSimpleApp Class
|
||
|
//
|
||
|
// LPRECT lpRect - Client area rect of "frame" window
|
||
|
//
|
||
|
// HWND hWnd - Window Handle of "frame" window
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// StgCreateDocfile OLE API
|
||
|
// CreateWindow Windows API
|
||
|
// ShowWindow Windows API
|
||
|
// UpdateWindow Windows API
|
||
|
// EnableMenuItem Windows API
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
// This routine was added so that failure could be returned
|
||
|
// from object creation.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
CSimpleDoc FAR * CSimpleDoc::Create(CSimpleApp FAR *lpApp, LPRECT lpRect,
|
||
|
HWND hWnd)
|
||
|
{
|
||
|
CSimpleDoc FAR * lpTemp = new CSimpleDoc(lpApp, hWnd);
|
||
|
|
||
|
if (!lpTemp)
|
||
|
return NULL;
|
||
|
|
||
|
// create storage for the doc.
|
||
|
HRESULT hErr = StgCreateDocfile (NULL,
|
||
|
STGM_READWRITE | STGM_TRANSACTED |
|
||
|
STGM_SHARE_EXCLUSIVE,
|
||
|
0, &lpTemp->m_lpStorage);
|
||
|
|
||
|
if (hErr != NOERROR)
|
||
|
goto error;
|
||
|
|
||
|
// create the document Window
|
||
|
lpTemp->m_hDocWnd = CreateWindow(
|
||
|
TEXT("SimpCntrDocWClass"),
|
||
|
NULL,
|
||
|
WS_CHILD | WS_CLIPCHILDREN,
|
||
|
lpRect->left,
|
||
|
lpRect->top,
|
||
|
lpRect->right,
|
||
|
lpRect->bottom,
|
||
|
hWnd,
|
||
|
NULL,
|
||
|
lpApp->m_hInst,
|
||
|
NULL);
|
||
|
|
||
|
if (!lpTemp->m_hDocWnd)
|
||
|
goto error;
|
||
|
|
||
|
ShowWindow(lpTemp->m_hDocWnd, SW_SHOWNORMAL); // Show the window
|
||
|
UpdateWindow(lpTemp->m_hDocWnd); // Sends WM_PAINT message
|
||
|
|
||
|
// Ensable InsertObject menu choice
|
||
|
EnableMenuItem( lpTemp->m_hEditMenu, 0, MF_BYPOSITION | MF_ENABLED);
|
||
|
|
||
|
// we will add one ref count on our document. later in CSimpleDoc::Close
|
||
|
// we will release this ref count. when the document's ref count goes
|
||
|
// to 0, the document will be deleted.
|
||
|
lpTemp->AddRef();
|
||
|
|
||
|
return (lpTemp);
|
||
|
|
||
|
error:
|
||
|
delete (lpTemp);
|
||
|
return NULL;
|
||
|
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::Close
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Close CSimpleDoc object.
|
||
|
// when the document's reference count goes to 0, the document
|
||
|
// will be destroyed.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// None
|
||
|
//
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// CSimpleSite::CloseOleObject SITE.CPP
|
||
|
// ShowWindow Windows API
|
||
|
// TestDebugOut Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CSimpleDoc::Close(void)
|
||
|
{
|
||
|
TestDebugOut(TEXT("In CSimpleDoc::Close\r\n"));
|
||
|
|
||
|
ShowWindow(m_hDocWnd, SW_HIDE); // Hide the window
|
||
|
|
||
|
// Close the OLE object in our document
|
||
|
if (m_lpSite)
|
||
|
m_lpSite->CloseOleObject();
|
||
|
|
||
|
// Release the ref count added in CSimpleDoc::Create. this will make
|
||
|
// the document's ref count go to 0, and the document will be deleted.
|
||
|
Release();
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::CSimpleDoc
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Constructor for the CSimpleDoc Class
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// CSimpleApp FAR * lpApp - Pointer to the CSimpleApp Class
|
||
|
//
|
||
|
// HWND hWnd - Window Handle of "frame" window
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// GetMenu Windows API
|
||
|
// GetSubMenu Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
CSimpleDoc::CSimpleDoc(CSimpleApp FAR * lpApp,HWND hWnd)
|
||
|
{
|
||
|
TestDebugOut(TEXT("In CSimpleDoc's Constructor\r\n"));
|
||
|
m_lpApp = lpApp;
|
||
|
m_lpSite = NULL;
|
||
|
m_nCount = 0;
|
||
|
// set up menu handles
|
||
|
m_hMainMenu = GetMenu(hWnd);
|
||
|
m_hFileMenu = GetSubMenu(m_hMainMenu, 0);
|
||
|
m_hEditMenu = GetSubMenu(m_hMainMenu, 1);
|
||
|
m_hHelpMenu = GetSubMenu(m_hMainMenu, 2);
|
||
|
m_hCascadeMenu = NULL;
|
||
|
|
||
|
m_lpActiveObject = NULL;
|
||
|
|
||
|
// flags
|
||
|
m_fInPlaceActive = FALSE;
|
||
|
m_fAddMyUI = FALSE;
|
||
|
m_fModifiedMenu = FALSE;
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::~CSimpleDoc
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Destructor for CSimpleDoc
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// CSimpleSite::UnloadOleObject SITE.CPP
|
||
|
// CSimpleSite::Release SITE.CPP
|
||
|
// IStorage::Release OLE API
|
||
|
// GetMenuItemCount Windows API
|
||
|
// RemoveMenu Windows API
|
||
|
// DestroyMenu Windows API
|
||
|
// DestroyWindows Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
CSimpleDoc::~CSimpleDoc()
|
||
|
{
|
||
|
TestDebugOut(TEXT("In CSimpleDoc's Destructor\r\n"));
|
||
|
|
||
|
// Release all pointers we hold to the OLE object. also release
|
||
|
// the ref count added in CSimpleSite::Create. this will make
|
||
|
// the Site's ref count go to 0, and the Site will be deleted.
|
||
|
if (m_lpSite)
|
||
|
{
|
||
|
m_lpSite->UnloadOleObject();
|
||
|
m_lpSite->Release();
|
||
|
m_lpSite = NULL;
|
||
|
}
|
||
|
|
||
|
// Release the Storage
|
||
|
if (m_lpStorage)
|
||
|
{
|
||
|
m_lpStorage->Release();
|
||
|
m_lpStorage = NULL;
|
||
|
}
|
||
|
|
||
|
// if the edit menu was modified, remove the menu item and
|
||
|
// destroy the popup if it exists
|
||
|
if (m_fModifiedMenu)
|
||
|
{
|
||
|
int nCount = GetMenuItemCount(m_hEditMenu);
|
||
|
RemoveMenu(m_hEditMenu, nCount-1, MF_BYPOSITION);
|
||
|
if (m_hCascadeMenu)
|
||
|
DestroyMenu(m_hCascadeMenu);
|
||
|
}
|
||
|
|
||
|
DestroyWindow(m_hDocWnd);
|
||
|
}
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::QueryInterface
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// interface negotiation at document level
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// REFIID riid - ID of interface to be returned
|
||
|
// LPVOID FAR* ppvObj - Location to return the interface
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// E_NOINTERFACE - Always
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
// ResultFromScode OLE API
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
// In this implementation, there are no doc level interfaces.
|
||
|
// In an MDI application, there would be an IOleInPlaceUIWindow
|
||
|
// associated with the document to provide document level tool
|
||
|
// space negotiation.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP CSimpleDoc::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
||
|
{
|
||
|
TestDebugOut(TEXT("In CSimpleDoc::QueryInterface\r\n"));
|
||
|
|
||
|
*ppvObj = NULL; // must set out pointer parameters to NULL
|
||
|
|
||
|
// Not a supported interface
|
||
|
return ResultFromScode(E_NOINTERFACE);
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::AddRef
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Increments the document reference count
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// UINT - The new reference count of CSimpleDoc
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CSimpleDoc::AddRef()
|
||
|
{
|
||
|
TestDebugOut(TEXT("In CSimpleDoc::AddRef\r\n"));
|
||
|
return ++m_nCount;
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::Release
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Decrements the document reference count
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// UINT - The new reference count of CSimpleDoc
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// TestDebugOut Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CSimpleDoc::Release()
|
||
|
{
|
||
|
TestDebugOut(TEXT("In CSimpleDoc::Release\r\n"));
|
||
|
|
||
|
if (--m_nCount == 0)
|
||
|
{
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
return m_nCount;
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::InsertObject
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Inserts a new object to this document
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// CSimpleSite::CSimpleSite SITE.CPP
|
||
|
// CSimpleSite::InitObject SITE.CPP
|
||
|
// CSimpleSite::Release SITE.CPP
|
||
|
// memset C Runtime
|
||
|
// OleUIInsertObject OLE2UI function
|
||
|
// CSimpleDoc::DisableInsertObject DOC.CPP
|
||
|
// IStorage::Revert OLE API
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
// This implementation only allows one object to be inserted
|
||
|
// into a document. Once the object has been inserted, then
|
||
|
// the Insert Object menu choice is greyed out, to prevent
|
||
|
// the user from inserting another.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CSimpleDoc::InsertObject()
|
||
|
{
|
||
|
OLEUIINSERTOBJECT io;
|
||
|
UINT iret;
|
||
|
TCHAR szFile[OLEUI_CCHPATHMAX];
|
||
|
|
||
|
m_lpSite = CSimpleSite::Create(this);
|
||
|
|
||
|
if (!m_lpSite)
|
||
|
{
|
||
|
/* memory allocation problem! cannot carry on.
|
||
|
*/
|
||
|
TestDebugOut(TEXT("Memory allocation error!\n"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// clear the structure
|
||
|
_fmemset(&io, 0, sizeof(OLEUIINSERTOBJECT));
|
||
|
|
||
|
// fill the structure
|
||
|
io.cbStruct = sizeof(OLEUIINSERTOBJECT);
|
||
|
io.dwFlags = IOF_SELECTCREATENEW | IOF_DISABLELINK |
|
||
|
IOF_DISABLEDISPLAYASICON | IOF_CREATENEWOBJECT |
|
||
|
IOF_CREATEFILEOBJECT;
|
||
|
io.hWndOwner = m_hDocWnd;
|
||
|
io.lpszCaption = (LPTSTR) TEXT("Insert Object");
|
||
|
io.iid = IID_IOleObject;
|
||
|
io.oleRender = OLERENDER_DRAW;
|
||
|
io.lpIOleClientSite = &m_lpSite->m_OleClientSite;
|
||
|
io.lpIStorage = m_lpSite->m_lpObjStorage;
|
||
|
io.ppvObj = (LPVOID FAR *)&m_lpSite->m_lpOleObject;
|
||
|
io.lpszFile = szFile;
|
||
|
io.cchFile = sizeof(szFile)/sizeof(TCHAR);
|
||
|
// cchFile is the number of characters of szFile
|
||
|
_fmemset((LPTSTR)szFile, 0, sizeof(szFile));
|
||
|
|
||
|
// call OUTLUI to do all the hard work
|
||
|
iret = OleUIInsertObject(&io);
|
||
|
|
||
|
if (iret == OLEUI_OK)
|
||
|
{
|
||
|
m_lpSite->InitObject((BOOL)(io.dwFlags & IOF_SELECTCREATENEW));
|
||
|
// disable Insert Object menu item
|
||
|
DisableInsertObject();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_lpSite->Release();
|
||
|
m_lpSite = NULL;
|
||
|
m_lpStorage->Revert();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::lResizeDoc
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Resizes the document
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// LPRECT lpRect - The size of the client are of the "frame"
|
||
|
// Window.
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// NULL
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// IOleInPlaceActiveObject::ResizeBorder Object
|
||
|
// MoveWindow Windows API
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
long CSimpleDoc::lResizeDoc(LPRECT lpRect)
|
||
|
{
|
||
|
// if we are InPlace, then call ResizeBorder on the object, otherwise
|
||
|
// just move the document window.
|
||
|
if (m_fInPlaceActive)
|
||
|
m_lpActiveObject->ResizeBorder(lpRect, &m_lpApp->m_OleInPlaceFrame,
|
||
|
TRUE);
|
||
|
else
|
||
|
MoveWindow(m_hDocWnd, lpRect->left, lpRect->top, lpRect->right,
|
||
|
lpRect->bottom, TRUE);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::lAddVerbs
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Adds the objects verbs to the edit menu.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// NULL
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// GetMenuItemCount Windows API
|
||
|
// OleUIAddVerbMenu OLE2UI function
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
long CSimpleDoc::lAddVerbs(void)
|
||
|
{
|
||
|
// m_fModifiedMenu is TRUE if the menu has already been modified
|
||
|
// once. Since we only support one obect every time the application
|
||
|
// is run, then once the menu is modified, it doesn't have
|
||
|
// to be done again.
|
||
|
if (m_lpSite && !m_fInPlaceActive && !m_fModifiedMenu)
|
||
|
{
|
||
|
int nCount = GetMenuItemCount(m_hEditMenu);
|
||
|
|
||
|
if (!OleUIAddVerbMenu ( m_lpSite->m_lpOleObject,
|
||
|
NULL,
|
||
|
m_hEditMenu,
|
||
|
nCount + 1,
|
||
|
IDM_VERB0,
|
||
|
0, // no maximum verb IDM enforced
|
||
|
FALSE,
|
||
|
0,
|
||
|
&m_hCascadeMenu))
|
||
|
{
|
||
|
TestDebugOut(TEXT("Fail in OleUIAddVerbMenu"));
|
||
|
}
|
||
|
|
||
|
m_fModifiedMenu = TRUE;
|
||
|
}
|
||
|
return (NULL);
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::PaintDoc
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Paints the Document
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// HDC hDC - hDC of the document Window
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// CSimpleSite::PaintObj SITE.CPP
|
||
|
//
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CSimpleDoc::PaintDoc (HDC hDC)
|
||
|
{
|
||
|
// if we supported multiple objects, then we would enumerate
|
||
|
// the objects and call paint on each of them from here.
|
||
|
|
||
|
if (m_lpSite)
|
||
|
m_lpSite->PaintObj(hDC);
|
||
|
|
||
|
}
|
||
|
|
||
|
//**********************************************************************
|
||
|
//
|
||
|
// CSimpleDoc::DisableInsertObject
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// Disable the ability to insert a new object in this document.
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None
|
||
|
//
|
||
|
// Function Calls:
|
||
|
// Function Location
|
||
|
//
|
||
|
// EnableMenuItem Windows API
|
||
|
//
|
||
|
// Comments:
|
||
|
//
|
||
|
// This implementation only allows one object to be inserted
|
||
|
// into a document. Once the object has been inserted, then
|
||
|
// the Insert Object menu choice is greyed out, to prevent
|
||
|
// the user from inserting another.
|
||
|
//
|
||
|
//********************************************************************
|
||
|
|
||
|
void CSimpleDoc::DisableInsertObject(void)
|
||
|
{
|
||
|
// Disable InsertObject menu choice
|
||
|
EnableMenuItem( m_hEditMenu, 0, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
|
||
|
}
|