ActiveX Documents and the World Wide Web

Microsoft's ActiveX Documents are designed to make it possible for heterogeneous documents to integrate seamlessly with a wide variety of container applications, including multivendor Web browsers.


October 01, 1996
URL:http://www.drdobbs.com/web-development/activex-documents-and-the-world-wide-we/184410094

Web Development: ActiveX...

ActiveX Documents and the World

Wide Web

Documents that are embeddable as objects


Vinod Anantharaman

Vinod, a program manager at Microsoft, can be contacted at [email protected].


Although the predominant document format on the World Wide Web is HTML, there is a storehouse of information that exists in other formats. This information may or may not integrate smoothly with the Web. One solution to this problem has been for applications to support a Save As HTML command to convert documents. But this may not always be practical because frequently only a subset of the native document content can be reasonably transformed into HTML. Also, "Save As HTML" represents an extra step to publish to the Web.

ActiveX Documents address this problem by making it possible for heterogeneous documents to integrate seamlessly with a wide variety of container applications, including multivendor web browsers. ActiveX Documents are an integral part of Microsoft's ActiveX technologies, which help software developers and web designers make static web pages come alive with more active contentanimation, 3-D virtual reality, video, and multimedia. ActiveX Documents are based on an underlying technology called "Document Objects" (DocObjects) that were introduced in the form of the Binder and WordMail applications in Microsoft Office Suite for Windows 95 (Office 95). In this article, I'll present an overview of DocObjects and discuss their use in different container applications. I'll also examine what it takes to implement a DocObject server or container.

Non-HTML Documents on the Web

Most web pages tend to be compound documents based on HTML. HTML lets you embed graphics formats such as GIF and JPEG into text streams by identifying these formats using special HTML tags. Most web browsers are capable of rendering these common formats natively. However, if your web page includes documents in another format (for instance, those generated by word processing, charting, drawing, CAD, or spreadsheet applications), they are not natively rendered in most browsers. Such documents appear as "foreign" objects that get serviced by their corresponding server applications, which are completely dissociated from the browser. When users click on such objects in the web page, the browser launches the server application in its own window and users have to view the embedded document there. Having to jump back and forth between the browser and application window causes a context switch that can be confusing and annoying. In addition, most browsers include features such as a "history" list of documents that have been browsed during a session and a "favorites" list of documents. These features, too, are tailored toward HTMLarbitrary document types typically cannot be part of such lists. What users need is a means of integrating such documents more tightly with web-browser software.

Embedded OLE Objects versus DocObjects

Embedded OLE objects have limitations when it comes to seamless integration of entire documents within containers. Embedded objects in traditional OLE-based compound documents are optimized for displaying relatively small pieces of server content within a containing document's page; for instance, a bitmap, chart, or spreadsheet table embedded inside a word-processor document.

OLE 2.0 introduced the notion of in-place activation that allows embedded objects to be edited within the container application, without the need to switch to the server's own window. In Figure 1, for instance, a Paint bitmap is in-place active inside a Word document. Object activation happens via explicit user action; by default, embedded objects sit dormant in their containers until the user double-clicks on the object (or runs the Edit verb on it from a context menu), upon which the container loads the object's server to allow editing. You can think of an embedded object as owning a small rectangular region within a page owned by the container document. The container tells the object how big it is in the online view and on the printed page, and this size is restricted by the page size of the container document. The container renders the embedded object as a simple metafile, in both the inactive view and on the printed page, rather than calling server code that asks the object to render itself. Consequently, multipage documents are not elegantly handled when embedded as standard OLE 2.0 objectsthey get clipped inside a restricted rectangular region both in the online view and when printed. Users need a means of integrating entire documents into container applications with none of these view and print restrictions.

DocObjects are full-scale, conventional documents that are embeddable as objects in compliant containers. They are always displayed in their native format within their container frame. They fully control their page layout and printing by virtue of their support for print interfaces, as opposed to passive metafile rendition, (as is the case with embedded OLE objects). DocObjects always occupy the entire editing area of a container and are always in-place active, so their servers are always available for editing with no special action on the part of the user.

You can think of DocObjects as convenient plug-ins that allow documents to appear natively in web browsers, with the full functionality of the document-server application available for WYSIWYG editing within the browser window. Adding DocObject support to a server application ensures that any document created with it will plug into DocObject-compliant web browsers without work on the part of the document author. For end users, DocObjects represent the cheapest web-publishing solution, since users are not required to do anything different than they are already doing. This technology would, for instance, let an employee in a company navigate a corporate Intranet to view a department's web page, examine the department's budget spreadsheet, query the database for sales data, or write a memoall from within the web browser--without converting that content to HTML.

The most-recent versions of the NCSA Mosaic browser and the Microsoft Internet Explorer are capable of hosting DocObjects. By supporting DocObject container interfaces, web-browser vendors extend the repertoire of content that their browsers can handle to include arbitrary document formats beyond plain HTML. Figure 2 is a Word document hosted as a DocObject inside an early version of Microsoft Internet Explorer 3.0. As you can see, the Word document appears in its native format within the browser, just as you would expect of an HTML document. The Word document is fully integrated with the browser's favorites and history lists, and all of Word's toolbars and menus are available for editing.

