Programming an Active Document ContainerProgramming an Active Document Container*
*Contents  *Index  *Topic Contents
*Previous Topic: Programming an Active Document Server
*Next Topic: Reference

Programming an Active Document Container

An Active Document container is an application that provides the view in which an Active Document resides. Instead of providing a document in which an in-place object resides, the container provides the basic user interface features that are specific to the container, and allows the server to merge its menus and add any other user interface components within the view area of the container. This allows the container to host any number of different Active Documents while still maintaining a user interface that is familiar to the user.

arrowg.gifThe Basics

arrowg.gifLoading the Active Document

arrowg.gifMiscellaneous Requirements

arrowg.gifPalette Management for Active Document Containers

The Basics

To create an Active Document container, you must implement the following interfaces. Some of these interfaces are not required for a minimal implementation of a container. This table specifies which interfaces are required.
Interface Required Description
IOleDocumentSite Yes The Active Document object uses this interface to request that the container activate it.
IOleClientSite Yes The Active Document object uses this interface to obtain information about the location and extent of its display site, its user interface, and other resources provided by the container.
IOleInPlaceSite Yes The Active Document object uses this interface to control in-place activation from within the container.
IAdviseSink Yes The Active Document object uses this interface to notify objects with which they have an advisory connection of changes in an object's data, view, name, or state.
IOleCommandTarget No The Active Document object uses this interface to dispatch commands and obtain command status information from the Active Document.
IContinueCallback No This is a generic callback mechanism for interruptible processes that should periodically ask an object whether to continue.

Loading the Active Document

To load the Active Document, your container should perform the following steps. These steps discuss how and when to create, activate, display, and close an Active Document.

Creating the Active Document Object

When opening an Active Document file, you need to create an instance of the Active Document object. This is accomplished with the OleCreateFromFile API. You pass this API a valid IStorage pointer and the name of the file you want to create the object from. If the API succeeds, you will receive a pointer to the Active Document object. This is the interface you will use to control the object. You can use this pointer to use QueryInterface for the IOleObject and/or IOleDocument interface pointers.

When you have the object's interface, you need to do the following:

  1. Set the object's client site by calling its IOleObject::SetClientSite method, passing your IOleClientSite interface.
  2. Set the object's advise sink by calling the object's IOleObject::Advise method, passing your IAdviseSink interface.
  3. Place the Active Document object into the running state by calling OleRun, passing the object's interface pointer.
  4. Obtain the Active Document view pointer by calling the object's IOleObject::DoVerb method with the iVerb parameter equal to OLEIVERB_SHOW. In response to this, the object will call your IOleDocumentSite::ActivateMe method. In IOleDocumentSite::ActivateMe, if the pViewToActivate parameter is not NULL, it contains the object's IOleDocumentView pointer. If pViewToActivate is NULL, you must call the object's IOleDocument::CreateView method to create the view.

    In the IOleDocument::CreateView call, the pIPSite and pstm parameters are optional. If you don't include them, or if you obtained the object's view pointer directly in IOleDocumentSite::ActivateMe, you will need to call the object's IOleDocumentView::SetInPlaceSite method with your IOleInPlaceSite pointer to set the view's in-place site and call the object's IOleDocumentView::ApplyViewState method with your view state stream pointer. This allows the view to obtain its view state information.

Activating the Active Document View

When you have the object's view pointer, you need to activate the view. These are the steps involved in this process:

  1. Call the object's IOleDocumentView::UIActivate method with the fUIActivate parameter set to TRUE.
  2. Set the object's display rectangle by calling its IOleDocumentView::SetRect method.
  3. Show the view by calling the object's IOleDocumentView::Show method with the fShow parameter set to TRUE.

Deactivating the Active Document View

To deactivate the view, hide it by calling the object's IOleDocumentView::Show method with FALSE. You then call the object's IOleDocumentView::UIActivate method with FALSE.

Closing the Active Document

To close the document, perform the following steps:

  1. Deactivate the view.
  2. Call the object's IOleDocumentView::CloseView method to close the view.
  3. When the view has been closed, the IOleDocumentView object is no longer valid, so you must release its pointer.
  4. Release any other pointers you have obtained from the object.
  5. Release the IOleDocument pointer.

Miscellaneous Requirements

You should design your container with these points in mind:

Palette Management for Active Document Containers

In general, the palette management scheme for Active Document containers is the same as the scheme used for ActiveX™ Controls, except that containers do not give ambient properties to the document. There are two different cases that need to be considered. The first is if the container can activate only one Active Document object at a time. The second is if the container can activate more than one Active Document object at a time.

Single Document Case

In the most common cases, your container will activate only one Active Document at a time. In this situation, it is best to allow the Active Document to have complete control over the palette, which includes managing palette issues for any controls or content within that document. To accomplish this, it is necessary for you to forward all Microsoft® Windows® palette management messages on to the Active Document. The following is a simple demonstration of how to forward these messages to the Active Document.

case WM_PALETTECHANGED:
case WM_QUERYNEWPALETTE:
   {
   HWND hwnd;
   IOleWindow *pOleWindow;
   if(pDocObj && SUCCEEDED(pDocObj->QueryInterface(IID_IOleWindow, 
         (LPVOID*)&pOleWindow))) 
      {
      LRESULT lres = 0;
      if (SUCCEEDED(pOleWindow->GetWindow(&hwnd))) 
         {
         lres = SendMessage(hwnd, uMsg, wParam, lParam);
         }

      pOleWindow->Release();
      return lres;
      }
   break;
   }

Multiple Document Case

In rare cases, your container might be able to activate more than one Active Document at a time. While you can implement such a container, you should avoid doing so if at all possible. One of the reasons this is discouraged is that no protocol currently exists for communicating palettes between an Active Document and its container. Therefore, the container cannot create a palette suitable to all Active Documents that it has activated.

Because of this, the activated Active Document in the foreground has control over the palette and will use foreground palette rendering. Other activated Active Documents in the background will use background palette rendering. The Active Document container itself does not participate in palette management at all.


Up Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.