In the late 1980s, Microsoft Windows development was an arcane art. Playing in the Windows development arena meant learning the Windows API—a set of functions exported by the Windows system DLLs. Everything in your Windows source code file had to be right or your program wouldn't work. And to top things off, every single Windows application was basically the same underneath the hood. Nearly every Windows application services both the message queue and a window procedure that processes window messages.
Of course, that's why there's MFC, right? MFC exists to save developers from having to constantly rewrite their message loops and window procedures. In MFC, you simply combine a CWinApp-derived class and a CWindow-derived class and voilà—you have a working Windows application.
Now we're in the age of component development, and folks are assembling systems from a variety of different pieces. At the center of all this component development is COM. When all the components can agree on how to talk to one another, it doesn't matter whether they are built using C++, Java, Microsoft Visual Basic, assembly language, or whatever.
Even though this new component development philosophy has come to pervade the software industry, some things remain constant—such as the need for a user interface. And a windowed interface is the style of user interface in vogue today. So if you're a C++ developer (and you don't succumb to the temptation of using Visual Basic), this means you're still going to need to service the message loop and write window procedures. Of course, you can choose to use MFC to help you. If you don't feel like buying into the whole MFC gestalt, however, there's another framework out there that will hide the message loop and wrap window handles for you—ATL. In this chapter, we'll examine how ATL handles windowing so that you can use it as an effective Windows application development tool (in addition to using it as an effective COM development tool).
Even the purest COM developer has to create a window once in a while. ATL isn't a rapid development environment for user interfaces, but it does provide an extensible variety of windowing classes that help in the creation and use of dialog boxes, control windows, standard windows, and more. The implementations range from the very thin CWindow to a complete Microsoft ActiveX control container with CAxHostWindow. The ATL window classes provide a reasonable compromise between adding MFC to your ATL project and coding straight to the Win32 SDK. Unlike MFC, ATL defines the message-handling part of a window in a separate class from the window, allowing you to easily create objects that process messages for a window but aren't windows themselves. This granularity promotes message-handling code reuse and enables extensibility.
Figure 14-1 shows the ATL 3.0 window class hierarchy when you use the default template parameters for base classes.
Figure 14-1. ATL 3.0 Window classes.
Many of the classes shown in the diagram have templatized base classes. This chart, however, represents the most commonly used case. Some of these classes you might never use, some aren't directly documented by ATL, and some provide implementation for more derived classes. We'll concentrate on the classes ATL intends for public consumption. In addition to the classes shown in Figure 14-1, the following typedefs are defined:
typedef CAxWindowT<CWindow> CAxWindow; typedef CWindowImplBaseT<CWindow> CWindowImplBase; typedef CDialogImplBaseT<CWindow> CDialogImplBase; typedef CContainedWindowT<CWindow> CContainedWindow;
These typedefs specify versions of ATL template window classes with CWindow as the base class. When using the default template parameters, CAxWindowT is equivalent to CAxWindow, and so on. ATL window classes are implemented in atlwin.h.