|  | Click Here!

Search the site:
EXPERT SEARCH

| Programming Languages
| Databases
| Security
| Web Services
| Network Services
| Middleware
| Components
| Operating Systems
| User Interfaces
| Groupware & Collaboration
| Content Management
| Productivity Applications
| Hardware
| Fun & Games

EarthWeb sites
Crossnodes
Datamation
Developer.com
DICE
EarthWeb.com
EarthWeb Direct
ERP Hub
Gamelan
GoCertify.com
HTMLGoodies
Intranet Journal
IT Knowledge
IT Library
JavaGoodies
JARS
JavaScripts.com
open source IT
RoadCoders
Y2K Info

- 11 — ActiveX DocObjects and Internet Explorer: Making Your Application Internet and Intranet Aware

- DocObject Technology
- ActiveX and Business
- Deeper Explanation of ActiveX DocObjects and Their History

- The Origin of DocObjects: The Concord Specification and Windows 95 Binder
- Edit Menu Merging Techniques of OLE 2.0 and DocObjects

- An ActiveX DocObject Example

- Major Features of Interfaces Used
- Main Interfaces Used
- Creating a DocObject Server with Visual C++ 4.1 AppWizard
- Implementing Your Example
- Setup and Usage Instructions

- Implementation Ideas: How to Use This Technology
- Conclusion

#
11 — ActiveX DocObjects and Internet Explorer: Making Your Application Internet and Intranet Aware

by Daniel F. Wygant

Imagine editing a Microsoft Word document by selecting a hyperlink displayed by Internet Explorer. After clicking on a hyperlink to a Microsoft Word document, the document is displayed in Internet Explorer's window. The Word menus and toolbars are displayed along with those from Internet Explorer, as shown in Figure 11.1.

Figure 11.1. Editing a Word document in Internet Explorer.

This is known as visual editing; Word becomes activated in Internet Explorer's window. The editing functions of both applications (Word and Internet Explorer) are coexisting on the Internet completely intact.

You can benefit greatly from this type of "online" document management and editing. It gives you a much greater maintenance capability, which doesn't exist for most file formats. The problem of distributing your documentation is also alleviated merely by putting the documents on the Web.

TIP
To try this on your own, you need Office95 and Internet Explorer 3.0; you can get the beta version of Internet Explorer 3.0 directly from Microsoft's Web site (http://www.microsoft.com/ie The Internet Explorer Home Page).

###
DocObject Technology

The new ActiveX DocObjects offer this new and powerful capability. They are intended for use in both Internet Explorer 3.0 and in the Office95 Binder for visually editing various file formats. The ActiveX DocObject technology uses a modified menu-sharing technique that more closely resembles the data's own standalone native editing application.

This chapter discusses how businesses can benefit from DocObject technology and gives a broader understanding of what the DocObject interfaces are. A sample DocObject OLE server, with source code, is presented to illustrate how this new ActiveX technology works. The chapter winds up by discussing ways ActiveX DocObject OLE servers could be used.

NOTE
The source code for all this chapter's examples can be found on this book's CD-ROM.

Using this technology allows you to manage your company's documentation through the Internet. This is illustrated in Figure 11.2, which shows many users accessing documents over the network.

Figure 11.2. Users accessing documents on a central HTTP server.

###
ActiveX and Business

Most businesses maintain a lot of documentation in a variety of formats. The cost of maintaining, updating, and distributing this information can be astronomical. The Binder delivered with Office95 gives you a way to organize your documents into a sort of three-ring binder, as the name implies. Like the Internet Explorer, the Binder allows you to visually edit documents that are associated with DocObject-enabled applications. The ActiveX DocObject technology, both for Office95's Binder and Internet Explorer, offers some solutions to these problems. In addition, it paves the way for better online publishing techniques that haven't been available in the past.

By using DocObjects, a business can develop better viewing and editing applications for its various data formats. They will be better because DocObjects work in the context of the binder they're embedded in. As an added bonus to your business, Internet Explorer understands how to use DocObjects. That is, all DocObject applications display in the context of their binder complete with their usual menus—in this case, Internet Explorer.

For example, your business could give users of their data and documents a DocObject server. Some users, such as the author or maintenance person, could be given either write access to the document or an editing-enabled DocObject application. Other users of the information might be allowed only view access to it or given a viewing-only DocObject application.

