Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




ActiveX Containers

visual c en


ActiveX Containers

ActiveX containers are the environment through which the end user controls and manipulates the appearance of data. Containers, through their menus, provide a means for the user to view data differently, change data formats, insert new data, and so on. Containers also allow the user to change the viewable size of the data by manipulating the frame and adding toolbars and other 'decorations' to the window frame.



This control and manipulation of the data does not usually take place unilaterally on the part of the container. Typically, it requires an interaction between the container and the data. The architecture for this interaction was developed by Microsoft; it is called the ActiveX Container Specification when referring to the container, and the ActiveX Document Specification when referring to the data.

This chapter specifically explores the ActiveX container side of the interaction, although it will be impossible to ignore the ActiveX document side. This chapter examines what has changed between OLE containers and ActiveX containers, what COM interfaces have to be supported, and how to use MFC classes to easily create ActiveX containers. More details about the ActiveX Document Specification can be found in Chapter 12, 'ActiveX Documents.'

Just What Is an ActiveX Container?

What an exciting industry to work in! Just when you think you have it all figured out, it seems as though everything changes. It wasn't that long ago when Microsoft was all jazzed about compound documents—the ability for the user to combine graphics, text, and data in one document. Now, with ActiveX, it appears as though this has all gone away and everything is suddenly the Internet! Not to worry. Everything you know about OLE technology still applies; it has just been extended to cover new opportunities. As this chapter unfolds, you will see how existing OLE container support has been enhanced with new COM interfaces and how MFC classes have been extended to support them. If you're new to COM, OLE, and ActiveX, you're in the right place. You'll find all the information you need to understand how ActiveX containers work.

So what is an ActiveX container? The short answer is that an ActiveX container is an OLE container with some new COM interfaces—in particular, IOleCommandTarget, IOleDocumentSite, and IContinueCallback. These new interfaces have been added to support corresponding new interfaces in ActiveX documents. These interfaces first appeared in the Microsoft Office Binder application. Binder, as well as Internet Explorer, is an ActiveX container. ActiveX documents differ from OLE embedded documents in that they occupy the entire client area of the container and control much more of the menu. To the user, the ActiveX container appears to be the native application frame window. If you create a new Binder document and insert a Word document, an Excel spreadsheet, or a PowerPoint presentation, you'll notice that as you click each component of the binder, the user interface changes, and the menus and toolbars appear as they would in the native application. This capability of the container to take on the appearance of any native application is what ActiveX containers are all about. They allow the Binder application to bind together several applications into one binder, which allows Internet Explorer to download and display any ActiveX document data from a Web server.

Let's explore these new interfaces further. The IOleCommandTarget COM interface allows menu commands or other actions to be routed from the ActiveX document to the ActiveX container. A corresponding IOleCommandTarget interface is defined for the ActiveX document. This corresponding interface allows the container to route menu commands and other actions to the document, allowing a bidirectional communication of commands to flow cooperatively between container and document. The effect to the user is that the container and document behave as a unified application. The user is unable to tell which piece of software supplies support for which menu item. Supporting the IOleCommandTarget interface is optional.

NOTE

With all the various COM interfaces, it is easy to get confused about what each interface is for. Remember that a COM server supplies an interface for someone else to use. It is a means of manipulating the COM server. For example, the container exposes the IOleCommandTarget interface so that other software can route menu commands and the like to the container.

The IOleDocumentSite COM interface provides one method: ActivateMe, which allows the document to ask the container to activate it as a full ActiveX document instead of an OLE in-place, embedded object.

The IContinueCallback COM interface is used to provide printing support. It is used in conjunction with the IPrint COM interface that the ActiveX document exposes. This interface is used by the document to provide progress information to the container and to allow the container the opportunity to cancel the printing operation.

What's New in MFC?

There is no support in MFC for these new COM interfaces. However, it is relatively straightforward to add support for these interfaces using the MFC COM interface macros. We will look at how to do this when we generate and examine the XContainer program.

Some Details About ActiveX Containers

