- Table of Contents
- Copyright
- About the Authors
- About the Contributors
- Acknowledgments
- Tell Us What You Think!
- Introduction
- How to Use This Book
- What You Need to Use This Book
- What's New in Visual C++ 6.0
- Contacting the Main Author
- Part I: Introduction
- Chapter 1. The Visual C++ 6.0 Environment
- Part II: MFC Programming
- Chapter 2. MFC Class Library Overview
- Chapter 3. MFC Message Handling Mechanism
- Chapter 4. The Document View Architecture
- Chapter 5. Creating and Using Dialog Boxes
- Chapter 6. Working with Device Contexts and GDI Objects
- Chapter 7. Creating and Using Property Sheets
- Chapter 8. Working with the File System
- Chapter 9. Using Serialization with File and Archive Objects
- Part III: Internet Programming with MFC
- Chapter 10. MFC and the Internet Server API (ISAPI)
- Chapter 11. The WinInet API
- Chapter 12. MFC HTML Support
- Part IV: Advanced Programming Topics
- Chapter 13. Using the Standard C++ Library
- Chapter 14. Error Detection and Exception Handling Techniques
- Chapter 15. Debugging and Profiling Strategies
- Chapter 16. Multithreading
- Chapter 17. Using Scripting and Other Tools to Automate the Visual C++ IDE
- Part V: Database Programming
- Chapter 18. Creating Custom AppWizards
- Chapter 19. Database Overview
- Chapter 20. ODBC Programming
- Chapter 21. MFC Database Classes
- Chapter 22. Using OLE DB
- Chapter 23. Programming with ADO
- Part VI: MFC Support for COM and ActiveX
- Chapter 24. Overview of COM and Active Technologies
- Chapter 25. Active Documents
- Chapter 26. Active Containers
- Chapter 27. Active Servers
- Chapter 28. ActiveX Controls
- Part VII: Using the Active Template Library
- Chapter 29. ATL Architecture
- Chapter 30. Creating COM Objects Using ATL
- Chapter 31. Creating ActiveX Controls Using ATL
- Chapter 32. Using ATL to Create MTS and COM+ Components
- Part VIII: Finishing Touches
- Chapter 33. Adding Windows Help
- Part IX: Appendix
The Active Template Library
The Active Template Library (ATL) is a recent addition to the Visual C++ product. It came about primarily as a result of the explosive growth of the Internet and Microsoft's ActiveX strategy, which originally was developed to encourage the use of COM-based components on the Internet and corporate intranets. In order for these controls to make sense in the Internet market, the controls have to be small and compact so that they can be downloaded from Web servers quickly. It certainly is possible to build these controls with MFC, but MFC applications are characteristically large and require large support DLLs. Another alternative to MFC was needed that could create smaller controls without the need for support DLLs. The ATL is the alternative Microsoft has provided.
ATL and MFC differ in their approaches. Both libraries rely on C++ capabilities, but that is where their similarities end. MFC is built on the concept of a class hierarchy. Most of the MFC classes derive from other classes, which eventually derive from CObject. This hierarchy allows classes to inherit many behaviors from their ancestors. As an example, consider the CButton class. It implements a handful of new methods but inherits a tremendous amount of behavior from the CWnd class. CWnd, in turn, inherits from CCmdTarget, which inherits from CObject. A strategy like this has a few interesting characteristics:
- The class hierarchy tends to be deep and therefore requires a lot of study to grasp.
- Application behavior is accomplished by inheriting from certain classes and overriding methods. This behavior creates a white-box effect and again requires a lot of study to understand how to integrate changes into any new derived classes.
- After you master the learning curve, you can quickly implement applications because so much behavior can be inherited.
ATL takes a different approach than MFC. It is based on the concept of a template. A template is a way of capturing an algorithm in the form of a pattern. For example, if you have a mathematical formula such as x + y + z that you want to implement for integers and floating-point numbers, you could create two classes:
class HighTechInteger
{
public:
HighTechInteger();
~HighTechInteger();
integer Calculate( int x, int y, int z ) { return( x+y+z ); }
};
class HighTechFloat
{
public:
HighTechFloat();
~HighTechFloat();
float Calculate( float x, float y, float z ) { return( x+y+z ); }
};
Notice how both implementations have identical algorithms for their Calculate methods. Given these classes, however, you could never use the HighTechInteger class to handle floating-point numbers. You must maintain two separate classes. This creates opportunities for bugs to be introduced if both classes are not kept in sync. The alternative is to create a template:
template <Type> class HighTech
{
public:
HighTech();
~HighTech();
Type Calculate( Type x, Type y, Type z ) { return( x+y+z ); }
};
HighTech<int> htInteger;
HighTech<float> htFloat;
Notice how this unifies the source code base and increases code reliability because the algorithm is implemented only once.
Another feature of C++ that ATL uses is multiple inheritance. C++ allows one class to inherit from several parent classes. Grady Booch, in his book Object-Oriented Analysis and Design with Applications (Addison-Wesley, 1998), describes special lightweight classes designed for multiple inheritance as mixin classes. C++ multiple inheritance can be used in many ways, but classes designed for the mixin approach typically are thin, focused, and easily reusable. Let's consider a mixin scenario:
class subtractMixin
{
public:
int Sub( int x, int y );
};
class MyCoolClass : public CoolBaseClass
{
public:
int Add( int x, int y );
};
class MyFriendsClass : public CoolBaseClass
{
public:
int Mult( int x, int y );
}
Suppose that the subtractMixin class is a useful, reusable algorithm that can be used in a variety of situations—it can be mixed in with many different classes. One way to implement this kind of feature would be as a separate class that could be inherited from to obtain the desired behavior. This class would be considered a mixin class. Mixin classes do not necessarily provide usefulness by themselves but are useful as additive behaviors. Now suppose that you want your MyCoolClass to have the capability to subtract as well as add. You could define another method in the MyCoolClass class or just inherit the behavior from subtractMixin:
class MyCoolClass : public CoolBaseClass, public subtractMixin
{
public:
int Add( int x, int y );
};
In addition, you could add subtract behavior to MyFriendsClass or any other class by inheriting from subtractMixin. It is not very useful to create an instance of subtractMixin by itself, however.
ATL uses both the template concept and the mixin concept. Because many of the COM interfaces are small and clean, they lend themselves to being used as mixin classes. The ATL strategy has these characteristics:
- There is no large class hierarchy to learn, but there are a number of mixin classes to learn.
- Application behavior is accomplished by inheriting from the required number of mixin classes. This approach tends to be more black box, although not necessarily.
- It takes more effort to implement the application. Unlike MFC applications, which inherit a great deal of behavior, ATL applications inherit only the necessities and must implement the rest manually.
- ATL applications are smaller than MFC applications as a result of shallow class hierarchies.
ATL is discussed in more detail in Part VII, "Using the Active Template Library."
ATL Classes Required for Active Document Support
The following list provides an overview of some of the ATL classes you will see in the ACTIVEDOC sample program:
- CComObjectRoot is a typedef of CComObjectRootEx. All ATL classes must inherit from this class. This class provides support for all the IUnknown interfaces and maintains the COM object's reference counts. It also determines whether the object supports single or multiple threading.
- CComCoClass is used to obtain CLSID and error information, and determines the default class factory. All classes that must be visible externally should inherit from this class.
- CComControl provides a number of useful functions for implementing ActiveX controls.
- IDispatchImpl provides an implementation of IDispatch.
- IProvideClassInfo2Impl provides type library information.
- IPersistStreamInitImpl provides a means of storing application data in a single storage stream.
- IPersistStorageImpl provides a means of asking the object to save and load itself from a storage object.
- IQuickActivateImpl provides a means for a container to ask for all the interfaces an object supports all at once.
- IOleControlImpl provides an implementation of IOleControl.
- IOleObjectImpl provides an implementation of IOleObject.
- IOleInPlaceActiveObjectImpl provides an implementation of IOleInPlaceActiveObject.
- IViewObjectExImpl provides implementations of IViewObject, IViewObject2, and IViewObjectEx.
- IOleInPlaceObjectWindowlessImpl provides an implementation of IOleInPlaceObject and IOleInPlaceObjectWindowless.
- IDataObjectImpl provides an implementation of IDataObject.
- ISupportErrorInfo defines a means by which the application can return error information to the container.
The ACTIVEDOC Program | Next Section

Account Sign In
View your cart