In either case, all your business information can be made more accessible through HTML pages with hyperlink references to the data files. When the hyperlinks are activated, the DocObject application for that data format will activate inside the browser. All the data format's application menus will be merged with Internet Explorer's menus.

NOTE
At present, only Internet Explorer has integrated ActiveX DocObject technology. However, Microsoft has agreed to provide an ActiveX plug-in for Netscape's browser in the near future. Other applications for DocObjects will undoubtedly soon follow.

The visual editing capabilities of ActiveX DocObject technology provides users with a consistent desktop, even while surfing the Internet. The familiar menus users are already comfortable with are displayed in the context of Internet Explorer's window, requiring less training time and encouraging higher productivity, something all businesses must be concerned with.

Another advantage of the DocObject's visual editing is that the documents can be stored in a central location. Your business could put all its documents on a central HTTP server, with massive data storage for speed, reliability, and centralized security. All users and maintenance personnel could then easily access the information stored there through their Internet Explorer browser. This is beneficial since the information can be easily found and either edited or viewed without moving or copying the actual files around. Figure 11.3 shows a sample configuration of an HTTP server.

Figure 11.3. HTTP server configuration for a business intranet.

###
Deeper Explanation of ActiveX DocObjects and Their History

In this section, I'll let you in on the big secret—DocObjects are not really new, just their use on the Internet is new. You'll see where the DocObject concept initially evolved from, then take a look at just what the DocObject does to make it special before getting into the sample code in the next section. The deeper explanation shows you before and after shots of DocObjects at work to illustrate how they work and what exactly the benefits are.

####
The Origin of DocObjects: The Concord Specification and Windows 95 Binder

Originally, the DocObject technology was mentioned in the Concord specification for the next generation of OLE after OLE 2.0. I would have said OLE 3.0, which was the unofficial name for Concord, but Microsoft decided to stop numbering the various versions of OLE to avoid confusion. It isn't uncommon for a technology leader like Microsoft to look into the next few generations of their software years in advance of its actual introduction. That is the case with the Concord specification, in which Microsoft actually mentions the Office95 specification. Microsoft's work on the Concord specification paved the way for the Office95 Binder interfaces, presenting some of the ideas used for DocObjects.

The Binder interfaces in Office95 were created to allow for the binder-container (Binder.EXE) delivered with Office95. This useful container allows you to organize various documents into the equivalent of a three-ring binder—thus, the term "binder." Each of the DocObjects in the binder are embedded into distinct (OLE) storages. As the objects are activated for visual editing in the Office95 Binder, their DocObject application is activated in the context of the Office95 Binder. The menu sharing, as discussed earlier, allows the DocObject to display its entire menu along with the Office95 Binder's menu. This menu merging was originally called in-place activation in OLE 2.0 terminology—Microsoft coined the phrase "visual editing" as a more descriptive term for in-place activation. Another reason for this choice in terminology is that the menu choice for in-place activation in an OLE 2.0 container is "Edit." You see the same kind of in-place activation, or visual editing, in Internet Explorer.

Once again, Microsoft used well-planned, well-designed, existing technology to pave the way for the future into other areas of computing. They borrowed the visual editing model from the Office95 Binder, which improved on the generic in-place activation model of OLE 2.0. Now your existing OLE applications can be retrofitted or redesigned to use the Binder-now-DocObject technology. Adding DocObject interfaces to your application instantly turns them into intranet/Internet applications—a significant but inexpensive added value. If you do, then Internet Explorer can use a hyperlinked document's application to perform visual editing.

TIP
Microsoft has hinted that Visual C++ 4.2 will support DocObject classes in Microsoft Foundation Classes, so they will probably either offer a DocObject Wizard or integrate the DocObject classes with their MFC AppWizard.

####
Edit Menu Merging Techniques of OLE 2.0 and DocObjects

Now look at a detailed example of using Office95 DocObjects. Note that you must have Office95 and Internet Explorer 3.0 (or better) installed. You start out with a click on a hyperlink in Internet Explorer, which references a Microsoft Word document (.doc). Microsoft Word is then activated in the context of the Internet Explorer for editing. Figure 11.4 shows Internet Explorer before and after Word is activated in-place to illustrate how the menus are merged.