ActiveX containers have a rich history. Their roots go back to the first release of OLE, when OLE meant object linking and embedding. The original intent of OLE 1 was to allow the user to view different types of data in a single interface. Before, OLE 1 applications were strictly monolithic. If you wanted to write a document, you would use a word processor. If you wanted to edit financial data, you would use a spreadsheet. OLE 1 changed that and allowed the user to view documents, spreadsheets, and charts side by side in a single application. Admittedly, this was a little awkward because to edit a piece of data, you had to double-click the data and bring up a separate application to change it. But it was an improvement.

OLE 2 came along and added, in particular, the concept of in-place activation. This meant that the user could double-click a piece of data and, instead of launching a completely separate document, could edit the data inside of the hosting application. This was a great step forward, but still a little awkward. First, you had to double-click the data to activate it. This was counter-intuitive; users were familiar with single-clicking something when they wanted to focus on it. Yet, despite this awkwardness, it was better than OLE 1.

ActiveX documents add yet another layer to OLE 2. Instead of appearing inside another document, ActiveX documents occupy the entire client area of the container. It appears as though the container is the native application. This concept is very useful, particularly when you think of the Internet. A container application that can adapt itself to any document it receives is a powerful tool. This is exactly what browsing the Web is all about: exploring lots of different things and downloading lots of different documents into your browser. Internet Explorer is an example of an ActiveX container that does just that.

Figure 13.1 illustrates the OLE architecture. Notice how the upper layers in the architecture depend, to some degree, on the lower layers. This diagram is like a historical summary of how OLE has changed. Each time the OLE specification changes, another building block is added to the existing foundation.

Now, let's break out the various parts of the OLE architecture and examine them.

Structured Storage

Structured storage is a very interesting concept. It came about as a result of the implementation of compound documents. Not only should the user be able to view and edit dissimilar data within the same application, but he should also be able to save all the changes to the same file. This requirement drove the need for structured storage.

Structured storage is similar to a file system. Data is stored in storage objects that in turn can be stored in other storage objects. Storage streams that contain the real data can be stored in storage objects. This is analogous to files that reside in directories that reside in other directories.

This capability to segregate portions of one file into hierarchical partitions is very useful for documents that contain other embedded objects. Each object can be assigned its own storage area inside the file, and the embedded object can put anything it wants in its own storage area. Figure 13.2 illustrates the hierarchical nature of structured storage.

FIGURE 13.1. OLE architecture

FIGURE 13.2. Hierarchical structured storage

Monikers

Monikers provide a means of referencing other objects without storing the object itself. They are intelligent OLE objects that are the backbone of OLE linking. When a user links an object into a compound document, the OLE object is referenced by a moniker. By activating a moniker, it is possible to retrieve the original OLE object and activate it within the compound document.

Uniform Data Transfer

Uniform Data Transfer provides a means of obtaining data from another object without being restricted to a particular transfer medium. The standard Windows Clipboard allows the transfer of data between applications using several different formats, but each of these formats has to be transmitted through the Clipboard memory. Although appropriate for some kinds of data, it becomes impractical for large data sets.

Uniform Data Transfer allows several different formats to be transferred between applications using several different mediums. The medium could be memory, as with the Clipboard. It could also be a disk or the OLE IStorage and IStream interfaces.

Embedded Objects

Embedded objects are OLE objects that allow themselves to be embedded inside a container. Embedded objects store their data in the structured storage of the container. Microsoft Word is an example of an embedded object as well as an ActiveX document.

Linked Objects

Linked objects are OLE objects that allow themselves to be linked inside a container. Unlike an embedded object, a linked object is not stored in the structured storage of the container. Instead, a linked object contains a reference to the location of the real object. Typically, the linked object provides an iconic representation of itself inside the container. When this icon is double-clicked, it brings up the native application for editing.

Drag-and-Drop

OLE drag-and-drop provides a way by which different applications can move data between themselves. Without OLE drag-and-drop, each application would have to define its own protocol from transferring data between itself and another application. OLE drag-and-drop, in combination with Uniform Data Transfer, provides a more system-wide protocol for exchanging data using the mouse.

In-Place Activation

