MORE INFORMATION
ActiveX document servers often need to know the full URL of the currently
open document file. For example, when an ActiveX document is hosted inside
the Internet Explorer frame, Internet Explorer downloads the data for the
document from the World Wide Web, invokes the server for that particular
document type, and then passes the data to the ActiveX document.
Specifically, the server may need to know that the data was actually pulled
from "http://example.microsoft.com/test.doc."
In most cases, an ActiveX document server needs the moniker that represents
the current document source. You can use the IMoniker::GetDisplayName()
method to determine the correct URL or file path of the document. This
information is especially important to ActiveX document servers that need
to access additional supporting data files from locations relative to the
URL of the current ActiveX document file. Once the ActiveX document has
retrieved the URL from GetDisplayName, it can determine a new absolute URL
for any extra data files it may need.
This article discusses two possible ways of obtaining a moniker to the
document source.
Implement the IPersistMoniker Interface
IPersistMoniker is one of the newest OLE/COM persistence mechanisms. It
allows an ActiveX document server (or other OLE server) to decide how it
persists itself into data, and it gives the server complete control over
how that data is obtained. As a result, the server will have a moniker that
represents the source of the data.
When navigating to an ActiveX document structured storage file, Internet
Explorer first reads a piece of the data file to determine the CLSID of the
ActiveX document. If the CLSID is available, Internet Explorer will have
enough information to load the document's server. Because Web documents may
take a long time to download completely, the server is usually created
before all of the data is available.
After the server is created, Internet Explorer performs a QueryInterface on
the server's document object for IPersistMoniker. If IPersistMoniker is not
supported, Internet Explorer reverts to the standard IPersistFile loading
mechanism. If IPersistMoniker is supported, Internet Explorer calls the
IPersistMoniker::Load method with the moniker it used to begin downloading
the data file. The ActiveX document server can then use the same moniker to
re-bind to the data file, which usually does not result in a second
download. Note that the server can retrieve the data from the supplied
moniker using whatever method it chooses.
The following sample code demonstrates the implementation of
IPersistMoniker::Load in a Visual C++ 5.0 MFC-based ActiveX document:
Sample Code:
// Necessary INCLUDES
#include <comdef.h>
#include <afxconv.h>
#include <urlmon.h>
// BEGIN_INTERFACE_MAP section for CPP file:
BEGIN_INTERFACE_MAP(CAxDoc, COleServerDoc)
// Other entries...
INTERFACE_PART(CAxDoc, IID_IPersistMoniker, PersistMoniker)
END_INTERFACE_MAP()
STDMETHODIMP CAxDoc::XPersistMoniker::Load(BOOL fFullyAvailable,
IMoniker __RPC_FAR *pimkName,
LPBC pibc, DWORD grfMode)
{
USES_CONVERSION;
METHOD_PROLOGUE_EX_(CAxDoc, PersistMoniker)
if (NULL == pimkName)
return E_FAIL;
// This is not efficient, but all data must be available
// If S_FALSE is returned, then a call back is made
// when the data is available
if (!fFullyAvailable)
return S_FALSE;
LPOLESTR strDisplayName;
pimkName->GetDisplayName(NULL, NULL, &strDisplayName);
pThis->m_strDataURL = OLE2T(strDisplayName);
try {
// Use the moniker to download the persisted data
// and obtain an IStorage on that data
IStoragePtr pStorage;
pimkName->BindToStorage(pibc, NULL, IID_IStorage,
(void**)&pStorage);
// Now use the default MFC implementation of IPersistStorage
// From this point forward, assume that
// IPersistStorage was used to persist the data.
IPersistStoragePtr pPersistStorage;
pThis->InternalQueryInterface(&IID_IPersistStorage,
(void**)&pPersistStorage);
pPersistStorage->Load(pStorage);
}
catch(...)
{
return E_FAIL;
}
return S_OK;
}
Use the IOleClientSite::GetMoniker Method
OLE/COM servers have used this method for some time and it is also
available to ActiveX document servers.
The following sample code demonstrates the implementation of
IOleClientSite::GetMoniker in a Visual C++ 5.0 MFC-based ActiveX document:
Sample Code:
LPMONIKER CAxDoc::GetMoniker()
{
LPMONIKER pmkThis = NULL;
if (m_lpClientSite &&
m_lpClientSite->GetMoniker(OLEGETMONIKER_FORCEASSIGN,
OLEWHICHMK_OBJFULL,
&pmkThis) != S_OK)
{
// To be safe, always set moniker to NULL on failure
pmkThis = NULL;
}
return pmkThis;
}
REFERENCES
In some sample code, this article uses Visual C++ 5.0 Smart Pointers
(IxxxPtr). For more information on Visual C++ 5.0 Smart Pointers and other
COM compiler features available in Visual C++ 5.0, please review the
following documentation:
Visual C++ Books Online: Visual C++; Visual C++ Programmer's Guide; Adding Program Functionality; Overviews; Compiler COM Support: Overview