Figure 11.4. Internet Explorer before and after Word menus are merged.

Internet Explorer then looks in the registry to see what application is associated with (.doc) Word documents—namely Microsoft Word (the Word.Document.6 registry key for Word 6.0). Since Microsoft Word has registry entries indicating it supports DocObjects (the DocObject registry key), Internet Explorer knows it can activate the document. The Internet Explorer then uses Word's "class id" (the CLSID registry key) to creates a Microsoft Word OLE server object to handle the document. After the initial Microsoft Word OLE server object creation, Internet Explorer tries to activate Word as an ActiveX Document by querying for Word's DocObject. Microsoft Word is then activated inside Internet Explorer's window with its usual complete set of commands and toolbars, just as though you were running Microsoft Word standalone. Figure 11.5 compares the menu and toolbars of Word running standalone and activated in Internet Explorer.

Figure 11.5. Comparing Word's menus and toolbars running standalone and in Internet Explorer.

That's the magic of Microsoft's new ActiveX DocObject technology—your application runs in the context of the container it's activated in. This is similar to OLE's Edit verb, which equates to, in OLE 2.0 terms, "in-place activation", or "visual editing" in DocObject terminology. Another OLE verb, Open, equates to running the native application standalone.

However, there is a difference between DocObject activation and OLE's in-place activation. With OLE's in-place activation, the menu is shared with the container the object is activated in. With DocObject activation, the menu is virtually taken over by the object. Some menu sharing still occurs, but the entire native application's menus are "embedded" in the container's menu. Also, the Help menu item is shared between the two applications, with both container and DocObject applications providing submenus.

With the MFC Scribble tutorial/example from Visual C++ 4.1, Microsoft has added the DocObject interfaces (look in \msdev\samples\mfc\ole\bindscrb where \msdev is the directory where you downloaded VC++). In fact, the sample code discussed in the next section uses the code from the Scribble example as a basis for its DocObject interfaces. The Scribble application is a simple drawing tool. It lets you draw lines of various thickness and save the lines to a file as a list of strokes (the CStroke class). The saved file (.osc) may be read to initialize Scribble as a standalone application, an OLE server, or a DocObject server. The file can be used by the standalone Scribble application, it can be inserted into an OLE container, or it can be activated in the Internet Explorer from a hyperlink. The OLE container can be an OLE 2.0 container or a Binder container, such as Office95 Binder. Scribble can run by itself in its own window, as a linked or embedded OLE Object in any OLE container (Microsoft Word for example), as a DocObject in any Office95 Binder–compliant application, or as a DocObject in Internet Explorer 3.0. The following lists the running scenarios for Scribble; Figures 11.6 through 11.9 illustrate all four cases:

- If you double-click on a file with a .osc extension, the standalone Scribble application runs.

Figure 11.6. Scribble running standalone.

