The Architecture of OLE Controls

What is an OLE control? In mundane terms, a control is mostly a collection of functionality and content (or information). It can also involve a specific and dedicated user interface that allows an end user to directly access the control's functionality and to directly manipulate its content. In addition, a control can be manipulated programmatically so that another piece of code can use it to perform specific tasks. Controls are, therefore, self-contained units of functionality and content that are independent of where they actually reside. That is, a control of a specific type in one container behaves the same as a control of the same type in another container.

An OLE control exposes its functionality through both incoming and outgoing interfaces. The incoming interfaces allow access to a control's content. This includes rendering data for the client of that control through either data structures or individual properties. A control's outgoing interfaces can include not only notifications of data changes or property changes but also custom event sets—notifications that a control sends when the user triggers an event in that control. A button control, for example, typically sends an event such as OnClick when the user presses it. An edit control might send events such as OnChange and OnValidate. OLE Controls classifies such events as requests, do events, or simple notifications.

Through events, then, a control transforms a user's actions into meaningful and precise triggers. Code in the container of that control (the container can be another control itself) picks up this event and executes some code in response. A container such as the Patron sample we'll see in this chapter does nothing more than play a user-selected sound in response to an event. More sophisticated containers, Microsoft Access or Visual Basic, for example, allow the user to attach custom code to an event. In either case, the user (or developer) determines exactly what happens when an event occurs.

Events are mechanisms to extend and modify a control's behavior when the control allows it. Certain events notify a container of a control's state change so that the container can cancel or modify that change. Other events ask the container to perform some action itself and give the container a customization capability similar to that which virtual functions give the implementer of a C++ derived class. Like virtual functions, a container might cancel, replace, or enhance the behavior of the operations that the customizable control supports. But unlike virtual functions, events ensure that the control always has a chance to maintain a consistent internal state without relying on the container to defer to it explicitly at some point. This gives the customizable object a higher degree of encapsulation.

A control's content, as I mentioned, consists of both data structures and individual properties. All of the content is usually persistent. The content provided through data structures is usually the data managed in the control itself, such as the text inside an edit control. Properties, on the other hand, are named characteristics and values that a control or a container can modify programmatically. Although some of these can expose bits of the control's actual content, most are used to expose a control's visual and behavioral aspects. Visual aspects include colors, fonts, label text, and so on. Behavioral aspects include operations such as telling a button whether it should behave as the momentary variety or as the push-on/push-off sort.