In-place activation is a key feature of OLE 2. It allows documents to be edited inside the container's client area without launching the native application. This feature is also called visual editing. Typically, an object that is in-place activated has some kind of hashed border around it. This indicates to the user that the highlighted object is currently being worked on. Figure 13.3 shows Microsoft Word as an in-place, activated object.

FIGURE 13.3. Microsoft Word as an in-place, activated object inside Excel

ActiveX Documents

ActiveX documents are in many ways just like in-place, activated documents. The exception is that when an ActiveX document is placed in an ActiveX container, it takes up the entire client area of the container. Gone are the hash marks that identify an in-place, activated object. The ActiveX document does not have to be double-clicked to be activated. It comes up active and appears to be a native application. Figure 13.4 shows Microsoft Word as an ActiveX document. Notice how the ActiveX container appears very similar to the native Microsoft Word application.

FIGURE 13.4. Microsoft Word as an ActiveX document inside Microsoft Binder, an ActiveX container

The COM Interfaces

COM interfaces are involved in the interactions between an ActiveX container and an ActiveX document.

Nine COM interfaces are part of the ActiveX container specification. Six of these interfaces were part of the OLE container specification, and the other three are new to ActiveX containers. Two of the new interfaces—IOleCommandTarget and IContinueCallback—are optional. Table 13.1 lists the COM interfaces with the corresponding MFC classes that implement the interface.

Table 13.1. COM interfaces used by containers

COM interface

Type

MFC class

IOleInPlaceFrame

OLE 2

COleControlContainer

IOleCommandTarget

New, optional

None

IOleInPlaceUIWindow

OLE 2

COleControlContainer

IOleContainer

OLE 2

COleControlContainer

IOleClientSite

OLE 2

COleClientItem

IAdviseSink

OLE 2

COleClientItem

IOleDocumentSite

New, required

None

COM interface

Type

MFC class

IOleInPlaceSite

OLE 2

COleClientItem

IContinueCallback

New, optional

None

These interfaces will now be discussed in more detail.

IOleInPlaceFrame

IOleInPlaceFrame is a COM interface derived from three other COM interfaces: IOleInPlaceUIWindow, IOleWindow, and IUnknown. It controls the top-level frame window of the container. With this interface, it is possible to add and remove items from the composite menu, set status text, manage modeless dialog boxes, and translate accelerator keys. Each of the interfaces that IOleInPlaceFrame derives from contributes required methods. Table 13.2 describes the interfaces.

Table 13.2. IOleInPlaceFrame interfaces

Interface name

Description

IUnknown methods

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IOleWindow methods

GetWindow

Gets the window handle to the frame, the document, the parent, or the in-place object

ContextSensitiveHelp

Gives the container the opportunity to handle context-sensitive help

IOleInPlaceUIWindow methods

GetBorder

Returns the rectangle where ActiveX documents can put their toolbars and other controls

RequestBorderSpace

Used to ask the container for space for toolbars and other controls

SetBorderSpace

Tells the container to allocate the space for toolbars and other controls

SetActiveObject

Called by the ActiveX document to create a link between itself and the ActiveX container

IOleInPlaceFrame methods

InsertMenus

Allows the container to insert its menu items into the shared menu

SetMenu

Allows the ActiveX document to install the merged container/document menu

RemoveMenus

Allows the container to remove its menu items

SetStatusText

Displays status text in the static area

EnableModeless

Enables or disables modeless dialogs at the frame level

TranslateAccelerator

Translates accelerator keystrokes intended for the container

IOleCommandTarget

IOleCommandTarget allows client and server to dispatch commands to each other. With the ActiveX container, it allows the ActiveX document to route commands that it generates to the container. Table 13.3 describes the interfaces.

Table 13.3. IOleCommandTarget interfaces

Interface name

Description

IUnknown methods

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IOleCommandTarget methods

QueryStatus

Asks the object whether it supports a particular type of command

Exec

Executes the requested command

IOleInPlaceUIWindow

