Chapter 15 OLE Automation Controllers and Tools

Various airlines, at least in the United States, pipe the communications between the pilot and the air traffic controller, allowing passengers to listen to their exchanges. Before I listened to one of these exchanges, I never thought of how pilots decide when to reduce speed or altitude on their approach to an airport. When I did listen the first time, I was mildly surprised—mostly from my ignorance of how a pilot and an air traffic controller work together. Every change in the status of the airplane was directed by the air traffic controller, who was keeping track of all the airplanes around that airport and coordinating their approach for landing. The controller in charge is the only person who understands where all the airplanes are, the only person who is aware of the relationship between the planes and of how to keep them from crashing into one another. The pilots of each airplane might be aware of one or two other planes—when visual contact is established—but they are otherwise too busy flying their own machine to think about the big picture.

I was struck most by how the controller would call an order to the pilot of my airplane, the pilot would acknowledge the order, and then I would feel the plane move…all the way to landing. The controller doesn't really know how the pilot moves the airplane; the pilot doesn't know how the controller knows what orders to give. Each of them trusts the other to understand his or her role in landing an airplane safely at a busy airport.

The relationship between an air traffic controller and an airplane pilot is the same as the relationship between an OLE Automation controller—or any client—and an object. The controller understands the big picture and how the objects (the pilots) are integrated into that whole. With that understanding, the controller can send the right commands at the right time to each object involved and keep everything running perfectly. No object is aware of the big picture—each is perhaps aware of only a few other objects—but each otherwise concentrates on making the internals of the encapsulated object (and there's no doubt that an airplane is encapsulated) work smoothly and without error. The controller and the object communicate through a standard interface. With airplanes, it's the specific terminology defined by the Federal Aviation Administration; with OLE, it's the interfaces and dispinterfaces we know and love so well.

This chapter will first look in more detail at the relationship between an automation controller and an object and at how this relationship can affect design decisions for both. We'll then look at the implementation of the AutoCli sample, which illustrates the way a controller calls IDispatch functions and handles exceptions. This sample is written specifically to work with the Beeper objects from Chapter 14; it doesn't have a generic language structure in which you can write automation scripts. (A more complex sample, one in which you could write automation scripts, is outside the scope of this book as well as its author.) That won't stop us from looking at the features of a much richer and generic controller, however, and at the ways those features might be implemented using automation objects.

Although half of this chapter is focused on the design and features of tools and other sophisticated controllers, much of what we'll see is relevant to a fair number of objects themselves, especially OLE controls that fire events by calling someone else's IDispatch implementation. That is, an object might implement both incoming and outgoing dispinterfaces, so it must know not only how to receive IDispatch calls but also how to call them. Even if you don't need outgoing interfaces, you will create the best and most powerful objects when you understand how a controller asks an object to perform various operations. Both sides need to understand the role of the other, just as air traffic controllers and airplane pilots need to understand each other.