It is the province of knowledge to speak, and it is the privilege of wisdom to listen.
—Dr. Oliver Wendell Holmes
In Chapter 2, we explored the notion of incoming interfaces for an object and the QueryInterface function that manages these interfaces. "Incoming," in the context of a client-object relationship, implies that the object "listens" to what the client has to say. In other words, incoming interfaces and their member functions are like an object's sensory organs—its eyes, ears, nose, and nerve endings—which receive input from the outside. But there is only so much you can say in a one-sided conversation.
Objects are fairly tolerant of loquacious clients, so they usually don't mind listening. Many objects, however, have useful things to say themselves, and this requires a two-way dialogue between object and client. Such two-way communication involves outgoing interfaces—the different languages that an object can speak through its own mouth as opposed to those that it can understand through its incoming senses. When an object supports one or more outgoing interfaces, it is said to be connectable. In this chapter, we'll cover the mechanisms that make connectable objects—also, for brevity, called sources—work.
A source can, of course, have as many outgoing interfaces as it likes. Each interface is composed of distinct member functions, with each function representing a single event, notification, or request. Events and notifications are equivalent concepts (and interchangeable terms), as they are both used to tell the client that something interesting happened in the object—that data changed, a property changed, or the user did something such as click a button. Obviously events are very important for OLE Controls, which use the mechanisms we'll describe in this chapter. Events and notifications differ from a request in that the object expects no response from the client. A request, on the other hand, is how an object asks the client a question and expects a response. For example, an object that allows a client to override an action such as a property change will first ask the client whether it will allow that action to occur. Events and requests are quite similar to Windows messages, some of which inform a window of an event (WM_MOVE, WM_PAINT, WM_COMMAND, WM_WININICHANGE, and so forth) and others of which ask for information (WM_CTLCOLOR, WM_QUERYENDSESSION).
In all of these cases, there must be some client that listens to what the object has to say and uses that information wisely. It is the client, therefore, that actually implements these interfaces on objects called sinks. From the sink's perspective, the interfaces are incoming, meaning that the sink listens through them. A connectable object plays the role of a client as far as the sink is concerned; thus, the sink is what the object's client uses to listen to that object. Confused about who is doing what? Let's look at the connectable object mechanisms to set everything straight.