IOleInPlaceUIWindow allows ActiveX documents to negotiate border space in the frame window. The interface manages the allocation of border space and the interaction between the document and the frame. IOleInPlaceUIWindow derives from IOleWindow. Table 13.4 describes the interfaces.

Table 13.4. IOleInPlaceUIWindow interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IOleWindow interfaces

GetWindow

Gets the window handle to the frame, the document, the parent, or the in-place object

ContextSensitiveHelp

Gives the container the opportunity to handle context-sensitive help

IOleInPlaceUIWindow methods

GetBorder

Returns the rectangle where ActiveX documents can put their toolbars and other controls

RequestBorderSpace

Used to ask the container for space for toolbars and other controls

SetBorderSpace

Tells the container to allocate the space for toolbars and other controls

SetActiveObject

Called by the ActiveX document to create a link between itself and the ActiveX container

IOleContainer

IOleContainer is used to query objects in a compound document or to lock the container in the running state. This interface is useful only when the container supports linked objects and requires both the container and the document to implement it. Table 13.5 describes the interfaces.

Table 13.5. IOleContainer interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IParseDisplayName method

ParseDisplayName

Parses a display name into something usable by a moniker

IOleContainer methods

EnumObjects

Enumerates objects in the container

LockContainer

> Keeps the container locked in running mode until it is explicitly released

IOleClientSite

IOleClientSite provides the means by which an ActiveX document obtains information about its container environment. It can determine information about its display area as well as other user interface information from the container. Table 13.6 describes the interfaces.

Table 13.6. IOleClientSite interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IOleClientSite methods

SaveObject

Saves the ActiveX document associated with this site

GetMoniker

Provides a way of creating a moniker to access the embedded ActiveX document

GetContainer

Returns a pointer to the container's IOleContainer interface

ShowObject

Positions the ActiveX document so that it is visible to the user; makes sure the container itself is visible to the user

OnShowWindow

Notifies the container when an object is about to become visible or invisible; does not apply to ActiveX documents or other in-place, activated objects

RequestNewObjectLayout

Asks the container to provide more or less space for displaying the ActiveX document

IAdviseSink

IAdviseSink provides a way for an ActiveX document to notify its container when its data or state changes. Table 13.7 describes the interfaces.

Table 13.7. IAdviseSink interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IAdviseSink methods

OnDataChange

Called when the data has changed

OnViewChange

Called when the view has changed

OnRename

Called when the name has changed

OnSave

Called when the ActiveX document has been saved to disk

OnClose

Called when the ActiveX document has been closed

IOleDocumentSite

IOleDocumentSite allows an ActiveX document to bypass the normal activation sequence for an in-place object and activate directly as a document object. Table 13.8 describes the interfaces.

Table 13.8. IOleDocumentSite interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IOleDocumentSite method

ActivateMe

Actives the ActiveX document as a document object instead of an in-place object

IOleInPlaceSite

IOleInPlaceSite works in conjunction with IOleDocumentSite. For each view that an ActiveX document instantiates, an IOleInPlaceSite object must exist. IOleDocumentSite manages one or more IOleInPlaceSite objects. This interface provides methods that manage the ActiveX document. Table 13.9 describes the interfaces.

Table 13.9. IOleInPlaceSite interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IOleWindow methods

GetWindow

Gets the window handle to the frame, the document, the parent, or the in-place object

ContextSensitiveHelp

Gives the container the opportunity to handle context-sensitive help

IOleInPlaceSite methods

CanInPlaceActivate

Gives the object permission to in-place activate

OnInPlaceActivate

Notifies the container that the ActiveX document is about to in-place activate

OnUIActivate

Called when the ActiveX document is about to in-place activate and replace the menu with a composite menu

GetWindowContext

Provides window hierarchy information

Scroll

Tells the container how to scroll the object

OnUIDeactivate

Tells the container that the ActiveX document is going away and that the container should restore its user interface.

OnInPlaceDeactivate

Tells the container that the ActiveX document is no longer in-place active

DiscardUndoState

Tells the container to discard its undo state

DeactivateAndUndo

Tells the container to end the in-place, active session and return to its undo state

OnPosRectChange