- If you drag a .osc file into a Word document, it displays a picture of the Scribble strokes in the Word document (although I don't guarantee this part), making the Scribble file an embedded OLE object in the document. Alternatively, you can insert a new Scribble document or insert an existing .osc file, either embedded or linked.

Figure 11.7. Scribble running in Word.

- Using the Office95 Binder, you can embed a new or existing Scribble object into a binder file with the Binder's Section | Add or Section | Add from File commands, respectively. Alternatively, you can drag and drop an existing .osc file into the Binder. Currently, these will always be embedded files.

Figure 11.8. Scribble running in Binder.

- Finally, since Internet Explorer provides DocObject support, if you click on a hyperlink to a Scribble (.osc) file, the Scribble application runs in the context of Internet Explorer's window. This is neither embedding or linking, but when visually edited in Internet Explorer, the ActiveX Document is used as though it were a linked file.

Figure 11.9. Scribble running in Internet Explorer.

A typical application can easily be written to run in these four different ways. The real power here comes from using the MFC framework from Visual C++ 4.1; it makes building your own DocObject application very easy. Other methods are time-consuming, at best. The next section explains in more detail how to use the MFC framework to build an ActiveX Document server application.

###
An ActiveX DocObject Example

In this example, you write a simple DocObject application; it's a multidocument (MDI) application called TextView that displays text windows (the CTextView class) for keying in and editing text. The file can be saved with the .tvi extension and read later to initialize the TextView application. In this example, you will focus only on the DocObject parts, although it can be used equally well as a standalone application, as an OLE server, or in the Office95 Binder.

The major features of the interfaces used are discussed first as a brief overview of how the TextView application was created and written. Next, the main interfaces are presented, introducing you to the DocObject interfaces. Following this is a presentation on the sequence of events that occur during initialization, activation and deactivation, and, finally, saving and termination. Next is the implementation details of crucial interface methods pertinent to writing a DocObject application. After all this, you can finally deal with the setup and usage instructions, followed by a few notes on testing and debugging your DocObject application.

####
Major Features of Interfaces Used

There are two main interfaces in the TextView application. For a particular DocObject, or document instance, there is one IOleDocument object, hence the name Document Object, or DocObject for short. I relate the IOleDocument object to a document, so I will usually refer to it as just "the document" from here on.

Each document has one or more IOleDocumentView interfaces. Each one of these objects represents one view; each of these views is merely a different representation of the data in the document. Perhaps the document can be viewed with different levels of detail, like zooming in on a drawing or looking at your town from the street and then from the rooftop. At any rate, the different views are your DocObject's different views of its data or document. Figure 11.10 illustrates the ActiveX Document/View architecture.

Figure 11.10. ActiveX Document/View architecture.

A good example of multiple views might be an Excel spreadsheet. One set of views of the Excel spreadsheet could be of the database with various options set, such as gridlines off and a background displayed. This would essentially just be a set of rows and columns with numbers, words, and other data in each slot. Another view may be a diagram view, or a picture of the data in the spreadsheet. For instance, the author can create a pie chart from the data in the Excel spreadsheet.

On the client side—the container—there is an interface called IOleDocumentSite. It's just what it sounds like: the server's "view site" within the container. This interface represents where the server's ActiveX Document will "live" in the client's application, or where the DocObject will be placed. The IOleDocumentSite isn't really used in that manner, but rather tells your DocObject application that it's supposed to act like a DocObject and not like the typical OLE 2.0 server object. This makes a difference when the container asks your ActiveX Document to activate; you can tell the container to activate with a particular—favorite or default—view.

Most applications in the examples and tutorials from both the VC+ 4.1 samples and the ActiveX SDK samples provide only one view. If your DocObject server is an MDI application, then the implementation of the one view is fairly straightforward.. However, if you do or can have multiple views (as in the preceding Excel example), there is an IEnumOleDocumentViews interface that you can support. The client may initially ask your document for a status flag that indicates, among other things, whether your DocObject supports multiple views. The client may also ask your document to return this document view enumeration, which is essentially a standardized list interface (or enumeration) of the views you support. If your DocObject has only one view, then it returns that view and NULL for the enumeration. In the sample code for this chapter, there is only one view, so this interface isn't supported.

There are a few other important ActiveX Document interfaces. Though not required, they are important parts of the ActiveX DocObject specification. The following is a brief description of each interface:

- The IPrint interface is used for printing through the client. In the Office95 Binder, in particular, it's used to create the binder in hardcopy form, which would have a real-life binder layout.
- The IContinueCallback interface, used with the IPrint interface, is designed to facilitate a generalized callback interface for a continue/interrupt paradigm yet to be implemented anywhere but in the IPrint interface.
- The last interface is the IOleCommandTarget. This interface must be used to perform a command handshake between client and server. In the specification, it's referred to as the "command dispatch interface" used for executing and querying commands.

####
Main Interfaces Used

Now draw yourself a BIG cup of coffee (with Scribble) and read on about the main interfaces used for this example:

- IOleDocument This represents the file, or rather the "document." For both the Binder and Internet Explorer, all QueryInterface() calls go through this interface. It represents the DocObject and is one-to-one with the file. It has the following interface methods:
  CreateView() Returns a view object (IOleDocumentView), possibly pre-initializing it with a saved view state stored in a stream (IStream) passed in. Also the "view site" (IOleInPlaceSite) may be passed in.
  Parameters
  (input) IOleInPlaceSite *pIPSite
  (input) IStream *pstm
  (input) DWORD dwReserved
  (output) IOleDocumentView **ppView
  GetDocMiscStatus() Returns a status flag, duplicated in the objects registry under the "DocObject" key. The client is responsible for using this status to determine how to communicate with the DocObject. The values are listed in Table 11.1.
  Parameters
  (output) DWORD *pdwStatus
Table 11.1. The values that may be assigned to the status word returned.

    DOCMISC enumerations
    =
    Meaning Interfaces
DOCMISC_CANCREATEMULTIPLEVIEWS | 1 | supports multiple IEnumOleDocumentViews views interface supported
DOCMISC_SUPPORTCOMPLEXRECTANGLES | 2 | can use complex IOleDocumentView's rectangles for SetRectComplex interface scrollbar method not construction implemented
DOCMISC_CANTOPENEDIT | 4 | cannot "open" IOleDocumentView's Open standalone view interface method not application implemented
DOCMISC_NOFILESUPPORT | 8 | cannot read/ write IPersistFile interface file not implemented, only IPersistStorage interface implemented

EnumViews() Returns either an enumeration of view objects (IEnumOleDocumentViews) if your DocObject supports multiple views, or a single-view object (IOleDocumentView) if not.
Parameters
(output) IEnumOleDocumentViews **ppEnum
(output) IOleDocumentView **ppView
IOleDocumentView Represents a single view of your document. If your DocObject supports multiple views, there is a many-to-one relationship of views to document; otherwise, it's a one-to-one relationship. According to the specification in the ActiveX SDK, "this interface provides all the necessary operations for a container to manipulate, manage, and activate a view."
SetInPlaceSite() Saves the view site's (IOleInPlaceSite) interface pointer in the container.
Parameter
(input) IOleInPlaceSite *pIPSite
GetInPlaceSite() Returns the view site's (IOleInPlaceSite) interface pointer in the container.
Parameter
(output) IOleInPlaceSite **ppIPSite
GetDocument() Returns an (IUnknown) interface pointer to the DocObject.
Parameter
(output) IUnknown **ppunk
SetRect() Sets the view's rectangle for display inside the container or client.
Parameter
(input) LPRECT prcView
GetRect() Returns the view's rectangle for display inside the container or client. An error (E_UNEXPECTED) is returned if no view rectangle has been set yet.
Parameter
(output) LPRECT prcView
SetRectComplex() Same as SetRect() with additional rectangles for vertical and horizontal scrollbars.
Parameters
(input) LPRECT prcView
(input) LPRECT prcHScroll
(input) LPRECT prcVScroll
(input) LPRECT prcSizeBox
Show() Either "Show" or "Hide." This is the same idea as OLE's "Show" and "Hide" verbs. To "Show" means to in-place activate the view without a user-interface (UI) activation and to show, or display, the view window. To "Hide" means to deactivate the user interface and hide the view.
Parameter
(input) BOOL fShow
UIActivate() Activate or deactivate the user interface. Activating involves the menu merging/sharing, setting up the toolbar and accelerators, and so forth.
Parameter
(input) BOOL fUIActivate
Open() Same as OLE's "Open" verb. Invokes the native application as a separate process or in a pop-up window.
Parameter
void; no parameters
CloseView() Close down the view by hiding the view and user interface by calling Show(FALSE) and release the view site's (IOleInPlaceSite) interface pointer in the container by calling SetInPlaceSite(NULL).
Parameter
(input) DWORD dwReserved
SaveViewState() Save view-specific data to a stream for use in reinitializing the view at a later time by ApplyViewState(). According to the DocObject specification, this interface "instructs the view to save its state into the given stream, where the state includes properties like the view type, zoom factor, insertion point, and so on."
Parameter
(input) IStream *pstm
ApplyViewState() Reinitialize the view from data in a stream previously saved by SaveViewState(). According to the DocObject specification, this interface "instructs a view to reinitialize itself according to the data in a stream that was previously written through IOleDocumentView::SaveViewState."
Parameter
(input) IStream *pstm
Clone() Create and return another view object exactly like itself.
Parameters
(input) IOleInPlaceSite *pIPSiteNew
(output) IOleDocumentView **ppViewNew

IOleObject This is the main interface used by containers to communicate to all OLE objects. The only interface methods of interest to this discussion are SetClientSite() and DoVerb().
SetClientSite() This interface method is called by the container to set up the "view site" interface pointer. If the "view site" passed in has the IOleDocumentSite interface, then the server is supposed to act like a DocObject as opposed to an ordinary OLE server.
DoVerb() For an ActiveX Document server, this interface method is called by the container to allow your document to specify which view to use. This view would typically be the default or favorite view.

- IPersistFile This interface is a standard OLE server interface. The Load() interface method is called by the client with the filename to use for initialization.
- IPersistStorage This interface, also a standard OLE interface, is used for OLE embedding (as opposed to linking). The container calls the Save() interface method with a pointer to a structured storage (IStorage) to let the OLE server save—or embed—its data in the container's document. Likewise, the Load() interface method is later called to let the OLE server initialize itself from the embedded data.

####
Creating a DocObject Server with Visual C++ 4.1 AppWizard

Let me begin by saying, "Thanks, Microsoft." Once again, they've made life a bit easier—relatively speaking, of course. There is an example of the Scribble tutorial in the VC++ 4.1 sample code with the DocObject interfaces. The source for the Scribble-DocObject sample code is in \msdev\samples\mfc\ole\bindscrb, where \msdev\ is the directory where you download VC++. Alternatively, in the VC++ PRoject Workspace window on the InfoView tab, go to Samples\MFC Samples\MFC OLE Samples\BINDSCRB: Illustrates an MFC Document Binder.

What is exceptional is that this sample code is built by using the AppWizard and has just added an extra parent class for DocObject interfaces. This extra level of parent classes in turn has the respective standard MFC classes you normally get from AppWizard as parent classes. In other words, they just slipped in an extra level of parent classes to enable the DocObject interfaces. Therefore, if you create an AppWizard project, all you have to do is change your classes to use these new parent classes supplied with the Scribble-DocObject sample code, instead of the standard MFC classes.

That is, the Scribble-DocObject extensions are subclasses from the classes used to create a project with the VC++ 4.1 AppWizard. When I looked at the new DocObject classes, it instantly occurred to me that they will probably be added to MFC in VC++ 4.2. The classes are meant to accommodate the DocObject/Binder interfaces that Internet Explorer 3.0 and Office95 introduce. In addition, they also seamlessly integrate with the class structure created through the AppWizard.

Whether I'm right or wrong about these classes, all I can say is that using these subclasses made writing a DocObject application a snap! Until VC++ 4.2 makes its long-awaited appearance, however, you're better off using this sample code as a basis. All I had to do was change the parent class that AppWizard sets up for you (of COleServerDoc, COleServerItem, and COleIPFrameWnd) and make global replacements for the parent class name in most places. The new parent classes are CDocObjectServerDoc, CDocObjectServerItem, and CDocObjectIPFrameWnd. The details are explained in the following numbered steps—the actual AppWizard process. Figure 11.8 shows where in the class structure these classes fit, illustrating what Microsoft has done in the Scribble-DocObject sample code.

Figure 11.11. Scribble-DocObject MFC extensions.

To start with, bring up Visual C++, choose File | New (or Ctrl+N), and select the Project Workspace option from the New dialog box. This will bring up the New Project Workspace dialog box. Select MFC AppWizard (exe), enter the name TextView, and click the Create button to start the MFC AppWizard. The following list explains what to do for each of the six "step" dialog boxes:

1. Check either the "Multiple documents" (default) or "Single document" checkbox, depending on which you prefer, then click the Next button.
2. Click the Next button again on this database support step, taking the default of "none".
3. Check the "Full Server" option. Make sure the "Yes, please" checkbox is selected under the "Would you like support for OLE compound files?" option, then click the Next button.
4. Check the "Context-sensitive Help" option under "What features would you like to include?" so that all options in this list are selected. Click the "Advanced. . ." button to bring up the Advanced Options dialog box. On the Document Template Strings option tab in the "File extension" field, enter tvi—note that as you type, you see the letters being added to the "Filter name." You can edit the other fields as follows, but it isn't essential:
   Doc type name = TxView
   File new name (OLE short name) = TxVw
   Main frame caption = Text Viewer
   Filter name = Text View Files (*.tvi)
   File type name (OLE long name) = TextView Document
   Now click the Close button to close the Advanced Options dialog box, then click the Next button.
5. Click the Next button to go to the next step, taking the defaults for source file comments and using the shared MFC library.
6. Select the CTextViewView class, change the "Base class" to CEditView, and change the "Header file" and "Implementation file" to TxVwView.h and TxVwView.cpp, respectively, so they both have eight-character filenames. Next, select the CTextViewDoc class and change the "Header file" and "Implementation file" to TxtVwDoc.h and TxtVwDoc.cpp, respectively. Now click the Finish button to bring up the New Project Information dialog box, then click the OK button to complete the Wizardry.

####
Implementing Your Example

The AppWizard has done quite a bit of the work for you, and the classes you borrow from the Scribble-DocObject sample code essentially do the rest. To use this code, copy the following files into your project directory:

Binddcmt.cpp

Binddoc.cpp

Binddoc.h

Bindipfw.cpp

Bindipfw.h

Binditem.cpp

Binditem.h

Bindview.cpp

Mfcbind.cpp

Mfcbind.h

Oleobjct.cpp

Print. cpp

TIP
An alternative to just copying files from the Scribble-DocObject sample code into each project is creating a dynamic-link library or a static library (using the New Project Workspace dialog box) from this code and using the library in multiple projects.

To include these files in your project, choose Insert | Files into Project. . . from the menu to bring up the Insert Files into Project dialog box. Select the following files (note only the .cpp files):

Binddcmt.cpp

Binddoc.cpp

Bindipfw.cpp

Binditem.cpp

Bindview.cpp

Mfcbind.cpp

Oleobjct.cpp

Print.cpp

To change the class hierarchy so you can use these DocObject MFC classes, edit and change the parent classes as indicated in the following files:

- TxtVwDoc.h: Change parent from COleServerDoc to CDocObjectServerDoc
  class CTextViewDoc : public CDocObjectServerDoc
- SrvrItem.h: Change parent from COleServerItem to CDocObjectServerItem
  class CTextViewSrvrItem : public CDocObjectServerItem
- IpFrame.h: Change parent from COleIPFrameWnd to CDocObjectIPFrameWnd
  class CInPlaceFrame : public CDocObjectIPFrameWnd

Now your classes are using the new parent classes which enable the DocObject interfaces. The next step is to use the Find in Files toolbar button and Edit | Replace commands: Replace COleServerDoc with CDocObjectServerDoc, COleServerItem with CDocObjectServerItem, and COleIPFrameWnd with CDocObjectIPFrameWnd in all the source and header files. Use the Find In Files dialog box with each of the original class names to help find all instances that must be changed. The only exception is the OnGetEmbeddedItem() method, which requires that you return a COleServerItem.

Now add the required #include files, as follows:

- TxtVwDoc.cpp and SrvrItem.cpp:
  #include "binddoc.h"
  #include "binditem.h"
- IpFrame.cpp:
  #include "bindipfw.h"
- TextView.cpp:
  #include "mfcbind.h"
  #include "binddoc.h"
  #include "bindipfw.h"
- TxVwView.cpp:
  #include "binddoc.h"

To perform the extra required DocObject registration, edit the CTextViewApp::InitInstance() method in the TextView.cpp file and change the line

    m_server.UpdateRegistry(OAT_INPLACE_SERVER);

to

    MfcBinderUpdateRegistry(pDocTemplate, OAT_INPLACE_SERVER);

Modify the CTextViewSrvrItem::OnGetExtent()method in the SrvrItem.cpp file to return the correct extents by changing the line

    rSize = CSize(3000, 3000);   // 3000 x 3000 HIMETRIC units

to

    rSize = pDoc->GetDocSize();

    CClientDC dc(NULL);

        // set a MM_LOENGLISH based on logical inches

    //  (we can't use MM_LOENGLISH because MM_LOENGLISH uses physical inches)

    dc.SetMapMode(MM_ANISOTROPIC);

    dc.SetViewportExt(dc.GetDeviceCaps(LOGPIXELSX), dc.GetDeviceCaps(LOGPIXELSY));

    dc.SetWindowExt(100, -100);

    dc.LPtoHIMETRIC(&rSize);

Now add a few things to the document class (CTextViewDoc) to initialize and provide the correct size. Add the following to the TxtVwDoc.h file:

    protected:

    CSize m_sizeDoc;

    public:

        CSize GetDocSize() { return m_sizeDoc; }

    protected:

        void InitDocument();

The InitDocument() method has only one line, used to initialize the document size:

    m_sizeDoc = CSize(200,200);

The OnOpenDocument() method should be added to the document class (CTextViewDoc) through the built-in Class Wizard; you also add a call to the InitDocument() method to set the size. Open the TxtVwDoc.cpp file, and you'll notice that it has a built-in Class Wizard on the window's title bar. Select the OnOpenDocument method from the Messages pull-down menu, and a Microsoft Developer Studio dialog box prompts you to add this method: OnOpenDocument is not handled. Do you want to add a handler? Click the Yes button, and the method is "magically" added (that's why it's called a Class Wizard!). Your cursor is placed at the following line:

    // TODO: Add your specialized creation code here

Change this to a call to the following:

    InitDocument();

Then add a call to the InitDocument() method in the document's constructor (CTextViewDoc::CTextViewDoc()) and in the document's OnNewDocument() method.

A string must be added to the Resource file's String Table for the MfcBinderUpdateRegistry() function. Select ResourceView from the Project Workspace window, and add the BIND_IDP_FAILED_TO_AUTO_REGISTER ID with the associated string: Unable to add Binder-Compatible entries to registry.

Before you try to compile and link the code, you must add the uuid3.lib library to the "Object/library modules" field in the Link option tab on the Project Settings dialog box to get the DocObject GUIDs. Choose Build | Settings from the menu to bring up the Project Settings dialog box, then select the Link tab. After adding the uuid3.lib, click in the "Project Options" field and enter the /nodefaultlib:"LIBC" option to avoid a link error.

Now you can compile and link your project.

####
Setup and Usage Instructions

The project is now ready to run. The TextView.exe executable must run standalone one time to perform the necessary registration. Once it has registered itself, the TextView application can be used to view its .tvi files in the context of Internet Explorer as a DocObject server.

First, run TextView standalone, and create and save a .tvi file with some text in it. Next, create an HTML file with a hyperlink reference to the .tvi file. The HTML file contains the following line, which references your new DocObj.tvi file:

    <A HREF="DocObj.tvi">Text View DocObject test</a>

When you select this hyperlink in Internet Explorer, the TextView DocObject is invoked to display in-place activation in the context of Internet Explorer. Figure 11.9 shows TextView running both standalone and serving as a DocObject in Internet Explorer.

Figure 11.12. The TextView application running standalone and as a DocObject server in Internet Explorer.

NOTE
The TextView application can also be used as an OLE server in the Office95 Binder.

###
Implementation Ideas: How to Use This Technology

Your initial example was of an Office95 Word document displaying in the context of Internet Explorer. If you have your own data format viewer or editor, providing DocObject support can make your application much more usable. Using the techniques outlined in this chapter will make building a DocObject application based on Visual C++ 4.1 MFC very easy. Take a look at another possible implementation to get you thinking the DocObject way.

One area that I see as a good candidate, outside of Office95, is the CAD/CAM market. The various CAD/CAM formats, such as AutoCAD, MicroStation, Imagineer, and Solid Edge, to name but a few, could really benefit by providing viewer/editor DocObject applications. This would enable their viewing through Internet Explorer. Could this lead to groupware applications? Imagine providing the capability to people at remote places to view or edit data for a group design. It's evident that this market stands a lot to gain from the evolving and expanding DocObject approach.

###
Conclusion

Making your application Internet and intranet aware is as easy as using the DocObject interfaces and Visual C++ 4.1 MFC classes. This can be a boon to your business by making your formats more accessible. The Office95 Binder and Internet Explorer are just the first two areas that have applied the DocObject interfaces; more DocObject container and server applications should follow in the near future. These new applications stand to revolutionize how diverse groups of people can easily access the same data in a standardized, efficient manner. If your business starts considering how to make use of these new interfaces now, it will undoubtedly stand to benefit considerably in the near (and far) future.

The next two chapters deal with ISAPI extensions. Chapter 12, "Controlling the Internet Information Server Through ActiveX ISAPI Filters," discusses how your business can use ISAPI filters to help manage their Internet site. Chapter 13, "Developing Web Applications Using ISAPI Extensions," discusses the efficiency advantages of using ISAPI extensions to service CGI requests.

| Use of this site is subject certain Terms & Conditions. Copyright (c) 1996-1999 EarthWeb, Inc.. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Please read our privacy policy for details.