723 lines
17 KiB
C++
723 lines
17 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 "app.h"
|
|
#include "site.h"
|
|
#include "doc.h"
|
|
#include "idt.h"
|
|
#include "dxferobj.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
|
|
// RegisterDragDrop OLE API
|
|
// CoLockObjectExternal OLE API
|
|
// CreateWindow Windows API
|
|
// ShowWindow Windows API
|
|
// UpdateWindow 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, // generate temp name
|
|
STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE,
|
|
0, &lpTemp->m_lpStorage);
|
|
|
|
if (hErr != NOERROR)
|
|
goto error;
|
|
|
|
// create the document Window
|
|
lpTemp->m_hDocWnd = CreateWindow(
|
|
"SimpDndDocWClass",
|
|
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( lpApp->m_hEditMenu, 1, MF_BYPOSITION | MF_ENABLED);
|
|
// Disable Copy menu choice
|
|
EnableMenuItem( lpApp->m_hEditMenu, 0, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
|
|
|
|
// It is *REQUIRED* to hold a strong LOCK on the object that is
|
|
// registered as drop target. this call will result in at least one
|
|
// ref count held on our document. later in CSimpleDoc::Close we will
|
|
// unlock this lock which will make our document's ref count go to 0.
|
|
// when the document's ref count goes to 0, it will be deleted.
|
|
CoLockObjectExternal (&lpTemp->m_DropTarget, TRUE, 0);
|
|
|
|
// Register our window as a DropTarget
|
|
RegisterDragDrop(lpTemp->m_hDocWnd, &lpTemp->m_DropTarget);
|
|
lpTemp->m_fRegDragDrop = TRUE;
|
|
|
|
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:
|
|
//
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Function Calls:
|
|
// Function Location
|
|
//
|
|
// RevokeDragDrop OLE API
|
|
// CoLockObjectExternal OLE API
|
|
// OleFlushClipboard OLE API
|
|
// ShowWindow Windows API
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
void CSimpleDoc::Close(void)
|
|
{
|
|
TestDebugOut("In CSimpleDoc::Close\r\n");
|
|
|
|
ShowWindow(m_hDocWnd, SW_HIDE); // Hide the window
|
|
|
|
// Remove our data transfer object from clipboard if it is there.
|
|
// this will leave HGLOBAL based data behind on the clipboard
|
|
// including OLE 1.0 compatibility formats.
|
|
OleFlushClipboard();
|
|
|
|
// Revoke our window as a DropTarget
|
|
if (m_fRegDragDrop) {
|
|
RevokeDragDrop(m_hDocWnd);
|
|
m_fRegDragDrop = FALSE;
|
|
}
|
|
|
|
// Close the OLE object in our document
|
|
if (m_lpSite)
|
|
m_lpSite->CloseOleObject();
|
|
|
|
// Unlock the lock added in CSimpleDoc::Create. this will make
|
|
// the document's ref count go to 0, and the document will be deleted.
|
|
CoLockObjectExternal (&m_DropTarget, FALSE, TRUE);
|
|
}
|
|
|
|
//**********************************************************************
|
|
//
|
|
// 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
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
#pragma warning(disable : 4355) // turn off this warning. This warning
|
|
// tells us that we are passing this in
|
|
// an initializer, before "this" is through
|
|
// initializing. This is ok, because
|
|
// we just store the ptr in the other
|
|
// constructor
|
|
|
|
CSimpleDoc::CSimpleDoc(CSimpleApp FAR * lpApp,HWND hWnd)
|
|
: m_DropTarget(this), m_DropSource(this)
|
|
#pragma warning (default : 4355) // Turn the warning back on
|
|
{
|
|
TestDebugOut("In CSimpleDoc's Constructor\r\n");
|
|
m_lpApp = lpApp;
|
|
m_lpSite = NULL;
|
|
m_nCount = 0;
|
|
// set up menu handles
|
|
lpApp->m_hMainMenu = GetMenu(hWnd);
|
|
lpApp->m_hFileMenu = GetSubMenu(lpApp->m_hMainMenu, 0);
|
|
lpApp->m_hEditMenu = GetSubMenu(lpApp->m_hMainMenu, 1);
|
|
lpApp->m_hHelpMenu = GetSubMenu(lpApp->m_hMainMenu, 2);
|
|
lpApp->m_hCascadeMenu = NULL;
|
|
m_fModifiedMenu = FALSE;
|
|
|
|
// drag/drop related stuff
|
|
m_fRegDragDrop = FALSE; // is doc registered as drop target?
|
|
m_fLocalDrag = FALSE; // is doc source of the drag
|
|
m_fLocalDrop = FALSE; // was doc target of the drop
|
|
m_fCanDropCopy = FALSE; // is Drag/Drop copy/move possible?
|
|
m_fCanDropLink = FALSE; // is Drag/Drop link possible?
|
|
m_fDragLeave = FALSE; // has drag left
|
|
m_fPendingDrag = FALSE; // LButtonDown--possible drag pending
|
|
m_ptButDown.x = m_ptButDown.y = 0; // LButtonDown coordinates
|
|
}
|
|
|
|
//**********************************************************************
|
|
//
|
|
// CSimpleDoc::~CSimpleDoc
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Destructor for CSimpleDoc
|
|
//
|
|
// Parameters:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Function Calls:
|
|
// Function Location
|
|
//
|
|
// TestDebugOut Windows API
|
|
// CSimpleSite::Release SITE.CPP
|
|
// IStorage::Release OLE API
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
CSimpleDoc::~CSimpleDoc()
|
|
{
|
|
TestDebugOut("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_lpApp->m_hEditMenu);
|
|
RemoveMenu(m_lpApp->m_hEditMenu, nCount-1, MF_BYPOSITION);
|
|
if (m_lpApp->m_hCascadeMenu)
|
|
DestroyMenu(m_lpApp->m_hCascadeMenu);
|
|
}
|
|
|
|
DestroyWindow(m_hDocWnd);
|
|
}
|
|
|
|
|
|
//**********************************************************************
|
|
//
|
|
// CSimpleDoc::QueryInterface
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Return a pointer to a requested interface
|
|
//
|
|
// Parameters:
|
|
//
|
|
// REFIID riid - ID of interface to be returned
|
|
// LPVOID FAR* ppvObj - Location to return the interface
|
|
//
|
|
// Return Value:
|
|
//
|
|
// S_OK - Interface supported
|
|
// E_NOINTERFACE - Interface NOT supported
|
|
//
|
|
// Function Calls:
|
|
// Function Location
|
|
//
|
|
// TestDebugOut Windows API
|
|
// ResultFromScode OLE API
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
STDMETHODIMP CSimpleDoc::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
|
{
|
|
TestDebugOut("In CSimpleDoc::QueryInterface\r\n");
|
|
|
|
*ppvObj = NULL; // must set out pointer parameters to NULL
|
|
|
|
// looking for IUnknown
|
|
if ( riid == IID_IUnknown)
|
|
{
|
|
AddRef();
|
|
*ppvObj = this;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
// looking for IDropTarget
|
|
if ( riid == IID_IDropTarget)
|
|
{
|
|
m_DropTarget.AddRef();
|
|
*ppvObj=&m_DropTarget;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
// looking for IDropSource
|
|
if ( riid == IID_IDropSource)
|
|
{
|
|
m_DropSource.AddRef();
|
|
*ppvObj=&m_DropSource;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
// Not a supported interface
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
//**********************************************************************
|
|
//
|
|
// CSimpleDoc::AddRef
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Increments the document reference count
|
|
//
|
|
// Parameters:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// UINT - The current reference count on the document
|
|
//
|
|
// Function Calls:
|
|
// Function Location
|
|
//
|
|
// TestDebugOut Windows API
|
|
// CSimpleApp::AddRef APP.CPP
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
STDMETHODIMP_(ULONG) CSimpleDoc::AddRef()
|
|
{
|
|
TestDebugOut("In CSimpleDoc::AddRef\r\n");
|
|
return ++m_nCount;
|
|
}
|
|
|
|
//**********************************************************************
|
|
//
|
|
// CSimpleDoc::Release
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Decrements the document reference count
|
|
//
|
|
// Parameters:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// UINT - The current reference count on the document
|
|
//
|
|
// Function Calls:
|
|
// Function Location
|
|
//
|
|
// TestDebugOut Windows API
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
STDMETHODIMP_(ULONG) CSimpleDoc::Release()
|
|
{
|
|
TestDebugOut("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
|
|
// memset C Runtime
|
|
// OleUIInsertObject OUTLUI function
|
|
// CSimpleDoc::DisableInsertObject DOC.CPP
|
|
//
|
|
// 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;
|
|
char szFile[OLEUI_CCHPATHMAX];
|
|
|
|
m_lpSite = CSimpleSite::Create(this);
|
|
|
|
// 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 = (LPSTR)"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);
|
|
_fmemset((LPSTR)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
|
|
//
|
|
// MoveWindow Windows API
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
long CSimpleDoc::lResizeDoc(LPRECT lpRect)
|
|
{
|
|
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 OUTLUI function
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
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_fModifiedMenu)
|
|
{
|
|
int nCount = GetMenuItemCount(m_lpApp->m_hEditMenu);
|
|
|
|
OleUIAddVerbMenu ( m_lpSite->m_lpOleObject,
|
|
NULL,
|
|
m_lpApp->m_hEditMenu,
|
|
nCount + 1,
|
|
IDM_VERB0,
|
|
0, // no maximum verb IDM enforced
|
|
FALSE,
|
|
1,
|
|
&m_lpApp->m_hCascadeMenu);
|
|
|
|
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
|
|
//
|
|
// Comments:
|
|
//
|
|
//********************************************************************
|
|
|
|
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
|
|
//
|
|
// RevokeDragDrop OLE API
|
|
// 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. Also we revoke ourself as
|
|
// a potential drop target.
|
|
//
|
|
//********************************************************************
|
|
|
|
void CSimpleDoc::DisableInsertObject(void)
|
|
{
|
|
// Disable InsertObject menu choice
|
|
EnableMenuItem( m_lpApp->m_hEditMenu, 1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
|
|
// Enable Copy menu choice
|
|
EnableMenuItem( m_lpApp->m_hEditMenu, 0, MF_BYPOSITION | MF_ENABLED);
|
|
|
|
// We no longer accept dropping of objects
|
|
if (m_fRegDragDrop) {
|
|
RevokeDragDrop(m_hDocWnd);
|
|
m_fRegDragDrop = FALSE;
|
|
}
|
|
}
|
|
|
|
//**********************************************************************
|
|
//
|
|
// CSimpleDoc::CopyObjectToClip
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Copy the embedded OLE object to the clipboard
|
|
//
|
|
// Parameters:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
// Function Calls:
|
|
// Function Location
|
|
//
|
|
// CDataXferObj::Create DXFEROBJ.CPP
|
|
// CDataXferObj::QueryInterface DXFEROBJ.CPP
|
|
// OleSetClipboard OLE API
|
|
//
|
|
// Comments:
|
|
//
|
|
// This implementation only allows one object to be inserted
|
|
// into a document. Once the object has been inserted, then
|
|
// the Copy menu choice is enabled.
|
|
//
|
|
//********************************************************************
|
|
|
|
void CSimpleDoc::CopyObjectToClip(void)
|
|
{
|
|
LPDATAOBJECT lpDataObj;
|
|
|
|
// Create a data transfer object by cloning the existing OLE object
|
|
CDataXferObj FAR* pDataXferObj = CDataXferObj::Create(m_lpSite,NULL);
|
|
if (! pDataXferObj) {
|
|
MessageBox(NULL,"Out-of-memory","SimpDnD",MB_SYSTEMMODAL|MB_ICONHAND);
|
|
return;
|
|
}
|
|
// initially obj is created with 0 refcnt. this QI will make it go to 1.
|
|
pDataXferObj->QueryInterface(IID_IDataObject, (LPVOID FAR*)&lpDataObj);
|
|
|
|
// put out data transfer object on the clipboard. this API will AddRef.
|
|
OleSetClipboard(lpDataObj);
|
|
|
|
// Give ownership of data transfer object to clipboard
|
|
pDataXferObj->Release();
|
|
}
|