Used by the ActiveX document to tell the container that its size has changed

IContinueCallback

IContinueCallback provides a mechanism by which the ActiveX document can ask the container if it should continue an interruptible process. This is used in conjunction with the ActiveX document's IPrint interface. Table 13.10 describes the interfaces.

Table 13.10. IContinueCallback interfaces

Interface name

Description

IUnknown interfaces

QueryInterface

Discovers required interfaces

AddRef

> Adds a reference count to the object

Release

Decrements the reference count for the object and eventually deletes the object

IContinueCallback methods

FContinue

Used by printing tasks to determine if printing should continue

FContinuePrinting

Used by the printing tasks to determine if the task should continue; also provides some progress information

More information about these COM interfaces can be found in the Visual C++ help. It is worth the time to read the descriptions of the interfaces in the help system. It provides a good background to the world of COM, OLE, and ActiveX. Another interesting exercise is to grep through the MFC source code to see where Microsoft has implemented these and other COM interfaces in the MFC Class Library. The MFC source code is usually located under the DevStudioVcMfc directory.

Building an ActiveX Container

There are several ways to build an ActiveX container. The most educational way is to use the native COM interfaces. Building a container this way would take longer, but would greatly increase your understanding of the intricacies of COM. We will not build a container this way in this chapter. If you are interested in trying this, read through the appropriate sections of Inside OLE, by Kraig Brockschmidt.

Another way to build an ActiveX container is to make use of the new ATL template library. This library is an alternative approach to using the MFC class library. These libraries are fundamentally different from each other. ATL is based on the idea of a template. Templates are ways of implementing code without knowing what kind of data is being worked with. For example, suppose you had a class that added two integers and another class that added two floating-point numbers. The code for both of these classes would be remarkably similar, perhaps something like c = a + b. The only difference between the two implementations is the type of data used in the calculation. This is the perfect situation for a template class. The code for the template looks the same c = a + b, but the types of a, b, and c are not resolved until the template class is declared in the code. If you are interested in learning more about templates, take a closer look at some of the MFC collection classes, the Standard Template Library, or the ATL. The key benefit to this approach is the small size of programs built with ATL.

MFC is based on the idea of a hierarchical class library. Programmers are encouraged to build layers of classes that can inherit behaviors from their parent classes. This approach tends to make it very easy to implement functionality because, in most cases, you can just inherit it. However, hierarchical classes tend to grow large, both in terms of the size of programs generated and the number of classes to learn and understand. The programming language SmallTalk is built on the idea of inheriting functionality and overriding the behaviors you want to change. The key characteristics of a SmallTalk project is that it takes a new person a long time to learn the SmallTalk hierarchy. But someone who knows SmallTalk can implement new functionality quickly. SmallTalk programs also tend to be large. MFC programs share these characteristics.

For the purpose of this chapter, we will use MFC to build a container program. We do this because we can inherit a great deal of ActiveX container behavior without writing any code. In addition, since containers are not usually downloaded through the Internet, the size of the resulting container program is not as critical as it is for other kinds of ActiveX programs.

The XContainer Program

We will now build a simple ActiveX container called XContainer. We'll step through the Visual C++ AppWizard and review the results. The AppWizard automatically generates much of the code that is needed for a container. The AppWizard does not directly support the new ActiveX container interfaces, however; we will have to add those manually.

Generating XContainer

We will now step through the Visual C++ AppWizard to generate a basic OLE container. To create a new project, select New from the File menu. Figure 13.5 illustrates the dialog that you should see. For the XContainer project, we will use the MFC EXE AppWizard. Fill in the edit boxes as indicated and click OK.

FIGURE 13.5. Creating a new project with Visual C++

Figure 13.6 illustrates the next dialog you should see. This dialog asks you what kind of application to create. The three basic types are SDI (Single Document Interface), MDI (Multiple Document Interface), and dialog-based. For the purposes of the XContainer program, choose Single document. Click Next to continue.

Figure 13.7 illustrates the next dialog you should see. This dialog allows you to specify the type of automatic database support that will be added to the application. Because we will not be using a database, select None and click Next to continue.