DocObjects were introduced as part of Office 95. Word, Excel, and Powerpoint were enhanced to become DocObject servers. A DocObject container application called the "Binder" was introduced as part of the suite. Binder can be best thought of as an electronic paper clip that "binds" together multiple subdocuments (known as "sections"), each of which can span multiple pages. Sections can be created using Word, Excel, Powerpoint, and other third-party DocObject server applications. Each compound document created by Binder behaves as a single entity in every respectit saves with a unique filename, can be mailed or routed electronically as a single unit, and prints as a single job.

Figure 3 is a Binder compound document called "Report" that contains five sections created with three different DocObject serversWord, Powerpoint, and Excel. The section currently active in the Binder is called "Data," which happens to be in Excel. As you can see, Excel is hosted as a DocObject that extends to take up the entire available client area of the Binder container, and all of Excel's toolbars and menus are available to the user for editing the section.

WordMail also illustrates DocObject technology. Since Microsoft Word in Office 95 is a DocObject server, the Microsoft Exchange mail client (which is included as a standard part of Windows 95) simply added DocObject container support, thus making all of Word's rich-editing and word-processing features available inside Exchange mail notes. WordMail users can make the most of Word's support for templates, styles, revision marks, Auto-Correct, drawing tools, tables, and several other advanced features. The Exchange note in Figure 4, for instance, shows the power of editing mail using Word. The red wavy marks under the word "followup" in the callout are produced by Word's background spell-checker, and indicate that the correct spelling is "follow-up."

Architecture and Implementation

For an application to become a DocObject server, it helps to componentize the application into frame and document objects, with the DocObject interfaces implemented on the latter object. You can retain almost all existing OLE services in the areas of object storage, standard embedding, in-place activation, menu negotiation, and automation. As Figure 5 illustrates, DocObject servers are required to implement two new interfaces: IOleDocument and IOleDocumentView. IOleDocument is essentially a holder for one or more IOleDocumentViews, each of which handles a particular view on the document (for instance, normal, page layout, and outline views in Word). Applications that support a single view can implement IOleDocument and IOleDocumentView on the same intrinsic object. There are a couple of optional server-side interfaces, namely IOleCommandTarget and IPrint. The container implements the standard OLE in-place site interfaces plus a DocObject interface called IOleDocumentSite. Listings One and Two illustrate these mandatory interfaces and their respective methods. Listing One is the DocObject server and Listing Two is the DocObject container.

How Does it Work?

An object determines whether to activate as DocObject depending on client site supportwhen the object's IOleObject::SetClientSite is called, it queries the container for IOleDocumentSite; see Listing Three. Next, when the object is asked to in-place activate through IOleObject::DoVerb, it determines whether it is a DocObject by checking the m_fDocObject flag. If it is a DocObject, it bypasses the normal OLE in-place activation sequence, calls IOleDocumentSite::ActivateMe (the only method in the IOleDocumentSite interface), and becomes active as a DocObject, rather than calling IOleClientSite::ShowObject or ShowWindow. This happens for the OLEIVERB_SHOW, OLEIVERB_OPEN, and OLEIVERB_UIACTIVATE verbs of DoVerb. The document can specify which view to activate by passing the view's IOleDocumentView pointer in the pviewToActivate argument of ActivateMe. Alternatively, the container can call the DocObject's IOleDocument::CreateView to obtain the view it wishes to activate. While the object is acting as a DocObject, it should return an error if DoVerb is called with OLEIVERB_HIDE.

Becoming a DocObject server also requires a few changes to in-place activation. Unlike embedded objects, DocObjects should not display a hatched border around them when they are active, and any scroll bars should be drawn within the view rectangle rather than outside. Also, there is no need to generate IOleInPlaceSite::OnPosRectChange calls, since the DocObject always extends to the entire client area of the container. DocObjects can ignore IOleObject::SetExtent calls for the same reason.

Command Dispatch via IOleCommandTarget

