2990 lines
99 KiB
C
2990 lines
99 KiB
C
|
/*************************************************************************
|
||
|
**
|
||
|
** OLE 2 Sample Code
|
||
|
**
|
||
|
** oleapp.c
|
||
|
**
|
||
|
** This file contains functions and methods that are common to
|
||
|
** server and the client version of the app. This includes the class
|
||
|
** factory methods and all OleApp functions.
|
||
|
**
|
||
|
** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
|
||
|
**
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "outline.h"
|
||
|
#include <ole2ver.h>
|
||
|
|
||
|
OLEDBGDATA
|
||
|
|
||
|
extern LPOUTLINEAPP g_lpApp;
|
||
|
|
||
|
extern IUnknownVtbl g_OleApp_UnknownVtbl;
|
||
|
|
||
|
extern IUnknownVtbl g_OleDoc_UnknownVtbl;
|
||
|
extern IPersistFileVtbl g_OleDoc_PersistFileVtbl;
|
||
|
extern IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl;
|
||
|
extern IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl;
|
||
|
extern IDataObjectVtbl g_OleDoc_DataObjectVtbl;
|
||
|
|
||
|
#if defined( USE_DRAGDROP )
|
||
|
extern IDropTargetVtbl g_OleDoc_DropTargetVtbl;
|
||
|
extern IDropSourceVtbl g_OleDoc_DropSourceVtbl;
|
||
|
#endif // USE_DRAGDROP
|
||
|
|
||
|
#if defined( OLE_SERVER )
|
||
|
extern IOleObjectVtbl g_SvrDoc_OleObjectVtbl;
|
||
|
extern IPersistStorageVtbl g_SvrDoc_PersistStorageVtbl;
|
||
|
|
||
|
#if defined( SVR_TREATAS )
|
||
|
extern IStdMarshalInfoVtbl g_SvrDoc_StdMarshalInfoVtbl;
|
||
|
#endif // SVR_TREATAS
|
||
|
|
||
|
extern IUnknownVtbl g_PseudoObj_UnknownVtbl;
|
||
|
extern IOleObjectVtbl g_PseudoObj_OleObjectVtbl;
|
||
|
extern IDataObjectVtbl g_PseudoObj_DataObjectVtbl;
|
||
|
|
||
|
#if defined( INPLACE_SVR )
|
||
|
extern IOleInPlaceObjectVtbl g_SvrDoc_OleInPlaceObjectVtbl;
|
||
|
extern IOleInPlaceActiveObjectVtbl g_SvrDoc_OleInPlaceActiveObjectVtbl;
|
||
|
#endif // INPLACE_SVR
|
||
|
|
||
|
#endif // OLE_SERVER
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
|
||
|
extern IOleUILinkContainerVtbl g_CntrDoc_OleUILinkContainerVtbl;
|
||
|
extern IUnknownVtbl g_CntrLine_UnknownVtbl;
|
||
|
extern IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl;
|
||
|
extern IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl;
|
||
|
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
extern IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl;
|
||
|
extern IOleInPlaceFrameVtbl g_CntrApp_OleInPlaceFrameVtbl;
|
||
|
extern BOOL g_fInsideOutContainer;
|
||
|
#endif // INPLACE_CNTR
|
||
|
|
||
|
#endif // OLE_CNTR
|
||
|
|
||
|
// REVIEW: these are NOT useful end-user messages
|
||
|
static char ErrMsgCreateCF[] = "Can't create Class Factory!";
|
||
|
static char ErrMsgRegCF[] = "Can't register Class Factory!";
|
||
|
static char ErrMsgRegMF[] = "Can't register Message Filter!";
|
||
|
|
||
|
extern UINT g_uMsgHelp;
|
||
|
|
||
|
|
||
|
/* OleApp_InitInstance
|
||
|
* -------------------
|
||
|
*
|
||
|
* Initialize the app instance by creating the main frame window and
|
||
|
* performing app instance specific initializations
|
||
|
* (eg. initializing interface Vtbls).
|
||
|
*
|
||
|
* RETURNS: TRUE if the memory could be allocated, and the server app
|
||
|
* was properly initialized.
|
||
|
* FALSE otherwise
|
||
|
*
|
||
|
*/
|
||
|
BOOL OleApp_InitInstance(LPOLEAPP lpOleApp, HINSTANCE hInst, int nCmdShow)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
HRESULT hrErr;
|
||
|
DWORD dwBuildVersion = OleBuildVersion();
|
||
|
LPMALLOC lpMalloc = NULL;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_InitInstance\r\n")
|
||
|
|
||
|
lpOleApp->m_fOleInitialized = FALSE;
|
||
|
|
||
|
/* OLE2NOTE: check if the build version of the OLE2 DLL's match
|
||
|
** what our application is expecting.
|
||
|
*/
|
||
|
if (HIWORD(dwBuildVersion) != rmm || LOWORD(dwBuildVersion) < rup) {
|
||
|
OleDbgAssertSz(0, "ERROR: OLE 2.0 DLL's are NOT compatible!");
|
||
|
|
||
|
#if !defined( _DEBUG )
|
||
|
return FALSE; // Wrong version of DLL's
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
/* OLE2NOTE: Use a special debug allocator to help track down
|
||
|
** memory leaks.
|
||
|
*/
|
||
|
OleStdCreateDbAlloc(0, &lpMalloc);
|
||
|
#endif
|
||
|
/* OLE2NOTE: the OLE libraries must be properly initialized before
|
||
|
** making any calls. OleInitialize automatically calls
|
||
|
** CoInitialize. we will use the default task memory allocator
|
||
|
** therefore we pass NULL to OleInitialize.
|
||
|
*/
|
||
|
OLEDBG_BEGIN2("OleInitialize called\r\n")
|
||
|
hrErr = OleInitialize(lpMalloc);
|
||
|
|
||
|
if (FAILED(hrErr))
|
||
|
{
|
||
|
// Replacing the allocator may not be legal - try initializing
|
||
|
// without overriding the allocator
|
||
|
hrErr = OleInitialize(NULL);
|
||
|
}
|
||
|
|
||
|
OLEDBG_END2
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
/* OLE2NOTE: release the special debug allocator so that only OLE is
|
||
|
** holding on to it. later when OleUninitialize is called, then
|
||
|
** the debug allocator object will be destroyed. when the debug
|
||
|
** allocator object is destoyed, it will report (to the Output
|
||
|
** Debug Terminal) whether there are any memory leaks.
|
||
|
*/
|
||
|
if (lpMalloc) lpMalloc->lpVtbl->Release(lpMalloc);
|
||
|
#endif
|
||
|
|
||
|
if (hrErr != NOERROR) {
|
||
|
OutlineApp_ErrorMessage(lpOutlineApp,"OLE initialization failed!");
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************
|
||
|
** OLE2NOTE: we must remember the fact that OleInitialize has
|
||
|
** been call successfully. the very last thing an app must
|
||
|
** be do is properly shut down OLE by calling
|
||
|
** OleUninitialize. This call MUST be guarded! it is only
|
||
|
** allowable to call OleUninitialize if OleInitialize has
|
||
|
** been called SUCCESSFULLY.
|
||
|
*****************************************************************/
|
||
|
|
||
|
lpOleApp->m_fOleInitialized = TRUE;
|
||
|
|
||
|
// Initialize the OLE 2.0 interface method tables.
|
||
|
if (! OleApp_InitVtbls(lpOleApp))
|
||
|
goto error;
|
||
|
|
||
|
// Register OLE 2.0 clipboard formats.
|
||
|
lpOleApp->m_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE);
|
||
|
lpOleApp->m_cfEmbeddedObject = RegisterClipboardFormat(
|
||
|
CF_EMBEDDEDOBJECT
|
||
|
);
|
||
|
lpOleApp->m_cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE);
|
||
|
lpOleApp->m_cfFileName = RegisterClipboardFormat(CF_FILENAME);
|
||
|
lpOleApp->m_cfObjectDescriptor =
|
||
|
RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
|
||
|
lpOleApp->m_cfLinkSrcDescriptor =
|
||
|
RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR);
|
||
|
|
||
|
lpOleApp->m_cRef = 0;
|
||
|
lpOleApp->m_cDoc = 0;
|
||
|
lpOleApp->m_fUserCtrl = FALSE;
|
||
|
lpOleApp->m_dwRegClassFac = 0;
|
||
|
lpOleApp->m_lpClassFactory = NULL;
|
||
|
lpOleApp->m_cModalDlgActive = 0;
|
||
|
|
||
|
INIT_INTERFACEIMPL(
|
||
|
&lpOleApp->m_Unknown,
|
||
|
&g_OleApp_UnknownVtbl,
|
||
|
lpOleApp
|
||
|
);
|
||
|
|
||
|
#if defined( USE_DRAGDROP )
|
||
|
|
||
|
// delay before dragging should start, in milliseconds
|
||
|
lpOleApp->m_nDragDelay = GetProfileInt(
|
||
|
"windows",
|
||
|
"DragDelay",
|
||
|
DD_DEFDRAGDELAY
|
||
|
);
|
||
|
|
||
|
// minimum distance (radius) before drag should start, in pixels
|
||
|
lpOleApp->m_nDragMinDist = GetProfileInt(
|
||
|
"windows",
|
||
|
"DragMinDist",
|
||
|
DD_DEFDRAGMINDIST
|
||
|
);
|
||
|
|
||
|
// delay before scrolling, in milliseconds
|
||
|
lpOleApp->m_nScrollDelay = GetProfileInt(
|
||
|
"windows",
|
||
|
"DragScrollDelay",
|
||
|
DD_DEFSCROLLDELAY
|
||
|
);
|
||
|
|
||
|
// inset-width of the hot zone, in pixels
|
||
|
lpOleApp->m_nScrollInset = GetProfileInt(
|
||
|
"windows",
|
||
|
"DragScrollInset",
|
||
|
DD_DEFSCROLLINSET
|
||
|
);
|
||
|
|
||
|
// scroll interval, in milliseconds
|
||
|
lpOleApp->m_nScrollInterval = GetProfileInt(
|
||
|
"windows",
|
||
|
"DragScrollInterval",
|
||
|
DD_DEFSCROLLINTERVAL
|
||
|
);
|
||
|
|
||
|
#if defined( IF_SPECIAL_DD_CURSORS_NEEDED )
|
||
|
// This would be used if the app wanted to have custom drag/drop cursors
|
||
|
lpOleApp->m_hcursorDragNone = LoadCursor ( hInst, "DragNoneCur" );
|
||
|
lpOleApp->m_hcursorDragCopy = LoadCursor ( hInst, "DragCopyCur" );
|
||
|
lpOleApp->m_hcursorDragMove = LoadCursor ( hInst, "DragMoveCur" );
|
||
|
lpOleApp->m_hcursorDragLink = LoadCursor ( hInst, "DragLinkCur" );
|
||
|
#endif // IF_SPECIAL_DD_CURSORS_NEEDED
|
||
|
|
||
|
#endif // USE_DRAGDROP
|
||
|
|
||
|
lpOleApp->m_lpMsgFilter = NULL;
|
||
|
|
||
|
#if defined( USE_MSGFILTER )
|
||
|
/* OLE2NOTE: Register our message filter upon app startup. the
|
||
|
** message filter is used to handle concurrency.
|
||
|
** we will use a standard implementation of IMessageFilter that
|
||
|
** is included as part of the OLE2UI library.
|
||
|
*/
|
||
|
lpOleApp->m_lpMsgFilter = NULL;
|
||
|
if (! OleApp_RegisterMessageFilter(lpOleApp))
|
||
|
goto error;
|
||
|
|
||
|
/* OLE2NOTE: because our app is initially INVISIBLE, we must
|
||
|
** DISABLE the busy dialog. we should NOT put up any dialogs if
|
||
|
** our app is invisible. when our app window is made visible,
|
||
|
** then the busy dialog will be enabled.
|
||
|
*/
|
||
|
OleStdMsgFilter_EnableBusyDialog(lpOleApp->m_lpMsgFilter, FALSE);
|
||
|
#endif // USE_MSGFILTER
|
||
|
|
||
|
#if defined( OLE_SERVER )
|
||
|
/* OLE2NOTE: perform initialization specific for an OLE server */
|
||
|
if (! ServerApp_InitInstance((LPSERVERAPP)lpOutlineApp, hInst, nCmdShow))
|
||
|
goto error;
|
||
|
#endif
|
||
|
#if defined( OLE_CNTR )
|
||
|
/* OLE2NOTE: perform initialization specific for an OLE container */
|
||
|
|
||
|
// Register help message
|
||
|
g_uMsgHelp = RegisterWindowMessage(SZOLEUI_MSG_HELP);
|
||
|
|
||
|
if (! ContainerApp_InitInstance((LPCONTAINERAPP)lpOutlineApp, hInst, nCmdShow))
|
||
|
goto error;
|
||
|
#endif
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
lpOleApp->m_hStdPal = OleStdCreateStandardPalette();
|
||
|
#endif
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return TRUE;
|
||
|
|
||
|
error:
|
||
|
OLEDBG_END3
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* OleApp_TerminateApplication
|
||
|
* ---------------------------
|
||
|
* Perform proper OLE application cleanup before shutting down
|
||
|
*/
|
||
|
void OleApp_TerminateApplication(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
OLEDBG_BEGIN3("OleApp_TerminateApplication\r\n")
|
||
|
|
||
|
/* OLE2NOTE: perform a clean shut down for OLE. at this point our
|
||
|
** App refcnt should be 0, or else we should never have reached
|
||
|
** this point!
|
||
|
*/
|
||
|
OleDbgAssertSz(lpOleApp->m_cRef == 0, "App NOT shut down properly");
|
||
|
|
||
|
if(lpOleApp->m_fOleInitialized) {
|
||
|
OLEDBG_BEGIN2("OleUninitialize called\r\n")
|
||
|
OleUninitialize();
|
||
|
OLEDBG_END2
|
||
|
}
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_ParseCmdLine
|
||
|
* -------------------
|
||
|
*
|
||
|
* Parse the command line for any execution flags/arguments.
|
||
|
* OLE2NOTE: check if "-Embedding" switch is given.
|
||
|
*/
|
||
|
BOOL OleApp_ParseCmdLine(LPOLEAPP lpOleApp, LPSTR lpszCmdLine, int nCmdShow)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
char szFileName[256]; /* buffer for filename in command line */
|
||
|
BOOL fStatus = TRUE;
|
||
|
BOOL fEmbedding = FALSE;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_ParseCmdLine\r\n")
|
||
|
|
||
|
szFileName[0] = '\0';
|
||
|
ParseCmdLine(lpszCmdLine, &fEmbedding, (LPSTR)szFileName);
|
||
|
|
||
|
#if defined( MDI_VERSION )
|
||
|
/* OLE2NOTE: an MDI app would ALWAYS register its ClassFactory. it
|
||
|
** can handle multiple objects at the same time, while an SDI
|
||
|
** application can only handle a single embedded or file-based
|
||
|
** object at a time.
|
||
|
*/
|
||
|
fStatus = OleApp_RegisterClassFactory(lpOleApp);
|
||
|
#endif
|
||
|
|
||
|
if(fEmbedding) {
|
||
|
|
||
|
if (szFileName[0] == '\0') {
|
||
|
|
||
|
/*****************************************************************
|
||
|
** App was launched with /Embedding.
|
||
|
** We must register our ClassFactory with OLE, remain hidden
|
||
|
** (the app window is initially created not visible), and
|
||
|
** wait for OLE to call IClassFactory::CreateInstance
|
||
|
** method. We do not automatically create a document as we
|
||
|
** do when the app is launched by the user from the
|
||
|
** FileManager. We must NOT make our app window visible
|
||
|
** until told to do so by our container.
|
||
|
**
|
||
|
** OLE2NOTE: Because we are an SDI app, we only register our
|
||
|
** ClassFactory if we are launched with the /Embedding
|
||
|
** flag WITHOUT a filename. an MDI app would ALWAYS
|
||
|
** register its ClassFactory. it can handle multiple
|
||
|
** objects at the same time, while an SDI application
|
||
|
** can only handle a single embedded or file-based
|
||
|
** object at a time.
|
||
|
*****************************************************************/
|
||
|
|
||
|
#if defined( SDI_VERSION )
|
||
|
fStatus = OleApp_RegisterClassFactory(lpOleApp);
|
||
|
#endif
|
||
|
} else {
|
||
|
|
||
|
/*****************************************************************
|
||
|
** App was launched with /Embedding <Filename>.
|
||
|
** We must create a document and load the file and
|
||
|
** register it in the RunningObjectTable BEFORE we
|
||
|
** enter our GetMessage loop (ie. before we yield).
|
||
|
** One way to perform these tasks is to call the same
|
||
|
** interface methods that OLE 2.0 calls for linking to a
|
||
|
** file:
|
||
|
** IClassFactory::CreateInstance
|
||
|
** IPersistFile::Load
|
||
|
**
|
||
|
** We must NOT make our app window visible until told to
|
||
|
** do so by our container. An application will be
|
||
|
** launched in this manner by an OLE 1.0 application
|
||
|
** link situation (eg. double clicking a linked object
|
||
|
** or OleCreateLinkFromFile called).
|
||
|
**
|
||
|
** OLE2NOTE: Because we are an SDI app, we should NOT
|
||
|
** register our ClassFactory when we are launched with the
|
||
|
** /Embedding <Filename> flag. our SDI instance can only
|
||
|
** handle a single embedded or file-based object.
|
||
|
** an MDI app WOULD register its ClassFactory at all
|
||
|
** times because it can handle multiple objects.
|
||
|
*****************************************************************/
|
||
|
|
||
|
// allocate a new document object
|
||
|
lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE);
|
||
|
if (! lpOutlineApp->m_lpDoc) {
|
||
|
OLEDBG_END3
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/* OLE2NOTE: initially the Doc object is created with a 0 ref
|
||
|
** count. in order to have a stable Doc object during the
|
||
|
** process of initializing the new Doc instance,
|
||
|
** we intially AddRef the Doc ref cnt and later
|
||
|
** Release it. This initial AddRef is artificial; it is simply
|
||
|
** done to guarantee that a harmless QueryInterface followed by
|
||
|
** a Release does not inadvertantly force our object to destroy
|
||
|
** itself prematurely.
|
||
|
*/
|
||
|
OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
/* OLE2NOTE: OutlineDoc_LoadFromFile will register our document
|
||
|
** in the RunningObjectTable. this registration will
|
||
|
** AddRef our document. therefore our document will not
|
||
|
** be destroyed when we release the artificial AddRef
|
||
|
*/
|
||
|
fStatus = OutlineDoc_LoadFromFile(
|
||
|
lpOutlineApp->m_lpDoc, (LPSTR)szFileName);
|
||
|
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel AddRef
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return fStatus;
|
||
|
}
|
||
|
} else {
|
||
|
|
||
|
/*****************************************************************
|
||
|
** App was launched by the user (without /Embedding) and
|
||
|
** therefore is marked to be under user control.
|
||
|
** In this case, because we are an SDI app, we do NOT
|
||
|
** register our ClassFactory with OLE. This app instance can
|
||
|
** only manage one document at a time (either a user
|
||
|
** document or an embedded object document). An MDI app
|
||
|
** would register its ClassFactory here.
|
||
|
**
|
||
|
** We must create a document for the user (either
|
||
|
** initialized from a file given on the command line or
|
||
|
** initialized as an untitled document. We must also make
|
||
|
** our app window visible to the user.
|
||
|
*****************************************************************/
|
||
|
|
||
|
// allocate a new document object
|
||
|
lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE);
|
||
|
if (! lpOutlineApp->m_lpDoc) goto error;
|
||
|
|
||
|
/* OLE2NOTE: initially the Doc object is created with a 0 ref
|
||
|
** count. in order to have a stable Doc object during the
|
||
|
** process of initializing the new Doc instance,
|
||
|
** we intially AddRef the Doc ref cnt and later
|
||
|
** Release it. This initial AddRef is artificial; it is simply
|
||
|
** done to guarantee that a harmless QueryInterface followed by
|
||
|
** a Release does not inadvertantly force our object to destroy
|
||
|
** itself prematurely.
|
||
|
*/
|
||
|
OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
if(*szFileName) {
|
||
|
// initialize the document from the specified file
|
||
|
if (! OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, szFileName))
|
||
|
goto error;
|
||
|
} else {
|
||
|
// set the doc to an (Untitled) doc.
|
||
|
if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc))
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
// position and size the new doc window
|
||
|
OutlineApp_ResizeWindows(lpOutlineApp);
|
||
|
OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);// rel AddRef above
|
||
|
|
||
|
// show main app window
|
||
|
ShowWindow(lpOutlineApp->m_hWndApp, nCmdShow);
|
||
|
UpdateWindow(lpOutlineApp->m_hWndApp);
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
ContainerDoc_UpdateLinks((LPCONTAINERDOC)lpOutlineApp->m_lpDoc);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return fStatus;
|
||
|
|
||
|
error:
|
||
|
// REVIEW: should load string from string resource
|
||
|
OutlineApp_ErrorMessage(
|
||
|
lpOutlineApp,
|
||
|
"Could not create document--Out of Memory"
|
||
|
);
|
||
|
if (lpOutlineApp->m_lpDoc) // rel artificial AddRef above
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_CloseAllDocsAndExitCommand
|
||
|
* ---------------------------------
|
||
|
*
|
||
|
* Close all active documents and exit the app.
|
||
|
* Because this is an SDI, there is only one document
|
||
|
* If the doc was modified, prompt the user if he wants to save it.
|
||
|
*
|
||
|
* Returns:
|
||
|
* TRUE if the app is successfully closed
|
||
|
* FALSE if failed or aborted
|
||
|
*
|
||
|
* OLE2NOTE: in the OLE version, we can NOT directly
|
||
|
* destroy the App object. we can only take all
|
||
|
* necessary actions to ensure that our object receives
|
||
|
* all of its Releases from clients holding onto
|
||
|
* pointers (eg. closing all docs and flushing the
|
||
|
* clipboard) and then we must hide our window and wait
|
||
|
* actually for our refcnt to reach 0. when it reaches 0,
|
||
|
* our destructor (OutlineApp_Destroy) will be called.
|
||
|
* each document addref's the app object in order to
|
||
|
* guarentee that the app does not shut down while the doc
|
||
|
* is still open. closing all docs, will release these
|
||
|
* refcnt's. if there are now more open documents AND the
|
||
|
* app is not under the control of the user (ie. launched by
|
||
|
* OLE) then the app will now shut down. the OleApp_Release
|
||
|
* function executes this shut down procedure. after closing
|
||
|
* all docs, then releasing the user refcnt will force the
|
||
|
* app to shut down.
|
||
|
*/
|
||
|
BOOL OleApp_CloseAllDocsAndExitCommand(
|
||
|
LPOLEAPP lpOleApp,
|
||
|
BOOL fForceEndSession
|
||
|
)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
DWORD dwSaveOption = (fForceEndSession ?
|
||
|
OLECLOSE_NOSAVE : OLECLOSE_PROMPTSAVE);
|
||
|
|
||
|
/* OLE2NOTE: in order to have a stable App object during the
|
||
|
** process of closing, we intially AddRef the App ref cnt and
|
||
|
** later Release it. This initial AddRef is artificial; it is
|
||
|
** simply done to guarantee that our App object does not
|
||
|
** destroy itself until the end of this routine.
|
||
|
*/
|
||
|
OleApp_AddRef(lpOleApp);
|
||
|
|
||
|
/* Because this is an SDI app, there is only one document.
|
||
|
** Close the doc. if it is successfully closed and the app will
|
||
|
** not automatically exit, then also exit the app.
|
||
|
** if this were an MDI app, we would loop through and close all
|
||
|
** open MDI child documents.
|
||
|
*/
|
||
|
|
||
|
#if defined( OLE_SERVER )
|
||
|
if (!fForceEndSession &&
|
||
|
lpOutlineApp->m_lpDoc->m_docInitType == DOCTYPE_EMBEDDED)
|
||
|
dwSaveOption = OLECLOSE_SAVEIFDIRTY;
|
||
|
#endif
|
||
|
|
||
|
if (! OutlineDoc_Close(lpOutlineApp->m_lpDoc, dwSaveOption)) {
|
||
|
OleApp_Release(lpOleApp);
|
||
|
return FALSE; // User Aborted shutdown
|
||
|
}
|
||
|
#if defined( _DEBUG )
|
||
|
OleDbgAssertSz(
|
||
|
lpOutlineApp->m_lpDoc==NULL,
|
||
|
"Closed doc NOT properly destroyed"
|
||
|
);
|
||
|
#endif
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
/* if we currently have data on the clipboard then we must tell
|
||
|
** the clipboard to release our clipboard data object
|
||
|
** (document)
|
||
|
*/
|
||
|
if (lpOutlineApp->m_lpClipboardDoc)
|
||
|
OleApp_FlushClipboard(lpOleApp);
|
||
|
#endif
|
||
|
|
||
|
OleApp_HideWindow(lpOleApp);
|
||
|
|
||
|
/* OLE2NOTE: this call forces all external connections to our
|
||
|
** object to close down and therefore guarantees that we receive
|
||
|
** all releases associated with those external connections.
|
||
|
*/
|
||
|
OLEDBG_BEGIN2("CoDisconnectObject(lpApp) called\r\n")
|
||
|
CoDisconnectObject((LPUNKNOWN)&lpOleApp->m_Unknown, 0);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
OleApp_Release(lpOleApp); // release artificial AddRef above
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_ShowWindow
|
||
|
* -----------------
|
||
|
*
|
||
|
* Show the window of the app to the user.
|
||
|
* make sure app window is visible and bring the app to the top.
|
||
|
* IF fGiveUserCtrl == TRUE
|
||
|
* THEN give the user the control over the life-time of the app.
|
||
|
*/
|
||
|
void OleApp_ShowWindow(LPOLEAPP lpOleApp, BOOL fGiveUserCtrl)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_ShowWindow\r\n")
|
||
|
|
||
|
/* OLE2NOTE: while the application is visible and under user
|
||
|
** control, we do NOT want it to be prematurely destroyed when
|
||
|
** the user closes a document. thus we must inform OLE to hold
|
||
|
** an external lock on our application on behalf of the user.
|
||
|
** this arranges that OLE holds at least 1 reference to our
|
||
|
** application that will NOT be released until we release this
|
||
|
** external lock. later, when the application window is hidden, we
|
||
|
** will release this external lock.
|
||
|
*/
|
||
|
if (fGiveUserCtrl && ! lpOleApp->m_fUserCtrl) {
|
||
|
lpOleApp->m_fUserCtrl = TRUE;
|
||
|
OleApp_Lock(lpOleApp, TRUE /* fLock */, 0 /* not applicable */);
|
||
|
}
|
||
|
|
||
|
// we must show our App window and force it to have input focus
|
||
|
ShowWindow(lpOutlineApp->m_hWndApp, SW_SHOWNORMAL);
|
||
|
SetFocus(lpOutlineApp->m_hWndApp);
|
||
|
|
||
|
/* OLE2NOTE: because our app is now visible, we can enable the busy
|
||
|
** dialog. we should NOT put up any dialogs if our app is
|
||
|
** invisible.
|
||
|
*/
|
||
|
OleApp_EnableBusyDialogs(lpOleApp, TRUE, TRUE);
|
||
|
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_HideWindow
|
||
|
* -----------------
|
||
|
*
|
||
|
* Hide the window of the app from the user.
|
||
|
* take away the control of the app by the user.
|
||
|
*/
|
||
|
void OleApp_HideWindow(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_HideWindow\r\n")
|
||
|
|
||
|
/* OLE2NOTE: the application is now being hidden, so we must release
|
||
|
** the external lock that was made on behalf of the user.
|
||
|
** if this is that last external lock on our application, thus
|
||
|
** enabling our application to complete its shutdown operation.
|
||
|
*/
|
||
|
if (lpOleApp->m_fUserCtrl) {
|
||
|
lpOleApp->m_fUserCtrl = FALSE;
|
||
|
OleApp_Lock(lpOleApp, FALSE /*fLock*/, TRUE /*fLastUnlockReleases*/);
|
||
|
}
|
||
|
|
||
|
ShowWindow(lpOutlineApp->m_hWndApp, SW_HIDE);
|
||
|
|
||
|
/* OLE2NOTE: because our app is now INVISIBLE, we must DISABLE the busy
|
||
|
** dialog. we should NOT put up any dialogs if our app is
|
||
|
** invisible.
|
||
|
*/
|
||
|
OleApp_EnableBusyDialogs(lpOleApp, FALSE, FALSE);
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_Lock
|
||
|
** -----------
|
||
|
** Lock/Unlock the App object. if the last lock is unlocked and
|
||
|
** fLastUnlockReleases == TRUE, then the app object will shut down
|
||
|
** (ie. it will recieve its final release and its refcnt will go to 0).
|
||
|
*/
|
||
|
HRESULT OleApp_Lock(LPOLEAPP lpOleApp, BOOL fLock, BOOL fLastUnlockReleases)
|
||
|
{
|
||
|
HRESULT hrErr;
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
if (fLock) {
|
||
|
OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,TRUE) called\r\n")
|
||
|
} else {
|
||
|
if (fLastUnlockReleases)
|
||
|
OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,FALSE,TRUE) called\r\n")
|
||
|
else
|
||
|
OLEDBG_BEGIN2("CoLockObjectExternal(lpApp,FALSE,FALSE) called\r\n")
|
||
|
}
|
||
|
#endif // _DEBUG
|
||
|
|
||
|
OleApp_AddRef(lpOleApp); // artificial AddRef to make object stable
|
||
|
|
||
|
hrErr = CoLockObjectExternal(
|
||
|
(LPUNKNOWN)&lpOleApp->m_Unknown, fLock, fLastUnlockReleases);
|
||
|
|
||
|
OleApp_Release(lpOleApp); // release artificial AddRef above
|
||
|
|
||
|
OLEDBG_END2
|
||
|
return hrErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_Destroy
|
||
|
* --------------
|
||
|
*
|
||
|
* Free all OLE related resources that had been allocated for the app.
|
||
|
*/
|
||
|
void OleApp_Destroy(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
// OLE2NOTE: Revoke our message filter upon app shutdown.
|
||
|
OleApp_RevokeMessageFilter(lpOleApp);
|
||
|
|
||
|
// OLE2NOTE: Revoke our ClassFactory upon app shutdown.
|
||
|
OleApp_RevokeClassFactory(lpOleApp);
|
||
|
|
||
|
#if defined( IF_SPECIAL_DD_CURSORS_NEEDED )
|
||
|
// This would be used if the app wanted to have custom drag/drop cursors
|
||
|
DestroyCursor(lpOleApp->m_hcursorDragNone);
|
||
|
DestroyCursor(lpOleApp->m_hcursorDragCopy);
|
||
|
DestroyCursor(lpOleApp->m_hcursorDragLink);
|
||
|
DestroyCursor(lpOleApp->m_hcursorDragMove);
|
||
|
#endif // IF_SPECIAL_DD_CURSORS_NEEDED
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
if (lpOleApp->m_hStdPal) {
|
||
|
DeleteObject(lpOleApp->m_hStdPal);
|
||
|
lpOleApp->m_hStdPal = NULL;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_DocLockApp
|
||
|
** -----------------
|
||
|
** Add a lock on the App on behalf of the Doc. the App may not close
|
||
|
** while the Doc exists.
|
||
|
**
|
||
|
** when a document is first created, it calls this method to
|
||
|
** guarantee that the application stays alive (OleDoc_Init).
|
||
|
** when a document is destroyed, it calls
|
||
|
** OleApp_DocUnlockApp to release this hold on the app.
|
||
|
*/
|
||
|
void OleApp_DocLockApp(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
ULONG cDoc;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_DocLockApp\r\n")
|
||
|
|
||
|
cDoc = ++lpOleApp->m_cDoc;
|
||
|
|
||
|
OleDbgOutRefCnt3("OleApp_DocLockApp: cDoc++\r\n", lpOleApp, cDoc);
|
||
|
|
||
|
OleApp_Lock(lpOleApp, TRUE /* fLock */, 0 /* not applicable */);
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_DocUnlockApp
|
||
|
** -------------------
|
||
|
** Forget all references to a closed document.
|
||
|
** Release the lock on the App on behalf of the Doc. if this was the
|
||
|
** last lock on the app, then it will shutdown.
|
||
|
*/
|
||
|
void OleApp_DocUnlockApp(LPOLEAPP lpOleApp, LPOUTLINEDOC lpOutlineDoc)
|
||
|
{
|
||
|
ULONG cDoc;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_DocUnlockApp\r\n")
|
||
|
|
||
|
/* OLE2NOTE: when there are no open documents and the app is not
|
||
|
** under the control of the user then revoke our ClassFactory to
|
||
|
** enable the app to shut down.
|
||
|
*/
|
||
|
cDoc = --lpOleApp->m_cDoc;
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
OleDbgAssertSz (
|
||
|
lpOleApp->m_cDoc >= 0, "DocUnlockApp called with cDoc == 0");
|
||
|
|
||
|
OleDbgOutRefCnt3(
|
||
|
"OleApp_DocUnlockApp: cDoc--\r\n", lpOleApp, cDoc);
|
||
|
#endif
|
||
|
|
||
|
OleApp_Lock(lpOleApp, FALSE /* fLock */, TRUE /* fLastUnlockReleases */);
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_HideIfNoReasonToStayVisible
|
||
|
** ----------------------------------
|
||
|
**
|
||
|
** if there are no more documents visible to the user and the app
|
||
|
** itself is not under user control, then it has no reason to stay
|
||
|
** visible. we thus should hide the app. we can not directly destroy
|
||
|
** the app, because it may be validly being used programatically by
|
||
|
** another client application and should remain running. the app
|
||
|
** should simply be hidden from the user.
|
||
|
*/
|
||
|
void OleApp_HideIfNoReasonToStayVisible(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
LPOUTLINEDOC lpOutlineDoc;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_HideIfNoReasonToStayVisible\r\n")
|
||
|
|
||
|
if (lpOleApp->m_fUserCtrl) {
|
||
|
OLEDBG_END3
|
||
|
return; // remain visible; user in control of app
|
||
|
}
|
||
|
|
||
|
/* Because this is an SDI app, there is only one user document.
|
||
|
** check if it is visible to the user. an MDI app would loop over
|
||
|
** all open MDI child documents to see if any are visible.
|
||
|
*/
|
||
|
lpOutlineDoc = (LPOUTLINEDOC)lpOutlineApp->m_lpDoc;
|
||
|
if (lpOutlineDoc && IsWindowVisible(lpOutlineDoc->m_hWndDoc))
|
||
|
return; // remain visible; the doc is visible to the user
|
||
|
|
||
|
// if we reached here, the app should be hidden
|
||
|
OleApp_HideWindow(lpOleApp);
|
||
|
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_AddRef
|
||
|
** -------------
|
||
|
**
|
||
|
** increment the ref count of the App object.
|
||
|
**
|
||
|
** Returns the new ref count on the object
|
||
|
*/
|
||
|
ULONG OleApp_AddRef(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
++lpOleApp->m_cRef;
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
OleDbgOutRefCnt4(
|
||
|
"OleApp_AddRef: cRef++\r\n",
|
||
|
lpOleApp,
|
||
|
lpOleApp->m_cRef
|
||
|
);
|
||
|
#endif
|
||
|
return lpOleApp->m_cRef;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_Release
|
||
|
** --------------
|
||
|
**
|
||
|
** decrement the ref count of the App object.
|
||
|
** if the ref count goes to 0, then the app object is destroyed.
|
||
|
**
|
||
|
** Returns the remaining ref count on the object
|
||
|
*/
|
||
|
ULONG OleApp_Release (LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
ULONG cRef;
|
||
|
|
||
|
cRef = --lpOleApp->m_cRef;
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
OleDbgAssertSz (lpOleApp->m_cRef >= 0, "Release called with cRef == 0");
|
||
|
|
||
|
OleDbgOutRefCnt4(
|
||
|
"OleApp_AddRef: cRef--\r\n", lpOleApp, cRef);
|
||
|
#endif // _DEBUG
|
||
|
/*********************************************************************
|
||
|
** OLE2NOTE: when the ClassFactory refcnt == 0, then destroy it. **
|
||
|
** otherwise the ClassFactory is still in use. **
|
||
|
*********************************************************************/
|
||
|
|
||
|
if(cRef == 0)
|
||
|
OutlineApp_Destroy((LPOUTLINEAPP)lpOleApp);
|
||
|
|
||
|
return cRef;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* OleApp_QueryInterface
|
||
|
** ---------------------
|
||
|
**
|
||
|
** Retrieve a pointer to an interface on the app object.
|
||
|
**
|
||
|
** OLE2NOTE: this function will AddRef the ref cnt of the object.
|
||
|
**
|
||
|
** Returns NOERROR if interface is successfully retrieved.
|
||
|
** E_NOINTERFACE if the interface is not supported
|
||
|
*/
|
||
|
HRESULT OleApp_QueryInterface (
|
||
|
LPOLEAPP lpOleApp,
|
||
|
REFIID riid,
|
||
|
LPVOID FAR* lplpvObj
|
||
|
)
|
||
|
{
|
||
|
SCODE sc;
|
||
|
|
||
|
/* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
|
||
|
*lplpvObj = NULL;
|
||
|
|
||
|
if (IsEqualIID(riid, &IID_IUnknown)) {
|
||
|
OleDbgOut4("OleApp_QueryInterface: IUnknown* RETURNED\r\n");
|
||
|
|
||
|
*lplpvObj = (LPVOID) &lpOleApp->m_Unknown;
|
||
|
OleApp_AddRef(lpOleApp);
|
||
|
sc = S_OK;
|
||
|
}
|
||
|
else {
|
||
|
sc = E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
OleDbgQueryInterfaceMethod(*lplpvObj);
|
||
|
return ResultFromScode(sc);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_RejectInComingCalls
|
||
|
** -------------------------
|
||
|
** Reject/Handle in coming OLE (LRPC) calls.
|
||
|
**
|
||
|
** OLE2NOTE: if the app is in a state when it can NOT handle in
|
||
|
** coming OLE method calls from an external process (eg. the app has
|
||
|
** an application modal dialog up), then it should call
|
||
|
** OleApp_RejectInComingCalls(TRUE). in this state the
|
||
|
** IMessageFilter::HandleInComingCall method will return
|
||
|
** SERVERCALL_RETRYLATER. this tells the caller to try again in a
|
||
|
** little while. normally the calling app will put up a dialog (see
|
||
|
** OleUIBusy dialog) in this situation informing the user of the
|
||
|
** situation. the user then is normally given the option to
|
||
|
** "Switch To..." the busy application, retry, or cancel the
|
||
|
** operation. when the app is ready to continue processing such
|
||
|
** calls, it should call OleApp_RejectInComingCalls(FALSE). in this
|
||
|
** state, SERVERCALL_ISHANDLED is returned by
|
||
|
** IMessageFilter::HandleInComingCall.
|
||
|
*/
|
||
|
void OleApp_RejectInComingCalls(LPOLEAPP lpOleApp, BOOL fReject)
|
||
|
{
|
||
|
#if defined( _DEBUG )
|
||
|
if (fReject)
|
||
|
OleDbgOut3("OleApp_RejectInComingCalls(TRUE)\r\n");
|
||
|
else
|
||
|
OleDbgOut3("OleApp_RejectInComingCalls(FALSE)\r\n");
|
||
|
#endif // _DEBUG
|
||
|
|
||
|
OleDbgAssert(lpOleApp->m_lpMsgFilter != NULL);
|
||
|
if (! lpOleApp->m_lpMsgFilter)
|
||
|
return;
|
||
|
|
||
|
OleStdMsgFilter_SetInComingCallStatus(
|
||
|
lpOleApp->m_lpMsgFilter,
|
||
|
(fReject ? SERVERCALL_RETRYLATER : SERVERCALL_ISHANDLED)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_DisableBusyDialogs
|
||
|
** -------------------------
|
||
|
** Disable the Busy and NotResponding dialogs.
|
||
|
**
|
||
|
** Returns previous enable state so that it can be restored by
|
||
|
** calling OleApp_ReEnableBusyDialogs.
|
||
|
*/
|
||
|
void OleApp_DisableBusyDialogs(
|
||
|
LPOLEAPP lpOleApp,
|
||
|
BOOL FAR* lpfPrevBusyEnable,
|
||
|
BOOL FAR* lpfPrevNREnable
|
||
|
)
|
||
|
{
|
||
|
if (lpOleApp->m_lpMsgFilter) {
|
||
|
*lpfPrevNREnable = OleStdMsgFilter_EnableNotRespondingDialog(
|
||
|
lpOleApp->m_lpMsgFilter, FALSE);
|
||
|
*lpfPrevBusyEnable = OleStdMsgFilter_EnableBusyDialog(
|
||
|
lpOleApp->m_lpMsgFilter, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_EnableBusyDialogs
|
||
|
** ------------------------
|
||
|
** Set the enable state of the Busy and NotResponding dialogs.
|
||
|
**
|
||
|
** This function is typically used after a call to
|
||
|
** OleApp_DisableBusyDialogs in order to restore the previous enable
|
||
|
** state of the dialogs.
|
||
|
*/
|
||
|
void OleApp_EnableBusyDialogs(
|
||
|
LPOLEAPP lpOleApp,
|
||
|
BOOL fPrevBusyEnable,
|
||
|
BOOL fPrevNREnable
|
||
|
)
|
||
|
{
|
||
|
if (lpOleApp->m_lpMsgFilter) {
|
||
|
OleStdMsgFilter_EnableNotRespondingDialog(
|
||
|
lpOleApp->m_lpMsgFilter, fPrevNREnable);
|
||
|
OleStdMsgFilter_EnableBusyDialog(
|
||
|
lpOleApp->m_lpMsgFilter, fPrevBusyEnable);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_PreModalDialog
|
||
|
** ---------------------
|
||
|
** Keep track that a modal dialog is about to be brought up.
|
||
|
**
|
||
|
** while a modal dialog is up we need to take special actions:
|
||
|
** 1. we do NOT want to initialize our tool bar buttons on
|
||
|
** WM_ACTIVATEAPP. the tool bar is not accessible.
|
||
|
** 2. we want to reject new top-level, incoming LRPC calls
|
||
|
** (return SERVERCALL_RETRYLATER from IMessageFilter::
|
||
|
** HandleInComingCall).
|
||
|
** 3. (IN-PLACE SERVER) tell our in-place container to disable
|
||
|
** modeless dialogs by calling IOleInPlaceFrame::
|
||
|
** EnableModeless(FALSE).
|
||
|
** 4. (IN-PLACE CONTAINER) tell our UIActive in-place object to
|
||
|
** disable modeless dialogs by calling IOleInPlaceActiveObject::
|
||
|
** EnableModeless(FALSE).
|
||
|
*/
|
||
|
void OleApp_PreModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc)
|
||
|
{
|
||
|
if (lpOleApp->m_cModalDlgActive == 0) {
|
||
|
// top-level modal dialog is being brought up
|
||
|
|
||
|
#if defined( USE_FRAMETOOLS )
|
||
|
LPFRAMETOOLS lptb;
|
||
|
|
||
|
if (lpOleDoc)
|
||
|
lptb = ((LPOUTLINEDOC)lpOleDoc)->m_lpFrameTools;
|
||
|
else
|
||
|
lptb = OutlineApp_GetFrameTools((LPOUTLINEAPP)lpOleApp);
|
||
|
if (lptb)
|
||
|
FrameTools_EnableWindow(lptb, FALSE);
|
||
|
#endif // USE_FRAMETOOLS
|
||
|
|
||
|
OleApp_RejectInComingCalls(lpOleApp, TRUE);
|
||
|
|
||
|
#if defined( INPLACE_SVR )
|
||
|
{
|
||
|
LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
|
||
|
|
||
|
/* if the document bringing up the modal dialog is
|
||
|
** currently a UIActive in-place object, then tell the
|
||
|
** top-level in-place frame to disable its modeless
|
||
|
** dialogs.
|
||
|
*/
|
||
|
if (lpServerDoc && lpServerDoc->m_fUIActive &&
|
||
|
lpServerDoc->m_lpIPData &&
|
||
|
lpServerDoc->m_lpIPData->lpFrame) {
|
||
|
OLEDBG_BEGIN2("IOleInPlaceFrame::EnableModless(FALSE) called\r\n");
|
||
|
lpServerDoc->m_lpIPData->lpFrame->lpVtbl->EnableModeless(
|
||
|
lpServerDoc->m_lpIPData->lpFrame, FALSE);
|
||
|
OLEDBG_END2
|
||
|
}
|
||
|
}
|
||
|
#endif // INPLACE_SVR
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
{
|
||
|
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp;
|
||
|
|
||
|
/* if the document bringing up the modal dialog is an
|
||
|
** in-place container that has a UIActive object, then
|
||
|
** tell the UIActive object to disable its modeless
|
||
|
** dialogs.
|
||
|
*/
|
||
|
if (lpContainerApp->m_lpIPActiveObj) {
|
||
|
OLEDBG_BEGIN2("IOleInPlaceActiveObject::EnableModless(FALSE) called\r\n");
|
||
|
lpContainerApp->m_lpIPActiveObj->lpVtbl->EnableModeless(
|
||
|
lpContainerApp->m_lpIPActiveObj, FALSE);
|
||
|
OLEDBG_END2
|
||
|
}
|
||
|
}
|
||
|
#endif // INPLACE_CNTR
|
||
|
}
|
||
|
|
||
|
lpOleApp->m_cModalDlgActive++;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_PostModalDialog
|
||
|
** ----------------------
|
||
|
** Keep track that a modal dialog is being brought down. this call
|
||
|
** balances the OleApp_PreModalDialog call.
|
||
|
*/
|
||
|
void OleApp_PostModalDialog(LPOLEAPP lpOleApp, LPOLEDOC lpOleDoc)
|
||
|
{
|
||
|
lpOleApp->m_cModalDlgActive--;
|
||
|
|
||
|
if (lpOleApp->m_cModalDlgActive == 0) {
|
||
|
// last modal dialog is being brought down
|
||
|
|
||
|
#if defined( USE_FRAMETOOLS )
|
||
|
LPFRAMETOOLS lptb;
|
||
|
|
||
|
if (lpOleDoc)
|
||
|
lptb = ((LPOUTLINEDOC)lpOleDoc)->m_lpFrameTools;
|
||
|
else
|
||
|
lptb = OutlineApp_GetFrameTools((LPOUTLINEAPP)lpOleApp);
|
||
|
if (lptb) {
|
||
|
FrameTools_EnableWindow(lptb, TRUE);
|
||
|
FrameTools_UpdateButtons(lptb, (LPOUTLINEDOC)lpOleDoc);
|
||
|
}
|
||
|
#endif // USE_FRAMETOOLS
|
||
|
|
||
|
OleApp_RejectInComingCalls(lpOleApp, FALSE);
|
||
|
|
||
|
#if defined( INPLACE_SVR )
|
||
|
{
|
||
|
LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
|
||
|
|
||
|
/* if the document bringing down the modal dialog is
|
||
|
** currently a UIActive in-place object, then tell the
|
||
|
** top-level in-place frame it can re-enable its
|
||
|
** modeless dialogs.
|
||
|
*/
|
||
|
if (lpServerDoc && lpServerDoc->m_fUIActive &&
|
||
|
lpServerDoc->m_lpIPData &&
|
||
|
lpServerDoc->m_lpIPData->lpFrame) {
|
||
|
OLEDBG_BEGIN2("IOleInPlaceFrame::EnableModless(TRUE) called\r\n");
|
||
|
lpServerDoc->m_lpIPData->lpFrame->lpVtbl->EnableModeless(
|
||
|
lpServerDoc->m_lpIPData->lpFrame, TRUE);
|
||
|
OLEDBG_END2
|
||
|
}
|
||
|
}
|
||
|
#endif // INPLACE_SVR
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
{
|
||
|
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp;
|
||
|
|
||
|
/* if the document bringing down the modal dialog is an
|
||
|
** in-place container that has a UIActive object, then
|
||
|
** tell the UIActive object it can re-enable its
|
||
|
** modeless dialogs.
|
||
|
*/
|
||
|
if (lpContainerApp->m_lpIPActiveObj) {
|
||
|
OLEDBG_BEGIN2("IOleInPlaceActiveObject::EnableModless(TRUE) called\r\n");
|
||
|
lpContainerApp->m_lpIPActiveObj->lpVtbl->EnableModeless(
|
||
|
lpContainerApp->m_lpIPActiveObj, TRUE);
|
||
|
OLEDBG_END2
|
||
|
}
|
||
|
}
|
||
|
#endif // INPLACE_CNTR
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_InitVtbls
|
||
|
* ----------------
|
||
|
*
|
||
|
* initialize the methods in all of the interface Vtbl's
|
||
|
*
|
||
|
* OLE2NOTE: we only need one copy of each Vtbl. When an object which
|
||
|
* exposes an interface is instantiated, its lpVtbl is intialized
|
||
|
* to point to the single copy of the Vtbl.
|
||
|
*
|
||
|
*/
|
||
|
BOOL OleApp_InitVtbls (LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
BOOL fStatus;
|
||
|
|
||
|
// OleApp::IUnknown method table
|
||
|
OleStdInitVtbl(&g_OleApp_UnknownVtbl, sizeof(IUnknownVtbl));
|
||
|
g_OleApp_UnknownVtbl.QueryInterface = OleApp_Unk_QueryInterface;
|
||
|
g_OleApp_UnknownVtbl.AddRef = OleApp_Unk_AddRef;
|
||
|
g_OleApp_UnknownVtbl.Release = OleApp_Unk_Release;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleApp_UnknownVtbl,
|
||
|
sizeof(IUnknownVtbl),
|
||
|
"IUnknown"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// OleDoc::IUnknown method table
|
||
|
OleStdInitVtbl(&g_OleDoc_UnknownVtbl, sizeof(IUnknownVtbl));
|
||
|
g_OleDoc_UnknownVtbl.QueryInterface = OleDoc_Unk_QueryInterface;
|
||
|
g_OleDoc_UnknownVtbl.AddRef = OleDoc_Unk_AddRef;
|
||
|
g_OleDoc_UnknownVtbl.Release = OleDoc_Unk_Release;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_UnknownVtbl,
|
||
|
sizeof(IUnknownVtbl),
|
||
|
"IUnknown"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// OleDoc::IPersistFile method table
|
||
|
OleStdInitVtbl(&g_OleDoc_PersistFileVtbl, sizeof(IPersistFileVtbl));
|
||
|
g_OleDoc_PersistFileVtbl.QueryInterface = OleDoc_PFile_QueryInterface;
|
||
|
g_OleDoc_PersistFileVtbl.AddRef = OleDoc_PFile_AddRef;
|
||
|
g_OleDoc_PersistFileVtbl.Release = OleDoc_PFile_Release;
|
||
|
g_OleDoc_PersistFileVtbl.GetClassID = OleDoc_PFile_GetClassID;
|
||
|
g_OleDoc_PersistFileVtbl.IsDirty = OleDoc_PFile_IsDirty;
|
||
|
g_OleDoc_PersistFileVtbl.Load = OleDoc_PFile_Load;
|
||
|
g_OleDoc_PersistFileVtbl.Save = OleDoc_PFile_Save;
|
||
|
g_OleDoc_PersistFileVtbl.SaveCompleted = OleDoc_PFile_SaveCompleted;
|
||
|
g_OleDoc_PersistFileVtbl.GetCurFile = OleDoc_PFile_GetCurFile;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_PersistFileVtbl,
|
||
|
sizeof(IPersistFileVtbl),
|
||
|
"IPersistFile"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// OleDoc::IOleItemContainer method table
|
||
|
OleStdInitVtbl(&g_OleDoc_OleItemContainerVtbl, sizeof(IOleItemContainerVtbl));
|
||
|
g_OleDoc_OleItemContainerVtbl.QueryInterface =
|
||
|
OleDoc_ItemCont_QueryInterface;
|
||
|
g_OleDoc_OleItemContainerVtbl.AddRef = OleDoc_ItemCont_AddRef;
|
||
|
g_OleDoc_OleItemContainerVtbl.Release = OleDoc_ItemCont_Release;
|
||
|
g_OleDoc_OleItemContainerVtbl.ParseDisplayName =
|
||
|
OleDoc_ItemCont_ParseDisplayName;
|
||
|
g_OleDoc_OleItemContainerVtbl.EnumObjects= OleDoc_ItemCont_EnumObjects;
|
||
|
g_OleDoc_OleItemContainerVtbl.LockContainer =
|
||
|
OleDoc_ItemCont_LockContainer;
|
||
|
g_OleDoc_OleItemContainerVtbl.GetObject = OleDoc_ItemCont_GetObject;
|
||
|
g_OleDoc_OleItemContainerVtbl.GetObjectStorage =
|
||
|
OleDoc_ItemCont_GetObjectStorage;
|
||
|
g_OleDoc_OleItemContainerVtbl.IsRunning = OleDoc_ItemCont_IsRunning;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_OleItemContainerVtbl,
|
||
|
sizeof(IOleItemContainerVtbl),
|
||
|
"IOleItemContainer"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// OleDoc::IExternalConnection method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_OleDoc_ExternalConnectionVtbl,sizeof(IExternalConnectionVtbl));
|
||
|
g_OleDoc_ExternalConnectionVtbl.QueryInterface =
|
||
|
OleDoc_ExtConn_QueryInterface;
|
||
|
g_OleDoc_ExternalConnectionVtbl.AddRef = OleDoc_ExtConn_AddRef;
|
||
|
g_OleDoc_ExternalConnectionVtbl.Release = OleDoc_ExtConn_Release;
|
||
|
g_OleDoc_ExternalConnectionVtbl.AddConnection =
|
||
|
OleDoc_ExtConn_AddConnection;
|
||
|
g_OleDoc_ExternalConnectionVtbl.ReleaseConnection =
|
||
|
OleDoc_ExtConn_ReleaseConnection;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_ExternalConnectionVtbl,
|
||
|
sizeof(IExternalConnectionVtbl),
|
||
|
"IExternalConnection"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// OleDoc::IDataObject method table
|
||
|
OleStdInitVtbl(&g_OleDoc_DataObjectVtbl, sizeof(IDataObjectVtbl));
|
||
|
g_OleDoc_DataObjectVtbl.QueryInterface = OleDoc_DataObj_QueryInterface;
|
||
|
g_OleDoc_DataObjectVtbl.AddRef = OleDoc_DataObj_AddRef;
|
||
|
g_OleDoc_DataObjectVtbl.Release = OleDoc_DataObj_Release;
|
||
|
g_OleDoc_DataObjectVtbl.GetData = OleDoc_DataObj_GetData;
|
||
|
g_OleDoc_DataObjectVtbl.GetDataHere = OleDoc_DataObj_GetDataHere;
|
||
|
g_OleDoc_DataObjectVtbl.QueryGetData = OleDoc_DataObj_QueryGetData;
|
||
|
g_OleDoc_DataObjectVtbl.GetCanonicalFormatEtc =
|
||
|
OleDoc_DataObj_GetCanonicalFormatEtc;
|
||
|
g_OleDoc_DataObjectVtbl.SetData = OleDoc_DataObj_SetData;
|
||
|
g_OleDoc_DataObjectVtbl.EnumFormatEtc = OleDoc_DataObj_EnumFormatEtc;
|
||
|
g_OleDoc_DataObjectVtbl.DAdvise = OleDoc_DataObj_DAdvise;
|
||
|
g_OleDoc_DataObjectVtbl.DUnadvise = OleDoc_DataObj_DUnadvise;
|
||
|
g_OleDoc_DataObjectVtbl.EnumDAdvise = OleDoc_DataObj_EnumDAdvise;
|
||
|
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_DataObjectVtbl,
|
||
|
sizeof(IDataObjectVtbl),
|
||
|
"IDataObject"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
#if defined( USE_DRAGDROP )
|
||
|
|
||
|
// OleDoc::IDropTarget method table
|
||
|
OleStdInitVtbl(&g_OleDoc_DropTargetVtbl, sizeof(IDropTargetVtbl));
|
||
|
g_OleDoc_DropTargetVtbl.QueryInterface= OleDoc_DropTarget_QueryInterface;
|
||
|
g_OleDoc_DropTargetVtbl.AddRef = OleDoc_DropTarget_AddRef;
|
||
|
g_OleDoc_DropTargetVtbl.Release = OleDoc_DropTarget_Release;
|
||
|
|
||
|
g_OleDoc_DropTargetVtbl.DragEnter = OleDoc_DropTarget_DragEnter;
|
||
|
g_OleDoc_DropTargetVtbl.DragOver = OleDoc_DropTarget_DragOver;
|
||
|
g_OleDoc_DropTargetVtbl.DragLeave = OleDoc_DropTarget_DragLeave;
|
||
|
g_OleDoc_DropTargetVtbl.Drop = OleDoc_DropTarget_Drop;
|
||
|
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_DropTargetVtbl,
|
||
|
sizeof(IDropTargetVtbl),
|
||
|
"IDropTarget"
|
||
|
);
|
||
|
if (! fStatus)
|
||
|
return FALSE;
|
||
|
|
||
|
// OleDoc::IDropSource method table
|
||
|
OleStdInitVtbl(&g_OleDoc_DropSourceVtbl, sizeof(IDropSourceVtbl));
|
||
|
g_OleDoc_DropSourceVtbl.QueryInterface =
|
||
|
OleDoc_DropSource_QueryInterface;
|
||
|
g_OleDoc_DropSourceVtbl.AddRef = OleDoc_DropSource_AddRef;
|
||
|
g_OleDoc_DropSourceVtbl.Release = OleDoc_DropSource_Release;
|
||
|
|
||
|
g_OleDoc_DropSourceVtbl.QueryContinueDrag =
|
||
|
OleDoc_DropSource_QueryContinueDrag;
|
||
|
g_OleDoc_DropSourceVtbl.GiveFeedback = OleDoc_DropSource_GiveFeedback;
|
||
|
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_OleDoc_DropSourceVtbl,
|
||
|
sizeof(IDropSourceVtbl),
|
||
|
"IDropSource"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
#endif // USE_DRAGDROP
|
||
|
|
||
|
#if defined( OLE_SERVER )
|
||
|
|
||
|
// Initialize the server specific interface method tables.
|
||
|
if (! ServerApp_InitVtbls((LPSERVERAPP)lpOleApp))
|
||
|
return FALSE;
|
||
|
#endif
|
||
|
#if defined( OLE_CNTR )
|
||
|
|
||
|
// Initialize the container specific interface method tables.
|
||
|
if (! ContainerApp_InitVtbls((LPCONTAINERAPP)lpOleApp))
|
||
|
return FALSE;
|
||
|
#endif
|
||
|
return TRUE;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
/* OleApp_InitMenu
|
||
|
* ---------------
|
||
|
*
|
||
|
* Enable or Disable menu items depending on the state of
|
||
|
* the appliation.
|
||
|
* The OLE versions of the Outline sample app add a PasteSpecial command.
|
||
|
* Also, the container version add InsertObject and ObjectVerb menu items.
|
||
|
*/
|
||
|
void OleApp_InitMenu(
|
||
|
LPOLEAPP lpOleApp,
|
||
|
LPOLEDOC lpOleDoc,
|
||
|
HMENU hMenu
|
||
|
)
|
||
|
{
|
||
|
BOOL bMsgFilterInstalled = FALSE;
|
||
|
BOOL bRejecting = FALSE;
|
||
|
|
||
|
if (!lpOleApp || !hMenu)
|
||
|
return;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_InitMenu\r\n")
|
||
|
|
||
|
/*
|
||
|
** Enable/disable menu items for Message Filter
|
||
|
*/
|
||
|
bMsgFilterInstalled = (lpOleApp->m_lpMsgFilter != NULL);
|
||
|
bRejecting = bMsgFilterInstalled &&
|
||
|
OleStdMsgFilter_GetInComingCallStatus(lpOleApp->m_lpMsgFilter) != SERVERCALL_ISHANDLED;
|
||
|
|
||
|
CheckMenuItem(hMenu,
|
||
|
IDM_D_INSTALLMSGFILTER,
|
||
|
bMsgFilterInstalled ? MF_CHECKED : MF_UNCHECKED);
|
||
|
|
||
|
EnableMenuItem(hMenu,
|
||
|
IDM_D_REJECTINCOMING,
|
||
|
bMsgFilterInstalled ? MF_ENABLED : MF_GRAYED);
|
||
|
|
||
|
CheckMenuItem(hMenu,
|
||
|
IDM_D_REJECTINCOMING,
|
||
|
bRejecting ? MF_CHECKED : MF_UNCHECKED);
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
{
|
||
|
LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
|
||
|
BOOL fShowObject;
|
||
|
|
||
|
fShowObject = ContainerDoc_GetShowObjectFlag(lpContainerDoc);
|
||
|
CheckMenuItem(
|
||
|
hMenu,
|
||
|
IDM_O_SHOWOBJECT,
|
||
|
(fShowObject ? MF_CHECKED : MF_UNCHECKED)
|
||
|
);
|
||
|
|
||
|
#if defined( INPLACE_CNTR ) && defined( _DEBUG )
|
||
|
CheckMenuItem(
|
||
|
hMenu,
|
||
|
IDM_D_INSIDEOUT,
|
||
|
g_fInsideOutContainer ? MF_CHECKED:MF_UNCHECKED);
|
||
|
#endif // INPLACE_CNTR && _DEBUG
|
||
|
|
||
|
}
|
||
|
#endif // OLE_CNTR
|
||
|
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* OleApp_UpdateEditMenu
|
||
|
* ---------------------
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Update the Edit menuitems of the App according to the state of
|
||
|
* OutlineDoc
|
||
|
*
|
||
|
* Parameter:
|
||
|
* lpOutlineDoc pointer to the document
|
||
|
* hMenuEdit edit menu handle
|
||
|
*/
|
||
|
void OleApp_UpdateEditMenu(
|
||
|
LPOLEAPP lpOleApp,
|
||
|
LPOUTLINEDOC lpOutlineDoc,
|
||
|
HMENU hMenuEdit
|
||
|
)
|
||
|
{
|
||
|
int nFmtEtc;
|
||
|
UINT uEnablePaste = MF_GRAYED;
|
||
|
UINT uEnablePasteLink = MF_GRAYED;
|
||
|
LPDATAOBJECT lpClipboardDataObj;
|
||
|
LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
|
||
|
HRESULT hrErr;
|
||
|
BOOL fPrevEnable1;
|
||
|
BOOL fPrevEnable2;
|
||
|
|
||
|
if (!lpOleApp || !lpOutlineDoc || !hMenuEdit)
|
||
|
return;
|
||
|
|
||
|
if (!OleDoc_GetUpdateEditMenuFlag(lpOleDoc))
|
||
|
/* OLE2NOTE: if the flag is not set, we don't have to update
|
||
|
** the edit menu again. This blocks repetitive updating when
|
||
|
** the user move the mouse across Edit menu while holding
|
||
|
** down the button
|
||
|
*/
|
||
|
return;
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_InitEditMenu\r\n")
|
||
|
|
||
|
/* OLE2NOTE: we do not want to ever give the busy dialog when we
|
||
|
** are trying to put up our menus. eg. even if the source of
|
||
|
** data on the clipboard is busy, we do not want put up the busy
|
||
|
** dialog. thus we will disable the dialog and at the end
|
||
|
** re-enable it.
|
||
|
*/
|
||
|
OleApp_DisableBusyDialogs(lpOleApp, &fPrevEnable1, &fPrevEnable2);
|
||
|
|
||
|
// check if there is data on the clipboard that we can paste/paste link
|
||
|
|
||
|
OLEDBG_BEGIN2("OleGetClipboard called\r\n")
|
||
|
hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if (hrErr == NOERROR) {
|
||
|
nFmtEtc = OleStdGetPriorityClipboardFormat(
|
||
|
lpClipboardDataObj,
|
||
|
lpOleApp->m_arrPasteEntries,
|
||
|
lpOleApp->m_nPasteEntries
|
||
|
);
|
||
|
|
||
|
if (nFmtEtc >= 0)
|
||
|
uEnablePaste = MF_ENABLED; // there IS a format we like
|
||
|
|
||
|
OLEDBG_BEGIN2("OleQueryLinkFromData called\r\n")
|
||
|
hrErr = OleQueryLinkFromData(lpClipboardDataObj);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if(hrErr == NOERROR)
|
||
|
uEnablePasteLink = MF_ENABLED;
|
||
|
|
||
|
OleStdRelease((LPUNKNOWN)lpClipboardDataObj);
|
||
|
}
|
||
|
|
||
|
EnableMenuItem(hMenuEdit, IDM_E_PASTE, uEnablePaste);
|
||
|
EnableMenuItem(hMenuEdit, IDM_E_PASTESPECIAL, uEnablePaste);
|
||
|
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
if (ContainerDoc_GetNextLink((LPCONTAINERDOC)lpOutlineDoc, NULL))
|
||
|
EnableMenuItem(hMenuEdit, IDM_E_EDITLINKS, MF_ENABLED);
|
||
|
else
|
||
|
EnableMenuItem(hMenuEdit, IDM_E_EDITLINKS, MF_GRAYED);
|
||
|
|
||
|
|
||
|
{
|
||
|
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp;
|
||
|
HMENU hMenuVerb = NULL;
|
||
|
LPOLEOBJECT lpOleObj = NULL;
|
||
|
LPCONTAINERLINE lpContainerLine = NULL;
|
||
|
BOOL fSelIsOleObject;
|
||
|
|
||
|
EnableMenuItem(hMenuEdit, IDM_E_PASTELINK, uEnablePasteLink);
|
||
|
|
||
|
/* check if selection is a single line that contains an OleObject */
|
||
|
|
||
|
fSelIsOleObject = ContainerDoc_IsSelAnOleObject(
|
||
|
(LPCONTAINERDOC)lpOutlineDoc,
|
||
|
&IID_IOleObject,
|
||
|
(LPUNKNOWN FAR*)&lpOleObj,
|
||
|
NULL, /* we don't need the line index */
|
||
|
(LPCONTAINERLINE FAR*)&lpContainerLine
|
||
|
);
|
||
|
|
||
|
if (hMenuEdit != NULL) {
|
||
|
|
||
|
/* If the current line is an ContainerLine, add the object
|
||
|
** verb sub menu to the Edit menu. if the line is not an
|
||
|
** ContainerLine, (lpOleObj==NULL) then disable the
|
||
|
** Edit.Object command. this helper API takes care of
|
||
|
** building the verb menu as appropriate.
|
||
|
*/
|
||
|
OleUIAddVerbMenu(
|
||
|
(LPOLEOBJECT)lpOleObj,
|
||
|
(lpContainerLine ? lpContainerLine->m_lpszShortType:NULL),
|
||
|
hMenuEdit,
|
||
|
POS_OBJECT,
|
||
|
IDM_E_OBJECTVERBMIN,
|
||
|
0, // no uIDVerbMax enforced
|
||
|
TRUE, // Add Convert menu item
|
||
|
IDM_E_CONVERTVERB, // ID for Convert menu item
|
||
|
(HMENU FAR*) &hMenuVerb
|
||
|
);
|
||
|
|
||
|
#if defined( USE_STATUSBAR_LATER )
|
||
|
/* setup status messages for the object verb menu */
|
||
|
if (hMenuVerb) {
|
||
|
// REVIEW: this string should come from a string resource.
|
||
|
// REVIEW: this doesn't work for dynamically created menus
|
||
|
AssignPopupMessage(
|
||
|
hMenuVerb,
|
||
|
"Open, edit or interact with an object"
|
||
|
);
|
||
|
}
|
||
|
#endif // USE_STATUSBAR_LATER
|
||
|
}
|
||
|
|
||
|
if (lpOleObj)
|
||
|
OleStdRelease((LPUNKNOWN)lpOleObj);
|
||
|
}
|
||
|
|
||
|
#endif // OLE_CNTR
|
||
|
|
||
|
// re-enable the Busy/NotResponding dialogs
|
||
|
OleApp_EnableBusyDialogs(lpOleApp, fPrevEnable1, fPrevEnable2);
|
||
|
|
||
|
OleDoc_SetUpdateEditMenuFlag(lpOleDoc, FALSE);
|
||
|
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_RegisterClassFactory
|
||
|
* ---------------------------
|
||
|
*
|
||
|
* Register our app's ClassFactory with OLE.
|
||
|
*
|
||
|
*/
|
||
|
BOOL OleApp_RegisterClassFactory(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
HRESULT hrErr;
|
||
|
|
||
|
if (lpOleApp->m_lpClassFactory)
|
||
|
return TRUE; // already registered
|
||
|
|
||
|
OLEDBG_BEGIN3("OleApp_RegisterClassFactory\r\n")
|
||
|
|
||
|
/******************************************************************
|
||
|
** An SDI app must register its ClassFactory if it is launched
|
||
|
** for embedding (/Embedding command line option specified).
|
||
|
** An MDI app must register its ClassFactory in all cases,
|
||
|
******************************************************************/
|
||
|
|
||
|
lpOleApp->m_lpClassFactory = AppClassFactory_Create();
|
||
|
if (! lpOleApp->m_lpClassFactory) {
|
||
|
OutlineApp_ErrorMessage(g_lpApp, ErrMsgCreateCF);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
OLEDBG_BEGIN2("CoRegisterClassObject called\r\n")
|
||
|
hrErr = CoRegisterClassObject(
|
||
|
&CLSID_APP,
|
||
|
(LPUNKNOWN)lpOleApp->m_lpClassFactory,
|
||
|
CLSCTX_LOCAL_SERVER,
|
||
|
REGCLS_SINGLEUSE,
|
||
|
&lpOleApp->m_dwRegClassFac
|
||
|
);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if(hrErr != NOERROR) {
|
||
|
OleDbgOutHResult("CoRegisterClassObject returned", hrErr);
|
||
|
OutlineApp_ErrorMessage(g_lpApp, ErrMsgRegCF);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
OLEDBG_END3
|
||
|
return TRUE;
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (lpOleApp->m_lpClassFactory) {
|
||
|
OleStdRelease((LPUNKNOWN)lpOleApp->m_lpClassFactory);
|
||
|
lpOleApp->m_lpClassFactory = NULL;
|
||
|
}
|
||
|
OLEDBG_END3
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_RevokeClassFactory
|
||
|
* -------------------------
|
||
|
*
|
||
|
* Revoke our app's ClassFactory.
|
||
|
*
|
||
|
*/
|
||
|
void OleApp_RevokeClassFactory(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
HRESULT hrErr;
|
||
|
|
||
|
if (lpOleApp->m_lpClassFactory) {
|
||
|
|
||
|
OLEDBG_BEGIN2("CoRevokeClassObject called\r\n")
|
||
|
hrErr = CoRevokeClassObject(lpOleApp->m_dwRegClassFac);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
#if defined( _DEBUG )
|
||
|
if (hrErr != NOERROR) {
|
||
|
OleDbgOutHResult("CoRevokeClassObject returned", hrErr);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// we just release here; other folks may still have
|
||
|
// a pointer to our class factory, so we can't
|
||
|
// do any checks on the reference count.
|
||
|
OleStdRelease((LPUNKNOWN)lpOleApp->m_lpClassFactory);
|
||
|
lpOleApp->m_lpClassFactory = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#if defined( USE_MSGFILTER )
|
||
|
|
||
|
/* OleApp_RegisterMessageFilter
|
||
|
* ----------------------------
|
||
|
* Register our IMessageFilter*. the message filter is used to handle
|
||
|
* concurrency. we will use a standard implementation of IMessageFilter
|
||
|
* that is included as part of the OLE2UI library.
|
||
|
*/
|
||
|
BOOL OleApp_RegisterMessageFilter(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
HRESULT hrErr;
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
|
||
|
if (lpOleApp->m_lpMsgFilter == NULL) {
|
||
|
// Register our message filter.
|
||
|
lpOleApp->m_lpfnMsgPending = (MSGPENDINGPROC)MessagePendingProc;
|
||
|
lpOleApp->m_lpMsgFilter = OleStdMsgFilter_Create(
|
||
|
g_lpApp->m_hWndApp,
|
||
|
(LPSTR)APPNAME,
|
||
|
lpOleApp->m_lpfnMsgPending,
|
||
|
NULL /* Busy dialog callback hook function */
|
||
|
);
|
||
|
|
||
|
OLEDBG_BEGIN2("CoRegisterMessageFilter called\r\n")
|
||
|
hrErr = CoRegisterMessageFilter(
|
||
|
lpOleApp->m_lpMsgFilter,
|
||
|
NULL /* don't need previous message filter */
|
||
|
);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if(hrErr != NOERROR) {
|
||
|
OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgRegMF);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_RevokeMessageFilter
|
||
|
* --------------------------
|
||
|
* Revoke our IMessageFilter*. the message filter is used to handle
|
||
|
* concurrency. we will use a standard implementation of IMessageFilter
|
||
|
* that is included as part of the OLE2UI library.
|
||
|
*/
|
||
|
void OleApp_RevokeMessageFilter(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
|
||
|
|
||
|
if (lpOleApp->m_lpMsgFilter != NULL) {
|
||
|
// Revoke our message filter
|
||
|
OLEDBG_BEGIN2("CoRegisterMessageFilter(NULL) called\r\n")
|
||
|
CoRegisterMessageFilter(NULL, NULL);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if (lpOleApp->m_lpfnMsgPending) {
|
||
|
lpOleApp->m_lpfnMsgPending = NULL;
|
||
|
}
|
||
|
|
||
|
OleStdVerifyRelease(
|
||
|
(LPUNKNOWN)lpOleApp->m_lpMsgFilter,
|
||
|
"Release MessageFilter FAILED!"
|
||
|
);
|
||
|
lpOleApp->m_lpMsgFilter = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* MessagePendingProc
|
||
|
* ------------------
|
||
|
*
|
||
|
* Callback function for the IMessageFilter::MessagePending procedure. This
|
||
|
* function is called when a message is received by our application while
|
||
|
* we are waiting for an OLE call to complete. We are essentially
|
||
|
* blocked at this point, waiting for a response from the other OLE application.
|
||
|
* We should not process any messages which might cause another OLE call
|
||
|
* to become blocked, or any other call which might cause re-entrancy problems.
|
||
|
*
|
||
|
* For this application, only process WM_PAINT messages. A more sophisticated
|
||
|
* application might allow certain menu messages and menu items to be processed
|
||
|
* also.
|
||
|
*
|
||
|
* RETURNS: TRUE if we processed the message, FALSE if we did not.
|
||
|
*/
|
||
|
|
||
|
BOOL FAR PASCAL EXPORT MessagePendingProc(MSG FAR *lpMsg)
|
||
|
{
|
||
|
// Our application is only handling WM_PAINT messages when we are blocked
|
||
|
switch (lpMsg->message) {
|
||
|
case WM_PAINT:
|
||
|
OleDbgOut2("WM_PAINT dispatched while blocked\r\n");
|
||
|
|
||
|
DispatchMessage(lpMsg);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return FALSE; // return PENDINGMSG_WAITDEFPROCESS from MessagePending
|
||
|
}
|
||
|
#endif // USE_MSGFILTER
|
||
|
|
||
|
|
||
|
/* OleApp_FlushClipboard
|
||
|
* ---------------------
|
||
|
*
|
||
|
* Force the Windows clipboard to release our clipboard DataObject.
|
||
|
*/
|
||
|
void OleApp_FlushClipboard(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
LPOLEDOC lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
|
||
|
OLEDBG_BEGIN3("OleApp_FlushClipboard\r\n")
|
||
|
|
||
|
/* OLE2NOTE: if for some reason our clipboard data transfer
|
||
|
** document is still held on to by an external client, we want
|
||
|
** to forceably break all external connections.
|
||
|
*/
|
||
|
OLEDBG_BEGIN2("CoDisconnectObject called\r\n")
|
||
|
CoDisconnectObject((LPUNKNOWN)&lpClipboardDoc->m_Unknown, 0);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
OLEDBG_BEGIN2("OleFlushClipboard called\r\n")
|
||
|
OleFlushClipboard();
|
||
|
OLEDBG_END2
|
||
|
|
||
|
lpOutlineApp->m_lpClipboardDoc = NULL;
|
||
|
|
||
|
OLEDBG_END3
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_NewCommand
|
||
|
* -----------------
|
||
|
*
|
||
|
* Start a new untitled document (File.New command).
|
||
|
*/
|
||
|
void OleApp_NewCommand(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc;
|
||
|
|
||
|
if (! OutlineDoc_Close(lpOutlineDoc, OLECLOSE_PROMPTSAVE))
|
||
|
return;
|
||
|
|
||
|
OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed");
|
||
|
lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE);
|
||
|
if (! lpOutlineApp->m_lpDoc) goto error;
|
||
|
|
||
|
/* OLE2NOTE: initially the Doc object is created with a 0 ref
|
||
|
** count. in order to have a stable Doc object during the
|
||
|
** process of initializing the new Doc instance,
|
||
|
** we intially AddRef the Doc ref cnt and later
|
||
|
** Release it. This initial AddRef is artificial; it is simply
|
||
|
** done to guarantee that a harmless QueryInterface followed by
|
||
|
** a Release does not inadvertantly force our object to destroy
|
||
|
** itself prematurely.
|
||
|
*/
|
||
|
OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
// set the doc to an (Untitled) doc.
|
||
|
if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc))
|
||
|
goto error;
|
||
|
|
||
|
// position and size the new doc window
|
||
|
OutlineApp_ResizeWindows(lpOutlineApp);
|
||
|
OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc); // calls OleDoc_Lock
|
||
|
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel artificial AddRef
|
||
|
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
// REVIEW: should load string from string resource
|
||
|
OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document");
|
||
|
|
||
|
if (lpOutlineApp->m_lpDoc) {
|
||
|
// releasing the artificial AddRef above will destroy the document
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
lpOutlineApp->m_lpDoc = NULL;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleApp_OpenCommand
|
||
|
* ------------------
|
||
|
*
|
||
|
* Load a document from file (File.Open command).
|
||
|
*/
|
||
|
void OleApp_OpenCommand(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpOleApp;
|
||
|
LPOUTLINEDOC lpOutlineDoc = lpOutlineApp->m_lpDoc;
|
||
|
OPENFILENAME ofn;
|
||
|
char szFilter[]=APPFILENAMEFILTER;
|
||
|
char szFileName[256];
|
||
|
UINT i;
|
||
|
DWORD dwSaveOption = OLECLOSE_PROMPTSAVE;
|
||
|
BOOL fStatus = TRUE;
|
||
|
|
||
|
if (! OutlineDoc_CheckSaveChanges(lpOutlineDoc, &dwSaveOption))
|
||
|
return; // abort opening new doc
|
||
|
|
||
|
for(i=0; szFilter[i]; i++)
|
||
|
if(szFilter[i]=='|') szFilter[i]='\0';
|
||
|
|
||
|
_fmemset((LPOPENFILENAME)&ofn,0,sizeof(OPENFILENAME));
|
||
|
|
||
|
szFileName[0]='\0';
|
||
|
|
||
|
ofn.lStructSize=sizeof(OPENFILENAME);
|
||
|
ofn.hwndOwner=lpOutlineApp->m_hWndApp;
|
||
|
ofn.lpstrFilter=(LPSTR)szFilter;
|
||
|
ofn.lpstrFile=(LPSTR)szFileName;
|
||
|
ofn.nMaxFile=sizeof(szFileName);
|
||
|
ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||
|
ofn.lpstrDefExt=DEFEXTENSION;
|
||
|
|
||
|
OleApp_PreModalDialog(lpOleApp, (LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
fStatus = GetOpenFileName((LPOPENFILENAME)&ofn);
|
||
|
|
||
|
OleApp_PostModalDialog(lpOleApp, (LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
if(! fStatus)
|
||
|
return; // user canceled file open dialog
|
||
|
|
||
|
OutlineDoc_Close(lpOutlineDoc, OLECLOSE_NOSAVE);
|
||
|
OleDbgAssertSz(lpOutlineApp->m_lpDoc==NULL,"Closed doc NOT properly destroyed");
|
||
|
|
||
|
lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE);
|
||
|
if (! lpOutlineApp->m_lpDoc) goto error;
|
||
|
|
||
|
/* OLE2NOTE: initially the Doc object is created with a 0 ref
|
||
|
** count. in order to have a stable Doc object during the
|
||
|
** process of initializing the new Doc instance,
|
||
|
** we intially AddRef the Doc ref cnt and later
|
||
|
** Release it. This initial AddRef is artificial; it is simply
|
||
|
** done to guarantee that a harmless QueryInterface followed by
|
||
|
** a Release does not inadvertantly force our object to destroy
|
||
|
** itself prematurely.
|
||
|
*/
|
||
|
OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
fStatus=OutlineDoc_LoadFromFile(lpOutlineApp->m_lpDoc, (LPSTR)szFileName);
|
||
|
|
||
|
if (! fStatus) {
|
||
|
// loading the doc failed; create an untitled instead
|
||
|
|
||
|
// releasing the artificial AddRef above will destroy the document
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
lpOutlineApp->m_lpDoc = OutlineApp_CreateDoc(lpOutlineApp, FALSE);
|
||
|
if (! lpOutlineApp->m_lpDoc) goto error;
|
||
|
OleDoc_AddRef((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
if (! OutlineDoc_InitNewFile(lpOutlineApp->m_lpDoc))
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
// position and size the new doc window
|
||
|
OutlineApp_ResizeWindows(lpOutlineApp);
|
||
|
OutlineDoc_ShowWindow(lpOutlineApp->m_lpDoc);
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
UpdateWindow(lpOutlineApp->m_hWndApp);
|
||
|
ContainerDoc_UpdateLinks((LPCONTAINERDOC)lpOutlineApp->m_lpDoc);
|
||
|
#endif
|
||
|
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc); // rel artificial AddRef
|
||
|
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
// REVIEW: should load string from string resource
|
||
|
OutlineApp_ErrorMessage(lpOutlineApp, "Could not create new document");
|
||
|
|
||
|
if (lpOutlineApp->m_lpDoc) {
|
||
|
// releasing the artificial AddRef above will destroy the document
|
||
|
OleDoc_Release((LPOLEDOC)lpOutlineApp->m_lpDoc);
|
||
|
lpOutlineApp->m_lpDoc = NULL;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
|
||
|
/* OLE2NOTE: forward the WM_QUERYNEWPALETTE message (via
|
||
|
** SendMessage) to UIActive in-place object if there is one.
|
||
|
** this gives the UIActive object the opportunity to select
|
||
|
** and realize its color palette as the FOREGROUND palette.
|
||
|
** this is optional for in-place containers. if a container
|
||
|
** prefers to force its color palette as the foreground
|
||
|
** palette then it should NOT forward the this message. or
|
||
|
** the container can give the UIActive object priority; if
|
||
|
** the UIActive object returns 0 from the WM_QUERYNEWPALETTE
|
||
|
** message (ie. it did not realize its own palette), then
|
||
|
** the container can realize its palette.
|
||
|
** (see ContainerDoc_ForwardPaletteChangedMsg for more info)
|
||
|
**
|
||
|
** (It is a good idea for containers to use the standard
|
||
|
** palette even if they do not use colors themselves. this
|
||
|
** will allow embedded object to get a good distribution of
|
||
|
** colors when they are being drawn by the container)
|
||
|
**
|
||
|
*/
|
||
|
|
||
|
LRESULT OleApp_QueryNewPalette(LPOLEAPP lpOleApp)
|
||
|
{
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp;
|
||
|
|
||
|
if (lpContainerApp && lpContainerApp->m_hWndUIActiveObj) {
|
||
|
if (SendMessage(lpContainerApp->m_hWndUIActiveObj, WM_QUERYNEWPALETTE,
|
||
|
(WPARAM)0, (LPARAM)0)) {
|
||
|
/* Object selected its palette as foreground palette */
|
||
|
return (LRESULT)1;
|
||
|
}
|
||
|
}
|
||
|
#endif // INPLACE_CNTR
|
||
|
|
||
|
|
||
|
return wSelectPalette(((LPOUTLINEAPP)lpOleApp)->m_hWndApp,
|
||
|
lpOleApp->m_hStdPal, FALSE/*fBackground*/);
|
||
|
}
|
||
|
|
||
|
#endif // OLE_CNTR
|
||
|
|
||
|
|
||
|
|
||
|
/* This is just a helper routine */
|
||
|
|
||
|
LRESULT wSelectPalette(HWND hWnd, HPALETTE hPal, BOOL fBackground)
|
||
|
{
|
||
|
HDC hdc;
|
||
|
HPALETTE hOldPal;
|
||
|
UINT iPalChg = 0;
|
||
|
|
||
|
if (hPal == 0)
|
||
|
return (LRESULT)0;
|
||
|
|
||
|
hdc = GetDC(hWnd);
|
||
|
hOldPal = SelectPalette(hdc, hPal, fBackground);
|
||
|
iPalChg = RealizePalette(hdc);
|
||
|
SelectPalette(hdc, hOldPal, TRUE /*fBackground*/);
|
||
|
ReleaseDC(hWnd, hdc);
|
||
|
|
||
|
if (iPalChg > 0)
|
||
|
InvalidateRect(hWnd, NULL, TRUE);
|
||
|
|
||
|
return (LRESULT)1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
** OleApp::IUnknown interface implementation
|
||
|
*************************************************************************/
|
||
|
|
||
|
STDMETHODIMP OleApp_Unk_QueryInterface(
|
||
|
LPUNKNOWN lpThis,
|
||
|
REFIID riid,
|
||
|
LPVOID FAR* lplpvObj
|
||
|
)
|
||
|
{
|
||
|
LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp;
|
||
|
|
||
|
return OleApp_QueryInterface(lpOleApp, riid, lplpvObj);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) OleApp_Unk_AddRef(LPUNKNOWN lpThis)
|
||
|
{
|
||
|
LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp;
|
||
|
|
||
|
OleDbgAddRefMethod(lpThis, "IUnknown");
|
||
|
|
||
|
return OleApp_AddRef(lpOleApp);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP_(ULONG) OleApp_Unk_Release (LPUNKNOWN lpThis)
|
||
|
{
|
||
|
LPOLEAPP lpOleApp = ((struct CAppUnknownImpl FAR*)lpThis)->lpOleApp;
|
||
|
|
||
|
OleDbgReleaseMethod(lpThis, "IUnknown");
|
||
|
|
||
|
return OleApp_Release(lpOleApp);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#if defined( OLE_SERVER )
|
||
|
|
||
|
/*************************************************************************
|
||
|
** ServerDoc Supprt Functions Used by Server versions
|
||
|
*************************************************************************/
|
||
|
|
||
|
/* ServerApp_InitInstance
|
||
|
* ----------------------
|
||
|
*
|
||
|
* Initialize the app instance by creating the main frame window and
|
||
|
* performing app instance specific initializations
|
||
|
* (eg. initializing interface Vtbls).
|
||
|
*
|
||
|
* RETURNS: TRUE if the memory could be allocated, and the server app
|
||
|
* was properly initialized.
|
||
|
* FALSE otherwise
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
BOOL ServerApp_InitInstance(
|
||
|
LPSERVERAPP lpServerApp,
|
||
|
HINSTANCE hInst,
|
||
|
int nCmdShow
|
||
|
)
|
||
|
{
|
||
|
LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
|
||
|
|
||
|
/* Setup arrays used by IDataObject::EnumFormatEtc.
|
||
|
**
|
||
|
** OLE2NOTE: The order that the formats are listed for GetData is very
|
||
|
** significant. It should be listed in order of highest fidelity
|
||
|
** formats to least fidelity formats. A common ordering will be:
|
||
|
** 1. private app formats
|
||
|
** 2. EmbedSource
|
||
|
** 3. lower fidelity interchange formats
|
||
|
** 4. pictures (metafile, dib, etc.)
|
||
|
** (graphic-related apps offer pictures 1st!)
|
||
|
** 5. LinkSource
|
||
|
*/
|
||
|
|
||
|
/* m_arrDocGetFmts array enumerates the formats that a ServerDoc
|
||
|
** DataTransferDoc object can offer (give) through a
|
||
|
** IDataObject::GetData call. a ServerDoc DataTransferDoc offers
|
||
|
** data formats in the following order:
|
||
|
** 1. CF_OUTLINE
|
||
|
** 2. CF_EMBEDSOURCE
|
||
|
** 3. CF_OBJECTDESCRIPTOR
|
||
|
** 4. CF_TEXT
|
||
|
** 5. CF_METAFILEPICT
|
||
|
** 6. CF_LINKSOURCE *
|
||
|
** 7. CF_LINKSRCDESCRIPTOR *
|
||
|
**
|
||
|
** * NOTE: CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR is only
|
||
|
** offered if the doc is able to give
|
||
|
** a Moniker which references the data. CF_LINKSOURCE is
|
||
|
** deliberately listed last in this array of possible formats.
|
||
|
** if the doc does not have a Moniker then the last element of
|
||
|
** this array is not used. (see SvrDoc_DataObj_EnumFormatEtc).
|
||
|
**
|
||
|
** NOTE: The list of formats that a USER ServerDoc document can
|
||
|
** offer is a static list and is registered in the registration
|
||
|
** database for the SVROUTL class. The
|
||
|
** IDataObject::EnumFormatEtc method returns OLE_S_USEREG in the
|
||
|
** case the document is a user docuemt (ie. created via
|
||
|
** File.New, File.Open, InsertObject in a container, or
|
||
|
** IPersistFile::Load during binding a link source). this tells
|
||
|
** OLE to enumerate the formats automatically using the data the
|
||
|
** the REGDB.
|
||
|
*/
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[0].cfFormat = lpOutlineApp->m_cfOutline;
|
||
|
lpOleApp->m_arrDocGetFmts[0].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[0].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[0].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[0].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[1].cfFormat = lpOleApp->m_cfEmbedSource;
|
||
|
lpOleApp->m_arrDocGetFmts[1].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[1].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[1].tymed = TYMED_ISTORAGE;
|
||
|
lpOleApp->m_arrDocGetFmts[1].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[2].cfFormat = CF_TEXT;
|
||
|
lpOleApp->m_arrDocGetFmts[2].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[2].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[2].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[2].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[3].cfFormat = CF_METAFILEPICT;
|
||
|
lpOleApp->m_arrDocGetFmts[3].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[3].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[3].tymed = TYMED_MFPICT;
|
||
|
lpOleApp->m_arrDocGetFmts[3].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[4].cfFormat = lpOleApp->m_cfObjectDescriptor;
|
||
|
lpOleApp->m_arrDocGetFmts[4].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[4].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[4].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[4].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[5].cfFormat = lpOleApp->m_cfLinkSource;
|
||
|
lpOleApp->m_arrDocGetFmts[5].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[5].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[5].tymed = TYMED_ISTREAM;
|
||
|
lpOleApp->m_arrDocGetFmts[5].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[6].cfFormat = lpOleApp->m_cfLinkSrcDescriptor;
|
||
|
lpOleApp->m_arrDocGetFmts[6].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[6].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[6].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[6].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_nDocGetFmts = 7;
|
||
|
|
||
|
/* m_arrPasteEntries array enumerates the formats that a ServerDoc
|
||
|
** object can accept (get) from the clipboard.
|
||
|
** The formats are listed in priority order.
|
||
|
** ServerDoc accept data formats in the following order:
|
||
|
** 1. CF_OUTLINE
|
||
|
** 2. CF_TEXT
|
||
|
*/
|
||
|
// REVIEW: strings should be loaded from string resource
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.cfFormat =lpOutlineApp->m_cfOutline;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[0].lpstrFormatName = "Outline Data";
|
||
|
lpOleApp->m_arrPasteEntries[0].lpstrResultText = "Outline Data";
|
||
|
lpOleApp->m_arrPasteEntries[0].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.cfFormat = CF_TEXT;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[1].lpstrFormatName = "Text";
|
||
|
lpOleApp->m_arrPasteEntries[1].lpstrResultText = "text";
|
||
|
lpOleApp->m_arrPasteEntries[1].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_nPasteEntries = 2;
|
||
|
|
||
|
/** m_arrLinkTypes array enumerates the link types that a ServerDoc
|
||
|
** object can accept from the clipboard. ServerDoc does NOT
|
||
|
** accept any type of link from the clipboard. ServerDoc can
|
||
|
** only be the source of a link. it can not contain links.
|
||
|
*/
|
||
|
|
||
|
lpOleApp->m_nLinkTypes = 0;
|
||
|
|
||
|
#if defined( INPLACE_SVR )
|
||
|
|
||
|
lpServerApp->m_hAccelBaseApp = NULL;
|
||
|
lpServerApp->m_hAccelIPSvr = LoadAccelerators(
|
||
|
hInst,
|
||
|
"InPlaceSvrOutlAccel"
|
||
|
);
|
||
|
|
||
|
lpServerApp->m_lpIPData = NULL;
|
||
|
|
||
|
lpServerApp->m_hMenuEdit = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_EDITMENU
|
||
|
);
|
||
|
lpServerApp->m_hMenuLine = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_LINEMENU
|
||
|
);
|
||
|
lpServerApp->m_hMenuName = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_NAMEMENU
|
||
|
);
|
||
|
lpServerApp->m_hMenuOptions = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_OPTIONSMENU
|
||
|
);
|
||
|
lpServerApp->m_hMenuDebug = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_DEBUGMENU
|
||
|
);
|
||
|
lpServerApp->m_hMenuHelp = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_HELPMENU
|
||
|
);
|
||
|
|
||
|
#endif // INPLACE_SVR
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ServerApp_InitVtbls
|
||
|
* -------------------
|
||
|
*
|
||
|
* initialize the methods in all of the interface Vtbl's
|
||
|
*
|
||
|
* OLE2NOTE: we only need one copy of each Vtbl. When an object which
|
||
|
* exposes an interface is instantiated, its lpVtbl is intialized
|
||
|
* to point to the single copy of the Vtbl.
|
||
|
*
|
||
|
*/
|
||
|
BOOL ServerApp_InitVtbls (LPSERVERAPP lpServerApp)
|
||
|
{
|
||
|
BOOL fStatus;
|
||
|
|
||
|
// ServerDoc::IOleObject method table
|
||
|
OleStdInitVtbl(&g_SvrDoc_OleObjectVtbl, sizeof(IOleObjectVtbl));
|
||
|
g_SvrDoc_OleObjectVtbl.QueryInterface = SvrDoc_OleObj_QueryInterface;
|
||
|
g_SvrDoc_OleObjectVtbl.AddRef = SvrDoc_OleObj_AddRef;
|
||
|
g_SvrDoc_OleObjectVtbl.Release = SvrDoc_OleObj_Release;
|
||
|
g_SvrDoc_OleObjectVtbl.SetClientSite = SvrDoc_OleObj_SetClientSite;
|
||
|
g_SvrDoc_OleObjectVtbl.GetClientSite = SvrDoc_OleObj_GetClientSite;
|
||
|
g_SvrDoc_OleObjectVtbl.SetHostNames = SvrDoc_OleObj_SetHostNames;
|
||
|
g_SvrDoc_OleObjectVtbl.Close = SvrDoc_OleObj_Close;
|
||
|
g_SvrDoc_OleObjectVtbl.SetMoniker = SvrDoc_OleObj_SetMoniker;
|
||
|
g_SvrDoc_OleObjectVtbl.GetMoniker = SvrDoc_OleObj_GetMoniker;
|
||
|
g_SvrDoc_OleObjectVtbl.InitFromData = SvrDoc_OleObj_InitFromData;
|
||
|
g_SvrDoc_OleObjectVtbl.GetClipboardData = SvrDoc_OleObj_GetClipboardData;
|
||
|
g_SvrDoc_OleObjectVtbl.DoVerb = SvrDoc_OleObj_DoVerb;
|
||
|
g_SvrDoc_OleObjectVtbl.EnumVerbs = SvrDoc_OleObj_EnumVerbs;
|
||
|
g_SvrDoc_OleObjectVtbl.Update = SvrDoc_OleObj_Update;
|
||
|
g_SvrDoc_OleObjectVtbl.IsUpToDate = SvrDoc_OleObj_IsUpToDate;
|
||
|
g_SvrDoc_OleObjectVtbl.GetUserClassID = SvrDoc_OleObj_GetUserClassID;
|
||
|
g_SvrDoc_OleObjectVtbl.GetUserType = SvrDoc_OleObj_GetUserType;
|
||
|
g_SvrDoc_OleObjectVtbl.SetExtent = SvrDoc_OleObj_SetExtent;
|
||
|
g_SvrDoc_OleObjectVtbl.GetExtent = SvrDoc_OleObj_GetExtent;
|
||
|
g_SvrDoc_OleObjectVtbl.Advise = SvrDoc_OleObj_Advise;
|
||
|
g_SvrDoc_OleObjectVtbl.Unadvise = SvrDoc_OleObj_Unadvise;
|
||
|
g_SvrDoc_OleObjectVtbl.EnumAdvise = SvrDoc_OleObj_EnumAdvise;
|
||
|
g_SvrDoc_OleObjectVtbl.GetMiscStatus = SvrDoc_OleObj_GetMiscStatus;
|
||
|
g_SvrDoc_OleObjectVtbl.SetColorScheme = SvrDoc_OleObj_SetColorScheme;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_SvrDoc_OleObjectVtbl,
|
||
|
sizeof(IOleObjectVtbl),
|
||
|
"IOleObject"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// ServerDoc::IPersistStorage method table
|
||
|
OleStdInitVtbl(&g_SvrDoc_PersistStorageVtbl, sizeof(IPersistStorageVtbl));
|
||
|
g_SvrDoc_PersistStorageVtbl.QueryInterface = SvrDoc_PStg_QueryInterface;
|
||
|
g_SvrDoc_PersistStorageVtbl.AddRef = SvrDoc_PStg_AddRef;
|
||
|
g_SvrDoc_PersistStorageVtbl.Release = SvrDoc_PStg_Release;
|
||
|
g_SvrDoc_PersistStorageVtbl.GetClassID = SvrDoc_PStg_GetClassID;
|
||
|
g_SvrDoc_PersistStorageVtbl.IsDirty = SvrDoc_PStg_IsDirty;
|
||
|
g_SvrDoc_PersistStorageVtbl.InitNew = SvrDoc_PStg_InitNew;
|
||
|
g_SvrDoc_PersistStorageVtbl.Load = SvrDoc_PStg_Load;
|
||
|
g_SvrDoc_PersistStorageVtbl.Save = SvrDoc_PStg_Save;
|
||
|
g_SvrDoc_PersistStorageVtbl.SaveCompleted = SvrDoc_PStg_SaveCompleted;
|
||
|
g_SvrDoc_PersistStorageVtbl.HandsOffStorage = SvrDoc_PStg_HandsOffStorage;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_SvrDoc_PersistStorageVtbl,
|
||
|
sizeof(IPersistStorageVtbl),
|
||
|
"IPersistStorage"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
#if defined( SVR_TREATAS )
|
||
|
// ServerDoc::IStdMarshalInfo method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_SvrDoc_StdMarshalInfoVtbl, sizeof(IStdMarshalInfoVtbl));
|
||
|
g_SvrDoc_StdMarshalInfoVtbl.QueryInterface =
|
||
|
SvrDoc_StdMshl_QueryInterface;
|
||
|
g_SvrDoc_StdMarshalInfoVtbl.AddRef = SvrDoc_StdMshl_AddRef;
|
||
|
g_SvrDoc_StdMarshalInfoVtbl.Release = SvrDoc_StdMshl_Release;
|
||
|
g_SvrDoc_StdMarshalInfoVtbl.GetClassForHandler =
|
||
|
SvrDoc_StdMshl_GetClassForHandler;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_SvrDoc_StdMarshalInfoVtbl,
|
||
|
sizeof(IStdMarshalInfoVtbl),
|
||
|
"IStdMarshalInfo"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
#endif // SVR_TREATAS
|
||
|
|
||
|
#if defined( INPLACE_SVR )
|
||
|
// ServerDoc::IOleInPlaceObject method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_SvrDoc_OleInPlaceObjectVtbl,
|
||
|
sizeof(IOleInPlaceObjectVtbl)
|
||
|
);
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.QueryInterface
|
||
|
= SvrDoc_IPObj_QueryInterface;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.AddRef
|
||
|
= SvrDoc_IPObj_AddRef;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.Release
|
||
|
= SvrDoc_IPObj_Release;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.GetWindow
|
||
|
= SvrDoc_IPObj_GetWindow;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.ContextSensitiveHelp
|
||
|
= SvrDoc_IPObj_ContextSensitiveHelp;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.InPlaceDeactivate
|
||
|
= SvrDoc_IPObj_InPlaceDeactivate;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.UIDeactivate
|
||
|
= SvrDoc_IPObj_UIDeactivate;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.SetObjectRects
|
||
|
= SvrDoc_IPObj_SetObjectRects;
|
||
|
g_SvrDoc_OleInPlaceObjectVtbl.ReactivateAndUndo
|
||
|
= SvrDoc_IPObj_ReactivateAndUndo;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_SvrDoc_OleInPlaceObjectVtbl,
|
||
|
sizeof(IOleInPlaceObjectVtbl),
|
||
|
"IOleInPlaceObject"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// ServerDoc::IOleInPlaceActiveObject method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_SvrDoc_OleInPlaceActiveObjectVtbl,
|
||
|
sizeof(IOleInPlaceActiveObjectVtbl)
|
||
|
);
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.QueryInterface
|
||
|
= SvrDoc_IPActiveObj_QueryInterface;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.AddRef
|
||
|
= SvrDoc_IPActiveObj_AddRef;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.Release
|
||
|
= SvrDoc_IPActiveObj_Release;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.GetWindow
|
||
|
= SvrDoc_IPActiveObj_GetWindow;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.ContextSensitiveHelp
|
||
|
= SvrDoc_IPActiveObj_ContextSensitiveHelp;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.TranslateAccelerator
|
||
|
= SvrDoc_IPActiveObj_TranslateAccelerator;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.OnFrameWindowActivate
|
||
|
= SvrDoc_IPActiveObj_OnFrameWindowActivate;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.OnDocWindowActivate
|
||
|
= SvrDoc_IPActiveObj_OnDocWindowActivate;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.ResizeBorder
|
||
|
= SvrDoc_IPActiveObj_ResizeBorder;
|
||
|
g_SvrDoc_OleInPlaceActiveObjectVtbl.EnableModeless
|
||
|
= SvrDoc_IPActiveObj_EnableModeless;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_SvrDoc_OleInPlaceActiveObjectVtbl,
|
||
|
sizeof(IOleInPlaceActiveObjectVtbl),
|
||
|
"IOleInPlaceActiveObject"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// PseudoObj::IUnknown method table
|
||
|
OleStdInitVtbl(&g_PseudoObj_UnknownVtbl, sizeof(IUnknownVtbl));
|
||
|
g_PseudoObj_UnknownVtbl.QueryInterface = PseudoObj_Unk_QueryInterface;
|
||
|
g_PseudoObj_UnknownVtbl.AddRef = PseudoObj_Unk_AddRef;
|
||
|
g_PseudoObj_UnknownVtbl.Release = PseudoObj_Unk_Release;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_PseudoObj_UnknownVtbl,
|
||
|
sizeof(IUnknownVtbl),
|
||
|
"IUnknown"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// PseudoObj::IOleObject method table
|
||
|
OleStdInitVtbl(&g_PseudoObj_OleObjectVtbl, sizeof(IOleObjectVtbl));
|
||
|
g_PseudoObj_OleObjectVtbl.QueryInterface= PseudoObj_OleObj_QueryInterface;
|
||
|
g_PseudoObj_OleObjectVtbl.AddRef = PseudoObj_OleObj_AddRef;
|
||
|
g_PseudoObj_OleObjectVtbl.Release = PseudoObj_OleObj_Release;
|
||
|
g_PseudoObj_OleObjectVtbl.SetClientSite = PseudoObj_OleObj_SetClientSite;
|
||
|
g_PseudoObj_OleObjectVtbl.GetClientSite = PseudoObj_OleObj_GetClientSite;
|
||
|
g_PseudoObj_OleObjectVtbl.SetHostNames = PseudoObj_OleObj_SetHostNames;
|
||
|
g_PseudoObj_OleObjectVtbl.Close = PseudoObj_OleObj_Close;
|
||
|
g_PseudoObj_OleObjectVtbl.SetMoniker = PseudoObj_OleObj_SetMoniker;
|
||
|
g_PseudoObj_OleObjectVtbl.GetMoniker = PseudoObj_OleObj_GetMoniker;
|
||
|
g_PseudoObj_OleObjectVtbl.InitFromData = PseudoObj_OleObj_InitFromData;
|
||
|
g_PseudoObj_OleObjectVtbl.GetClipboardData =
|
||
|
PseudoObj_OleObj_GetClipboardData;
|
||
|
g_PseudoObj_OleObjectVtbl.DoVerb = PseudoObj_OleObj_DoVerb;
|
||
|
g_PseudoObj_OleObjectVtbl.EnumVerbs = PseudoObj_OleObj_EnumVerbs;
|
||
|
g_PseudoObj_OleObjectVtbl.Update = PseudoObj_OleObj_Update;
|
||
|
g_PseudoObj_OleObjectVtbl.IsUpToDate = PseudoObj_OleObj_IsUpToDate;
|
||
|
g_PseudoObj_OleObjectVtbl.GetUserType = PseudoObj_OleObj_GetUserType;
|
||
|
g_PseudoObj_OleObjectVtbl.GetUserClassID= PseudoObj_OleObj_GetUserClassID;
|
||
|
g_PseudoObj_OleObjectVtbl.SetExtent = PseudoObj_OleObj_SetExtent;
|
||
|
g_PseudoObj_OleObjectVtbl.GetExtent = PseudoObj_OleObj_GetExtent;
|
||
|
g_PseudoObj_OleObjectVtbl.Advise = PseudoObj_OleObj_Advise;
|
||
|
g_PseudoObj_OleObjectVtbl.Unadvise = PseudoObj_OleObj_Unadvise;
|
||
|
g_PseudoObj_OleObjectVtbl.EnumAdvise = PseudoObj_OleObj_EnumAdvise;
|
||
|
g_PseudoObj_OleObjectVtbl.GetMiscStatus = PseudoObj_OleObj_GetMiscStatus;
|
||
|
g_PseudoObj_OleObjectVtbl.SetColorScheme= PseudoObj_OleObj_SetColorScheme;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_PseudoObj_OleObjectVtbl,
|
||
|
sizeof(IOleObjectVtbl),
|
||
|
"IOleObject"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// ServerDoc::IDataObject method table
|
||
|
OleStdInitVtbl(&g_PseudoObj_DataObjectVtbl, sizeof(IDataObjectVtbl));
|
||
|
g_PseudoObj_DataObjectVtbl.QueryInterface =
|
||
|
PseudoObj_DataObj_QueryInterface;
|
||
|
g_PseudoObj_DataObjectVtbl.AddRef = PseudoObj_DataObj_AddRef;
|
||
|
g_PseudoObj_DataObjectVtbl.Release = PseudoObj_DataObj_Release;
|
||
|
g_PseudoObj_DataObjectVtbl.GetData = PseudoObj_DataObj_GetData;
|
||
|
g_PseudoObj_DataObjectVtbl.GetDataHere = PseudoObj_DataObj_GetDataHere;
|
||
|
g_PseudoObj_DataObjectVtbl.QueryGetData = PseudoObj_DataObj_QueryGetData;
|
||
|
g_PseudoObj_DataObjectVtbl.GetCanonicalFormatEtc =
|
||
|
PseudoObj_DataObj_GetCanonicalFormatEtc;
|
||
|
g_PseudoObj_DataObjectVtbl.SetData = PseudoObj_DataObj_SetData;
|
||
|
g_PseudoObj_DataObjectVtbl.EnumFormatEtc= PseudoObj_DataObj_EnumFormatEtc;
|
||
|
g_PseudoObj_DataObjectVtbl.DAdvise = PseudoObj_DataObj_DAdvise;
|
||
|
g_PseudoObj_DataObjectVtbl.DUnadvise = PseudoObj_DataObj_DUnadvise;
|
||
|
g_PseudoObj_DataObjectVtbl.EnumDAdvise = PseudoObj_DataObj_EnumAdvise;
|
||
|
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_PseudoObj_DataObjectVtbl,
|
||
|
sizeof(IDataObjectVtbl),
|
||
|
"IDataObject"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
#endif // OLE_SERVER
|
||
|
|
||
|
|
||
|
|
||
|
#if defined( OLE_CNTR )
|
||
|
|
||
|
/*************************************************************************
|
||
|
** ContainerDoc Supprt Functions Used by Container versions
|
||
|
*************************************************************************/
|
||
|
|
||
|
|
||
|
/* ContainerApp_InitInstance
|
||
|
* -------------------------
|
||
|
*
|
||
|
* Initialize the app instance by creating the main frame window and
|
||
|
* performing app instance specific initializations
|
||
|
* (eg. initializing interface Vtbls).
|
||
|
*
|
||
|
* RETURNS: TRUE if the memory could be allocated, and the server app
|
||
|
* was properly initialized.
|
||
|
* FALSE otherwise
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
BOOL ContainerApp_InitInstance(
|
||
|
LPCONTAINERAPP lpContainerApp,
|
||
|
HINSTANCE hInst,
|
||
|
int nCmdShow
|
||
|
)
|
||
|
{
|
||
|
LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp;
|
||
|
LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp;
|
||
|
|
||
|
lpContainerApp->m_cfCntrOutl=RegisterClipboardFormat(CONTAINERDOCFORMAT);
|
||
|
if(! lpContainerApp->m_cfCntrOutl) {
|
||
|
// REVIEW: should load string from string resource
|
||
|
OutlineApp_ErrorMessage(lpOutlineApp, "Can't register clipboard format!");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
|
||
|
lpContainerApp->m_fPendingUIDeactivate = FALSE;
|
||
|
lpContainerApp->m_fMustResizeClientArea = FALSE;
|
||
|
lpContainerApp->m_lpIPActiveObj = NULL;
|
||
|
lpContainerApp->m_hWndUIActiveObj = NULL;
|
||
|
lpContainerApp->m_hAccelIPCntr = LoadAccelerators(
|
||
|
hInst,
|
||
|
"InPlaceCntrOutlAccel"
|
||
|
);
|
||
|
lpContainerApp->m_hMenuFile = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_FILEMENU
|
||
|
);
|
||
|
lpContainerApp->m_hMenuView = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_VIEWMENU
|
||
|
);
|
||
|
lpContainerApp->m_hMenuDebug = GetSubMenu (
|
||
|
lpOutlineApp->m_hMenuApp,
|
||
|
POS_DEBUGMENU
|
||
|
);
|
||
|
|
||
|
INIT_INTERFACEIMPL(
|
||
|
&lpContainerApp->m_OleInPlaceFrame,
|
||
|
&g_CntrApp_OleInPlaceFrameVtbl,
|
||
|
lpContainerApp
|
||
|
);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/* Setup arrays used by IDataObject::EnumFormatEtc. This is used to
|
||
|
** support copy/paste and drag/drop operations.
|
||
|
**
|
||
|
** OLE2NOTE: The order that the formats are listed for GetData is very
|
||
|
** significant. It should be listed in order of highest fidelity
|
||
|
** formats to least fidelity formats. A common ordering will be:
|
||
|
** 1. private app formats
|
||
|
** 2. CF_EMBEDSOURCE or CF_EMBEDOBJECT (as appropriate)
|
||
|
** 3. lower fidelity interchange formats
|
||
|
** 4. CF_METAFILEPICT
|
||
|
** (graphic-related apps might offer picture 1st!)
|
||
|
** 5. CF_OBJECTDESCRIPTOR
|
||
|
** 6. CF_LINKSOURCE
|
||
|
** 6. CF_LINKSRCDESCRIPTOR
|
||
|
*/
|
||
|
|
||
|
/* m_arrDocGetFmts array enumerates the formats that a ContainerDoc
|
||
|
** object can offer (give) through a IDataObject::GetData call
|
||
|
** when the selection copied is NOT a single embedded object.
|
||
|
** when a single embedded object this list of formats available
|
||
|
** is built dynamically depending on the object copied. (see
|
||
|
** ContainerDoc_SetupDocGetFmts).
|
||
|
** The formats are listed in priority order.
|
||
|
** ContainerDoc objects accept data formats in the following order:
|
||
|
** 1. CF_CNTROUTL
|
||
|
** 2. CF_OUTLINE
|
||
|
** 3. CF_TEXT
|
||
|
** 4. CF_OBJECTDESCRIPTOR
|
||
|
**
|
||
|
** OLE2NOTE: CF_OBJECTDESCRIPTOR format is used to describe the
|
||
|
** data on the clipboard. this information is intended to be
|
||
|
** used, for example, to drive the PasteSpecial dialog. it is
|
||
|
** useful to render CF_OBJECTDESCRIPTOR format even when the
|
||
|
** data on the clipboard does NOT include CF_EMBEDDEDOBJECT
|
||
|
** format or CF_EMBEDSOURCE format as when a selection that is
|
||
|
** not a single OLE object is copied from the container only
|
||
|
** version CNTROUTL. by rendering CF_OBJECTDESCRIPTOR format the
|
||
|
** app can indicate a useful string to identifiy the source of
|
||
|
** the copy to the user.
|
||
|
*/
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[0].cfFormat = lpContainerApp->m_cfCntrOutl;
|
||
|
lpOleApp->m_arrDocGetFmts[0].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[0].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[0].tymed = TYMED_ISTORAGE;
|
||
|
lpOleApp->m_arrDocGetFmts[0].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[1].cfFormat = lpOutlineApp->m_cfOutline;
|
||
|
lpOleApp->m_arrDocGetFmts[1].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[1].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[1].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[1].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[2].cfFormat = CF_TEXT;
|
||
|
lpOleApp->m_arrDocGetFmts[2].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[2].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[2].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[2].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_arrDocGetFmts[3].cfFormat = lpOleApp->m_cfObjectDescriptor;
|
||
|
lpOleApp->m_arrDocGetFmts[3].ptd = NULL;
|
||
|
lpOleApp->m_arrDocGetFmts[3].dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrDocGetFmts[3].tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrDocGetFmts[3].lindex = -1;
|
||
|
|
||
|
lpOleApp->m_nDocGetFmts = 4;
|
||
|
|
||
|
/* m_arrSingleObjGetFmts array enumerates the formats that a
|
||
|
** ContainerDoc object can offer (give) through a
|
||
|
** IDataObject::GetData call when the selection copied IS a
|
||
|
** single OLE object.
|
||
|
** ContainerDoc objects accept data formats in the following order:
|
||
|
** 1. CF_CNTROUTL
|
||
|
** 2. CF_EMBEDDEDOBJECT
|
||
|
** 3. CF_OBJECTDESCRIPTOR
|
||
|
** 4. CF_METAFILEPICT (note DVASPECT will vary)
|
||
|
** 5. CF_LINKSOURCE *
|
||
|
** 6. CF_LINKSRCDESCRIPTOR *
|
||
|
**
|
||
|
** * OLE2NOTE: CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR is only
|
||
|
** offered if the OLE object is allowed to be linked to from the
|
||
|
** inside (ie. we are allowed to give out a moniker which binds
|
||
|
** to the running OLE object), then we want to offer
|
||
|
** CF_LINKSOURCE format. if the object is an OLE 2.0 embedded
|
||
|
** object then it is allowed to be linked to from the inside. if
|
||
|
** the object is either an OleLink or an OLE 1.0 embedding then
|
||
|
** it can not be linked to from the inside. if we were a
|
||
|
** container/server app then we could offer linking to the
|
||
|
** outside of the object (ie. a pseudo object within our
|
||
|
** document). we are a container only app that does not support
|
||
|
** linking to ranges of its data.
|
||
|
** the simplest way to determine if an object can be linked to
|
||
|
** on the inside is to call IOleObject::GetMiscStatus and test
|
||
|
** to see if the OLEMISC_CANTLINKINSIDE bit is NOT set.
|
||
|
**
|
||
|
** OLE2NOTE: optionally, a container that wants to have a
|
||
|
** potentially richer data transfer, can enumerate the data
|
||
|
** formats from the OLE object's cache and offer them too. if
|
||
|
** the object has a special handler, then it might be able to
|
||
|
** render additional data formats.
|
||
|
*/
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[0].cfFormat =
|
||
|
lpContainerApp->m_cfCntrOutl;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[0].ptd = NULL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[0].dwAspect = DVASPECT_CONTENT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[0].tymed = TYMED_ISTORAGE;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[0].lindex = -1;
|
||
|
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[1].cfFormat =
|
||
|
lpOleApp->m_cfEmbeddedObject;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[1].ptd = NULL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[1].dwAspect = DVASPECT_CONTENT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[1].tymed = TYMED_ISTORAGE;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[1].lindex = -1;
|
||
|
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[2].cfFormat =
|
||
|
lpOleApp->m_cfObjectDescriptor;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[2].ptd = NULL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[2].dwAspect = DVASPECT_CONTENT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[2].tymed = TYMED_HGLOBAL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[2].lindex = -1;
|
||
|
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[3].cfFormat = CF_METAFILEPICT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[3].ptd = NULL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[3].dwAspect = DVASPECT_CONTENT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[3].tymed = TYMED_MFPICT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[3].lindex = -1;
|
||
|
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[4].cfFormat =
|
||
|
lpOleApp->m_cfLinkSource;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[4].ptd = NULL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[4].dwAspect = DVASPECT_CONTENT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[4].tymed = TYMED_ISTREAM;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[4].lindex = -1;
|
||
|
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[5].cfFormat =
|
||
|
lpOleApp->m_cfLinkSrcDescriptor;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[5].ptd = NULL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[5].dwAspect = DVASPECT_CONTENT;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[5].tymed = TYMED_HGLOBAL;
|
||
|
lpContainerApp->m_arrSingleObjGetFmts[5].lindex = -1;
|
||
|
|
||
|
lpContainerApp->m_nSingleObjGetFmts = 6;
|
||
|
|
||
|
/* NOTE: the Container-Only version of Outline does NOT offer
|
||
|
** IDataObject interface from its User documents and the
|
||
|
** IDataObject interface available from DataTransferDoc's do NOT
|
||
|
** support SetData. IDataObject interface is required by objects
|
||
|
** which can be embedded or linked. the Container-only app only
|
||
|
** allows linking to its contained objects, NOT the data of the
|
||
|
** container itself.
|
||
|
*/
|
||
|
|
||
|
/* m_arrPasteEntries array enumerates the formats that a ContainerDoc
|
||
|
** object can accept from the clipboard. this array is used to
|
||
|
** support the PasteSpecial dialog.
|
||
|
** The formats are listed in priority order.
|
||
|
** ContainerDoc objects accept data formats in the following order:
|
||
|
** 1. CF_CNTROUTL
|
||
|
** 2. CF_OUTLINE
|
||
|
** 3. CF_EMBEDDEDOBJECT
|
||
|
** 4. CF_TEXT
|
||
|
** 5. CF_METAFILEPICT
|
||
|
** 6. CF_DIB
|
||
|
** 7. CF_BITMAP
|
||
|
** 8. CF_LINKSOURCE
|
||
|
**
|
||
|
** NOTE: specifying CF_EMBEDDEDOBJECT in the PasteEntry array
|
||
|
** indicates that the caller is interested in pasting OLE
|
||
|
** objects (ie. the caller calls OleCreateFromData). the
|
||
|
** OleUIPasteSpecial dialog and OleStdGetPriorityClipboardFormat
|
||
|
** call OleQueryCreateFromData to see if an OLE object format is
|
||
|
** available. thus, in fact if CF_EMBEDSOURCE or CF_FILENAME are
|
||
|
** available from the data source then and OLE object can be
|
||
|
** created and this entry will be matched. the caller should
|
||
|
** only specify one object type format.
|
||
|
** CF_FILENAME format (as generated by copying a file to
|
||
|
** the clipboard from the FileManager) is considered an object
|
||
|
** format; OleCreatFromData creates an object if the file has an
|
||
|
** associated class (see GetClassFile API) or if no class it
|
||
|
** creates an OLE 1.0 Package object. this format can also be
|
||
|
** paste linked by calling OleCreateLinkFromData.
|
||
|
*/
|
||
|
// REVIEW: strings should be loaded from string resource
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.cfFormat =
|
||
|
lpContainerApp->m_cfCntrOutl;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.tymed = TYMED_ISTORAGE;
|
||
|
lpOleApp->m_arrPasteEntries[0].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[0].lpstrFormatName = "Container Outline Data";
|
||
|
lpOleApp->m_arrPasteEntries[0].lpstrResultText =
|
||
|
"Container Outline Data";
|
||
|
lpOleApp->m_arrPasteEntries[0].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.cfFormat =lpOutlineApp->m_cfOutline;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrPasteEntries[1].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[1].lpstrFormatName = "Outline Data";
|
||
|
lpOleApp->m_arrPasteEntries[1].lpstrResultText = "Outline Data";
|
||
|
lpOleApp->m_arrPasteEntries[1].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[2].fmtetc.cfFormat =
|
||
|
lpOleApp->m_cfEmbeddedObject;
|
||
|
lpOleApp->m_arrPasteEntries[2].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[2].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[2].fmtetc.tymed = TYMED_ISTORAGE;
|
||
|
lpOleApp->m_arrPasteEntries[2].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[2].lpstrFormatName = "%s";
|
||
|
lpOleApp->m_arrPasteEntries[2].lpstrResultText = "%s";
|
||
|
lpOleApp->m_arrPasteEntries[2].dwFlags =
|
||
|
OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[3].fmtetc.cfFormat = CF_TEXT;
|
||
|
lpOleApp->m_arrPasteEntries[3].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[3].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[3].fmtetc.tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrPasteEntries[3].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[3].lpstrFormatName = "Text";
|
||
|
lpOleApp->m_arrPasteEntries[3].lpstrResultText = "text";
|
||
|
lpOleApp->m_arrPasteEntries[3].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[4].fmtetc.cfFormat = CF_METAFILEPICT;
|
||
|
lpOleApp->m_arrPasteEntries[4].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[4].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[4].fmtetc.tymed = TYMED_MFPICT;
|
||
|
lpOleApp->m_arrPasteEntries[4].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[4].lpstrFormatName = "Picture (Metafile)";
|
||
|
lpOleApp->m_arrPasteEntries[4].lpstrResultText = "a static picture";
|
||
|
lpOleApp->m_arrPasteEntries[4].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[5].fmtetc.cfFormat = CF_DIB;
|
||
|
lpOleApp->m_arrPasteEntries[5].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[5].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[5].fmtetc.tymed = TYMED_HGLOBAL;
|
||
|
lpOleApp->m_arrPasteEntries[5].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[5].lpstrFormatName = "Picture (DIB)";
|
||
|
lpOleApp->m_arrPasteEntries[5].lpstrResultText = "a static picture";
|
||
|
lpOleApp->m_arrPasteEntries[5].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[6].fmtetc.cfFormat = CF_BITMAP;
|
||
|
lpOleApp->m_arrPasteEntries[6].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[6].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[6].fmtetc.tymed = TYMED_GDI;
|
||
|
lpOleApp->m_arrPasteEntries[6].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[6].lpstrFormatName = "Picture (Bitmap)";
|
||
|
lpOleApp->m_arrPasteEntries[6].lpstrResultText = "a static picture";
|
||
|
lpOleApp->m_arrPasteEntries[6].dwFlags = OLEUIPASTE_PASTEONLY;
|
||
|
|
||
|
lpOleApp->m_arrPasteEntries[7].fmtetc.cfFormat = lpOleApp->m_cfLinkSource;
|
||
|
lpOleApp->m_arrPasteEntries[7].fmtetc.ptd = NULL;
|
||
|
lpOleApp->m_arrPasteEntries[7].fmtetc.dwAspect = DVASPECT_CONTENT;
|
||
|
lpOleApp->m_arrPasteEntries[7].fmtetc.tymed = TYMED_ISTREAM;
|
||
|
lpOleApp->m_arrPasteEntries[7].fmtetc.lindex = -1;
|
||
|
lpOleApp->m_arrPasteEntries[7].lpstrFormatName = "%s";
|
||
|
lpOleApp->m_arrPasteEntries[7].lpstrResultText = "%s";
|
||
|
lpOleApp->m_arrPasteEntries[7].dwFlags =
|
||
|
OLEUIPASTE_LINKTYPE1 | OLEUIPASTE_ENABLEICON;
|
||
|
|
||
|
lpOleApp->m_nPasteEntries = 8;
|
||
|
|
||
|
/* m_arrLinkTypes array enumerates the link types that a ContainerDoc
|
||
|
** object can accept from the clipboard
|
||
|
*/
|
||
|
|
||
|
lpOleApp->m_arrLinkTypes[0] = lpOleApp->m_cfLinkSource;
|
||
|
lpOleApp->m_nLinkTypes = 1;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ContainerApp_InitVtbls
|
||
|
** ----------------------
|
||
|
**
|
||
|
** initialize the interface Vtbl's used to support the OLE 2.0
|
||
|
** Container functionality.
|
||
|
*/
|
||
|
|
||
|
BOOL ContainerApp_InitVtbls(LPCONTAINERAPP lpApp)
|
||
|
{
|
||
|
BOOL fStatus;
|
||
|
|
||
|
// ContainerDoc::IOleUILinkContainer method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_CntrDoc_OleUILinkContainerVtbl,
|
||
|
sizeof(IOleUILinkContainerVtbl)
|
||
|
);
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.QueryInterface =
|
||
|
CntrDoc_LinkCont_QueryInterface;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.AddRef = CntrDoc_LinkCont_AddRef;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.Release = CntrDoc_LinkCont_Release;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.GetNextLink =
|
||
|
CntrDoc_LinkCont_GetNextLink;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.SetLinkUpdateOptions =
|
||
|
CntrDoc_LinkCont_SetLinkUpdateOptions;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.GetLinkUpdateOptions =
|
||
|
CntrDoc_LinkCont_GetLinkUpdateOptions;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.SetLinkSource =
|
||
|
CntrDoc_LinkCont_SetLinkSource;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.GetLinkSource =
|
||
|
CntrDoc_LinkCont_GetLinkSource;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.OpenLinkSource =
|
||
|
CntrDoc_LinkCont_OpenLinkSource;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.UpdateLink =
|
||
|
CntrDoc_LinkCont_UpdateLink;
|
||
|
g_CntrDoc_OleUILinkContainerVtbl.CancelLink =
|
||
|
CntrDoc_LinkCont_CancelLink;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_CntrDoc_OleUILinkContainerVtbl,
|
||
|
sizeof(IOleUILinkContainerVtbl),
|
||
|
"IOleUILinkContainer"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
|
||
|
// ContainerApp::IOleInPlaceFrame interface method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_CntrApp_OleInPlaceFrameVtbl,
|
||
|
sizeof(g_CntrApp_OleInPlaceFrameVtbl)
|
||
|
);
|
||
|
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.QueryInterface
|
||
|
= CntrApp_IPFrame_QueryInterface;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.AddRef
|
||
|
= CntrApp_IPFrame_AddRef;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.Release
|
||
|
= CntrApp_IPFrame_Release;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.GetWindow
|
||
|
= CntrApp_IPFrame_GetWindow;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.ContextSensitiveHelp
|
||
|
= CntrApp_IPFrame_ContextSensitiveHelp;
|
||
|
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.GetBorder
|
||
|
= CntrApp_IPFrame_GetBorder;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.RequestBorderSpace
|
||
|
= CntrApp_IPFrame_RequestBorderSpace;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.SetBorderSpace
|
||
|
= CntrApp_IPFrame_SetBorderSpace;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.SetActiveObject
|
||
|
= CntrApp_IPFrame_SetActiveObject;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.InsertMenus
|
||
|
= CntrApp_IPFrame_InsertMenus;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.SetMenu
|
||
|
= CntrApp_IPFrame_SetMenu;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.RemoveMenus
|
||
|
= CntrApp_IPFrame_RemoveMenus;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.SetStatusText
|
||
|
= CntrApp_IPFrame_SetStatusText;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.EnableModeless
|
||
|
= CntrApp_IPFrame_EnableModeless;
|
||
|
g_CntrApp_OleInPlaceFrameVtbl.TranslateAccelerator
|
||
|
= CntrApp_IPFrame_TranslateAccelerator;
|
||
|
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_CntrApp_OleInPlaceFrameVtbl,
|
||
|
sizeof(g_CntrApp_OleInPlaceFrameVtbl),
|
||
|
"IOleInPlaceFrame"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
#endif // INPLACE_CNTR
|
||
|
|
||
|
|
||
|
// ContainerLine::IUnknown interface method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_CntrLine_UnknownVtbl,
|
||
|
sizeof(g_CntrLine_UnknownVtbl)
|
||
|
);
|
||
|
g_CntrLine_UnknownVtbl.QueryInterface = CntrLine_Unk_QueryInterface;
|
||
|
g_CntrLine_UnknownVtbl.AddRef = CntrLine_Unk_AddRef;
|
||
|
g_CntrLine_UnknownVtbl.Release = CntrLine_Unk_Release;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_CntrLine_UnknownVtbl,
|
||
|
sizeof(g_CntrLine_UnknownVtbl),
|
||
|
"IUnknown"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// ContainerLine::IOleClientSite interface method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_CntrLine_OleClientSiteVtbl,
|
||
|
sizeof(g_CntrLine_OleClientSiteVtbl)
|
||
|
);
|
||
|
g_CntrLine_OleClientSiteVtbl.QueryInterface =
|
||
|
CntrLine_CliSite_QueryInterface;
|
||
|
g_CntrLine_OleClientSiteVtbl.AddRef = CntrLine_CliSite_AddRef;
|
||
|
g_CntrLine_OleClientSiteVtbl.Release = CntrLine_CliSite_Release;
|
||
|
g_CntrLine_OleClientSiteVtbl.SaveObject = CntrLine_CliSite_SaveObject;
|
||
|
g_CntrLine_OleClientSiteVtbl.GetMoniker = CntrLine_CliSite_GetMoniker;
|
||
|
g_CntrLine_OleClientSiteVtbl.GetContainer = CntrLine_CliSite_GetContainer;
|
||
|
g_CntrLine_OleClientSiteVtbl.ShowObject = CntrLine_CliSite_ShowObject;
|
||
|
g_CntrLine_OleClientSiteVtbl.OnShowWindow = CntrLine_CliSite_OnShowWindow;
|
||
|
g_CntrLine_OleClientSiteVtbl.RequestNewObjectLayout =
|
||
|
CntrLine_CliSite_RequestNewObjectLayout;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_CntrLine_OleClientSiteVtbl,
|
||
|
sizeof(g_CntrLine_OleClientSiteVtbl),
|
||
|
"IOleClientSite"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
// ContainerLine::IAdviseSink interface method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_CntrLine_AdviseSinkVtbl,
|
||
|
sizeof(g_CntrLine_AdviseSinkVtbl)
|
||
|
);
|
||
|
g_CntrLine_AdviseSinkVtbl.QueryInterface= CntrLine_AdvSink_QueryInterface;
|
||
|
g_CntrLine_AdviseSinkVtbl.AddRef = CntrLine_AdvSink_AddRef;
|
||
|
g_CntrLine_AdviseSinkVtbl.Release = CntrLine_AdvSink_Release;
|
||
|
g_CntrLine_AdviseSinkVtbl.OnDataChange = CntrLine_AdvSink_OnDataChange;
|
||
|
g_CntrLine_AdviseSinkVtbl.OnViewChange = CntrLine_AdvSink_OnViewChange;
|
||
|
g_CntrLine_AdviseSinkVtbl.OnRename = CntrLine_AdvSink_OnRename;
|
||
|
g_CntrLine_AdviseSinkVtbl.OnSave = CntrLine_AdvSink_OnSave;
|
||
|
g_CntrLine_AdviseSinkVtbl.OnClose = CntrLine_AdvSink_OnClose;
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_CntrLine_AdviseSinkVtbl,
|
||
|
sizeof(g_CntrLine_AdviseSinkVtbl),
|
||
|
"IAdviseSink"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
|
||
|
#if defined( INPLACE_CNTR )
|
||
|
|
||
|
// ContainerLine::IOleInPlaceSite interface method table
|
||
|
OleStdInitVtbl(
|
||
|
&g_CntrLine_OleInPlaceSiteVtbl,
|
||
|
sizeof(g_CntrLine_OleInPlaceSiteVtbl)
|
||
|
);
|
||
|
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.QueryInterface
|
||
|
= CntrLine_IPSite_QueryInterface;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.AddRef
|
||
|
= CntrLine_IPSite_AddRef;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.Release
|
||
|
= CntrLine_IPSite_Release;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.GetWindow
|
||
|
= CntrLine_IPSite_GetWindow;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.ContextSensitiveHelp
|
||
|
= CntrLine_IPSite_ContextSensitiveHelp;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.CanInPlaceActivate
|
||
|
= CntrLine_IPSite_CanInPlaceActivate;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.OnInPlaceActivate
|
||
|
= CntrLine_IPSite_OnInPlaceActivate;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.OnUIActivate
|
||
|
= CntrLine_IPSite_OnUIActivate;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.GetWindowContext
|
||
|
= CntrLine_IPSite_GetWindowContext;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.Scroll
|
||
|
= CntrLine_IPSite_Scroll;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.OnUIDeactivate
|
||
|
= CntrLine_IPSite_OnUIDeactivate;
|
||
|
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.OnInPlaceDeactivate
|
||
|
= CntrLine_IPSite_OnInPlaceDeactivate;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.DiscardUndoState
|
||
|
= CntrLine_IPSite_DiscardUndoState;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.DeactivateAndUndo
|
||
|
= CntrLine_IPSite_DeactivateAndUndo;
|
||
|
g_CntrLine_OleInPlaceSiteVtbl.OnPosRectChange
|
||
|
= CntrLine_IPSite_OnPosRectChange;
|
||
|
|
||
|
fStatus = OleStdCheckVtbl(
|
||
|
&g_CntrLine_OleInPlaceSiteVtbl,
|
||
|
sizeof(g_CntrLine_OleInPlaceSiteVtbl),
|
||
|
"IOleInPlaceSite"
|
||
|
);
|
||
|
if (! fStatus) return FALSE;
|
||
|
|
||
|
#endif // INPLACE_CNTR
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // OLE_CNTR
|