Figure 13.8 illustrates the next dialog you should see. This is where you tell the AppWizard that you want it to generate container support. We will not be supporting ActiveX controls in this example, so you can deselect that option. Click Next to continue.

FIGURE 13.6. Selecting a single-document application

FIGURE 13.7. Selecting database support

FIGURE 13.8. Selecting compound document support

Figure 13.9 illustrates the next dialog you should see. This dialog is for selecting miscellaneous user interface support. Leave the defaults and click Next to continue.

Figure 13.10 illustrates the next dialog you should see. This dialog is for selecting source code comments and MFC library support. Leave the defaults. Source comments are always useful, and making use of MFC in a shared DLL is more efficient than statically linking the MFC library with your application.

FIGURE 13.9. Selecting additional miscellaneous features

Figure 13.11 illustrates the next dialog that you should see. This is a summary of the MFC classes that the App Wizard will generate for you. Click Finish to continue.

Figure 13.10. Selecting source code comments and MFC support

Figure 13.11. The MFC Class review screen appears next

Figure 13.12 illustrates the last AppWizard dialog. Click OK to generate the XContainer code.

FIGURE 13.12. The final AppWizard screen

Reviewing the Code

Let's take a look at the files that AppWizard has generated. Table 13.11 contains the list of filenames.

Table 13.11. Generated files and their descriptions

CPP/header name

Purpose

StdAfx

Precompiled header support.

CntrItem

These files contain a class called CXContainerCntrItem. This class is derived from COleClientItem and supplies most of the OLE support for the container. We will modify these files to add ActiveX container support.

MainFrm

These files contain the class derived from CFrameWnd.

XContainer

These files contain the class derived from CWinApp.

XContainerDoc

These files contain the class derived from COleDocument.

XContainerView

These files contain the class derived from CView.

At this point, compile the XContainer application and run it. Without writing any code, we have a basic OLE container. Click the Edit menu and choose the Insert Object menu item. This will pop up a dialog and ask you to choose an OLE object type to insert into the container. If you have Microsoft Word, select it. Otherwise, choose some other OLE object. Figure 13.13 shows what the first iteration of XContainer looks like with Microsoft Word inserted into the container.

FIGURE 13.13. The first iteration of XContainer with Microsoft Word

Amazing, isn't it? All we did was click buttons, and voilà! An OLE container! Notice that the Word menus and toolbars have merged with XContainer, and Word does not fill the entire container client area. Also, there is a funny hashed border around the area where Word was placed. These are all characteristics of an embedded document.

AppWizard generates a great deal of code for us. If we were to implement complete support for linked and embedded objects, we would have to add support for the following issues:

  • Correctly sizing the embedded object
  • Hit testing and selection
  • Object activation
  • Resizing and moving
  • Deleting embedded objects
  • Copying and pasting
  • Menu merging

Interestingly enough, because an ActiveX document occupies the full client area, many of these issues are not applicable. If you want to learn more about these issues, search for an article titled 'Creating an OLE Container' in the Visual C++ help file. It is part of the OLE Container Tutorial. In the XContainer example, we will focus on the new interfaces that need to be implemented to support ActiveX documents in the container.

Adding the New Interfaces

We will now concentrate on adding the new ActiveX COM interface: IOleDocumentSite. The CntrItem.h and CntrItem.cpp files will need to be modified to accomplish this. Listing 13.1 shows the CntrItem.h file.

Listing 13.1. The CntrItem.h file.

// CntrItem.h : interface of the CXContainerCntrItem class


#if !defined(AFX_CNTRITEM_H__979CFC0E_DFC1_11D0_9845_0000C0E888CF__INCLUDED_)
#define AFX_CNTRITEM_H__979CFC0E_DFC1_11D0_9845_0000C0E888CF__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

class CXContainerDoc;
class CXContainerView;

class CXContainerCntrItem : public COleClientItem

CXContainerView* GetActiveView()


// ClassWizard generated virtual function overrides
//}AFX_VIRTUAL

// Implementation
public:
~CXContainerCntrItem();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
virtual void Serialize(CArchive& ar);