The DocObjects specification (available at http://www.microsoft.com/intdev/sdk/) includes an optional interface that functions as a generic mechanism for a server object and its container to dispatch commands to each other. Called IOleCommandTarget, this is a simple, extensible mechanism for a server and container to query and execute commands, as seen from the interface description in Listing Four.

IOleCommandTarget has two methodsa QueryStatus method to query whether a set of commands is supported, and an Exec method to execute a particular command. This interface is highly efficient in both in-process and out-ofprocess situations. A standard set of commands are already defined to enable greater interoperability between various applications, and the interface also enables applications to extend this by defining new command groups that are applicable to specific scenarios.

DocObject Print Interfaces

DocObject servers can support the optional IPrint interface for printing. Containers like the Office Binder call the IPrint::Print method to print one or more DocObjects contained in them, and can specify a broad range of printing parameters set by the user, as seen in the interface description in Listing Five. DocObject servers, in turn, must call the container's IContinueCallback::FContinuePrinting method (Listing Six) periodically when printing is in progress. Typically, they should call this method at least once per printed pagethis helps containers such as Binder put up UI for things like percentage progress on the print job, and allow containers to respond to the user clicking a Cancel button to terminate the print job.

Conclusion

Once deployed in an appropriate set of document-centric applications and browser software, DocObjects represent a zero-cost web-publishing solution that lets authors of disparate document types easily get their favorite document formats out on the Web. In terms of implementation, DocObjects are a relatively small set of OLE interfaces that require modest incremental effort over standard in-place embedding. Application development tools from multiple vendors, including upcoming versions of Visual Basic and Visual C++, will include tightly integrated support for DocObjects in the near future.

Figure 1: In-place active Paint bitmap embedded inside a page of a Word document.

Figure 2: Word as an ActiveX Document hosted inside Internet Explorer.

Figure 3: The Office Binder, a compound document containing five different sections, each of which is a DocObject.

Figure 4: WordMail in Office 95 makes use of Word as a DocObject to edit mail notes.

Figure 5: DocObject interface overview.

Listing One

interface IOleDocument : IUnknown {
  virtual HRESULT CreateView(pipsite,pstm,dwReserved,ppview)=0;
  virtual HRESULT GetDocMiscStatus(pdwStatus) = 0;
  virtual HRESULT EnumViews(ppenumview, ppview) = 0;
  }
interface IOleDocumentView : IUnknown {
  virtual HRESULT SetIn-placeSite(pipsite) = 0;
  virtual HRESULT GetIn-placeSite(ppipsite) = 0;
  virtual HRESULT GetDocument(ppunk) = 0;
  virtual HRESULT SetRect(lprcView) = 0;
  virtual HRESULT GetRect(lprcView) = 0;
  virtual HRESULT SetRectComplex(lprcView, lprcHScroll,
        lprcVScroll, lprcSizeBox) = 0;
  virtual HRESULT Show(fShow) = 0;
  virtual HRESULT UIActivate (fUIActivate) = 0;
  virtual HRESULT Open(void) = 0;
  virtual HRESULT Close(dwReserved) = 0;
  virtual HRESULT SaveViewState(pstm) = 0;
  virtual HRESULT ApplyViewState(pstm);
  virtual HRESULT Clone(pipsiteClone, ppviewClone) = 0;
  }

Listing Two

interface IOleDocumentSite :: public IUnknown {
  virtual HRESULT ActivateMe(pviewToActivate) = 0;
  }

Listing Three

IOleObject::SetClientSite(LPOLECLIENTSITE pclientsite)
{
//Perform regular SetClientSite processing.
if  (pclientsite) {
  // query for document site pointer
  if (pclientsite->QueryInterface(&IID_IOleDocumentSite,&m_pdocsite)==NOERROR)
    m_fDocObject = TRUE;
  }
}

Listing Four

interface IOleCommandTarget : IUnknown {
  virtual HRESULT QueryStatus (pguidCmdGroup, cCmds, rgCmds[], pcmdtext) = 0;
  virtual HRESULT Exec (pguidCmdGroup, nCmdID, nCmdexecopt,
        pvarargIn, pvarargOut) = 0;
  }

Listing Five

typedef enum {
  PRINTFLAG_MAYBOTHERUSER           = 1,
  PRINTFLAG_PROMPTUSER              = 2,
  PRINTFLAG_USERMAYCHANGEPRINTER    = 4,
  PRINTFLAG_RECOMPOSETODEVICE       = 8,
  PRINTFLAG_DONTACTUALLYPRINT       = 16,
  PRINTFLAG_PRINTTOFILE             = 64,   } PRINTFLAG;
typedef struct tagPAGERANGE {
  LONG  nFromPage;
  LONG  nToPage;
  } PAGERANGE;
typedef struct tagPAGESET {
  ULONG cbStruct;
  BOOL  fOddPages;
  BOOL fEvenPages;
  ULONG cPageRange;
  PAGERANGE rgPageRange[1];
  } PAGESET;
interface IPrint : IUnknown {
  HRESULT SetInitialPageNum(LONG nFirstPage);
  HRESULT GetPageInfo(LONG* nFirstPage, LONG* pcPages);
  HRESULT Print(DWORD grfFlags, DVTARGETDEVICE** pptd,
    PAGESET** ppPageSet, STGMEDIUM** ppstgmOptions,
    IContinueCallback* pCallback, LONG nFirstPage,
                                    LONG* pcPagesPrinted, LONG* pnPageLast);
  };


Listing Six

interface IContinueCallback : IUnknown {
  HRESULT FContinue(void);
  HRESULT FContinuePrinting(LONG cPagesPrinted,
    LONG nCurrentPage, LPOLESTR wszPrintStatus);
  };

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.