public:

IOleDocumentView *m_pDSView;

BEGIN_INTERFACE_PART(OleDocumentSite, IOleDocumentSite)
INIT_INTERFACE_PART(CXContainerCntrItem, OleDocumentSite)
STDMETHOD(ActivateMe)(LPOLEDOCUMENTVIEW);
END_INTERFACE_PART(OleDocumentSite)


DECLARE_INTERFACE_MAP()





// Microsoft Developer Studio will insert additional declarations immediately
before the previous line.

#endif // !defined(AFX_CNTRITEM_H__979CFC0E_DFC1_11D0_9845_0000C0E888CF__INCLUDED_)

This is essentially the file that was generated by the AppWizard with the addition of some MFC macros. These macros are the way that MFC implements COM interfaces. Table 13.12 itemizes these macros.

Table 13.12. MFC macros to implement a COM interface

Macro name

CDescription

 

BEGIN_INTERFACE_PART

This macro takes two parameters. The first is the name of a class that the macro will declare. Actually, MFC will prepend an X at the begin- ning of the name that you supply—in our case, XOleDocumentSite. The second parameter is the COM interface that this generated class will inherit from. The macro will also declare an instance of this class by prepending m_x in front of the name—in our case, m_xOleDocumentSite.

INIT_INTERFACE_PART

This macro takes two parameters. The first is the name of the class in which the COM interface will live. In our case, the COM interface is inside CXContainerCntrItem. The second parameter is the name of the generated class specified in BEGIN_INTERFACE_PART. These two parameters tell MFC how to connect the classes together.

STDMETHOD

This macro specifies the calling conventions of the COM method and the method name—in our case, ActivateMe. ActivateMe takes one parameter, a pointer to the ActiveX document's IOleDocumentView object.

END_INTERFACE_PART

This macro completes the set and takes one parameter, the name of the generated class.

DECLARE_INTERFACE_MAP

This macro places the actual map in the class for MFC to reference at runtime.

It should be noted that BEGIN_INTERFACE_PART automatically generates the three IUnknown methods for the class XOleDocumentSite: AddRef, Release, and QueryInterface.

Listing 13.2 shows the CntrItem.cpp file.

Listing 13.2. The CntrItem.cpp file

1// CntrItem.cpp : implementation of the CXContainerCntrItem class

#include 'stdafx.h'
#include 'XContainer.h'

#include 'XContainerDoc.h'
#include 'XContainerView.h'
#include 'CntrItem.h'

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// CXContainerCntrItem implementation

IMPLEMENT_SERIAL(CXContainerCntrItem, COleClientItem, 0)

CXContainerCntrItem::CXContainerCntrItem(CXContainerDoc* pContainer)
: COleClientItem(pContainer)


CXContainerCntrItem::~CXContainerCntrItem()



void CXContainerCntrItem::OnChange(OLE_NOTIFICATION nCode, DWORD dwParam)


BOOL CXContainerCntrItem::OnChangeItemPosition(const CRect& rectPos)

void CXContainerCntrItem::OnGetItemPosition(CRect& rPosition)


void CXContainerCntrItem::OnActivate()


void CXContainerCntrItem::OnDeactivateUI(BOOL bUndoable)


void CXContainerCntrItem::Serialize(CArchive& ar)

else




// CXContainerCntrItem diagnostics

#ifdef _DEBUG
void CXContainerCntrItem::AssertValid() const


void CXContainerCntrItem::Dump(CDumpContext& dc) const

#endif

// This code adds support for the IOleDocumentSite interface. This is the
// only additional COM interface required to create an ActiveX Container.


BEGIN_INTERFACE_MAP(CXContainerCntrItem, COleClientItem)
INTERFACE_PART(CXContainerCntrItem, IID_IOleDocumentSite, OleDocumentSite)
END_INTERFACE_MAP()


// Three standard IUnknown implementations


STDMETHODIMP_(ULONG) CXContainerCntrItem::XOleDocumentSite::AddRef()


STDMETHODIMP_(ULONG) CXContainerCntrItem::XOleDocumentSite::Release()


STDMETHODIMP CXContainerCntrItem::XOleDocumentSite::QueryInterface( REFIID iid, ALPVOID* ppvObj )



// The ActivateMe implementation


STDMETHODIMP CXContainerCntrItem::XOleDocumentSite::ActivateMe( ALPOLEDOCUMENTVIEW pDocView )
else
pThis->m_pDSView = pDocView;

//-------- ----- ------ -------- ----- ------ ----
// Negotiate toolbars and menus with the view.
//-------- ----- ------ -------- ----- ------ ----
pDocView->UIActivate(TRUE);

//-------- ----- ------ -------- ----- ------ ----
// Now that we have toolbars, etc. filling our client area, let's find
// out what is left for our ActiveX Document view.
//-------- ----- ------ -------- ----- ------ ----
pThis->GetActiveView()->GetClientRect( &rect );
pDocView->SetRect( &rect );

//-------- ----- ------ -------- ----- ------ ----
// Show the view to the world!
//-------- ----- ------ -------- ----- ------ ----
pDocView->Show( TRUE );
return NOERROR;

This, essentially, is the file that was generated by AppWizard. Some additions have been made to implement the macros that we added to the header file.

The new code starts with the BEGIN_INTERFACE_MAP macro. Table 13.13 itemizes the implementation macros.

Table 13.13. MFC macros for implementing COM interfaces

Macro name

Description

BEGIN_INTERFACE_MAP

This macro takes two parameters. The first parameter is the name of the class that contains the implementation of the COM interface. The second parameter is the name of the MFC base class for the first parameter.

INTERFACE_PART

This macro takes three parameters. The first parameter is the name of the class that contains the implementation of the COM interface. The second parameter is the unique identifier for the COM interface. This identifier starts with IID_, by convention. The third parameter is the name of the generated class. This name needs to match the name in the header file.

END_INTERFACE_MAP

This macro finishes the declaration.

The BEGIN_INTERFACE_PART macro in the header file automatically declares the three IUnknown methods. An implementation of these methods is required here. Notice that the name of the method is CXContainerCntrItem::XOleDocumentSite::AddRef. This kind of syntax indicates that the XOleDocumentSite class is actually declared within the context of the CXContainerCntrItem class. Therefore, in order to reference the AddRef method, you need to tell the compiler that you are declaring the AddRef method, which is part of XOleDocumentSite, which is part of CXContainerCntrItem.

Each COM method must begin with a METHOD_PROLOGUE_EX macro. As the macro name implies, it generates the appropriate prologue code before continuing with the rest of the code.

The most interesting implementation is the ActivateMe method. This method is called by the ActiveX document to tell the container that it should bypass the normal embedded object activation and bring up the document in the full client area. This method takes a pointer to the ActiveX document's IOleDocumentView object.

This method needs to create a connection between the container's IOleInPlaceSite interface and the document's IOleDocumentView interface. Next, it needs to tell the document to set up its menus and toolbars. The container tells the document how big the client area is and finally tells the document to show itself.

That's it! Figure 13.14 shows what XContainer looks like after support has been added for the IOleDocumentSite interface.

FIGURE 13.14. XContainer as a full ActiveX container

It is also possible to implement the IOleCommandTarget and IContinueCallback COM interfaces in the same manner. However, these interfaces are not required for ActiveX containers.

Summary

This chapter begins to explore the world of ActiveX containers. ActiveX represents Microsoft's continuing evolution of the OLE and COM technologies. It is a credit to the COM architecture that the OLE technologies can effectively change over time without becoming obsolete.

This chapter reviews portions of the OLE and COM architectures that are relevant to ActiveX container technology. Although the MFC classes have not yet changed to support the new ActiveX container COM interfaces, it is relatively easy to add the required support.

Other methods are available to implement ActiveX containers, in addition to using MFC. Containers could be implemented using the native COM interfaces or with the more recent ATL template library. Using MFC is completely appropriate in this case, though, because containers don't have the same constraints put on them as do other Internet-oriented COM objects.


Document Info


Accesari: 710
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2025 )