When an application creates a window, it registers a window procedure with the Windows kernel. The window procedure is the routine that handles messages for the window. Traditionally, the window procedure contains a huge case statement with entries for each message the window has to handle. Keep in mind that "window" in this sense means just about anything on the screen: each window, each control, and so on. Every time you create a new type of window, you have to create a complete window procedure.
The VCL simplifies message dispatching in several ways:
- Each component inherits a complete message-dispatching system.
- The dispatch system has default handling. You define handlers only for messages you need to respond to specially.
- You can modify small parts of the message handling and rely on inherited methods for most processing.
The greatest benefit of this message dispatch system is that you can safely send any message to any component at any time. If the component does not have a handler defined for the message, the default handling takes care of it, usually by ignoring the message.
Tracing the flow of messages
The VCL registers a method called MainWndProc as the window procedure for each type of component in an application. MainWndProc contains an exception-handling block, passing the message structure from Windows to a virtual method called WndProc and handling any exceptions by calling the application class's HandleException method.
MainWndProc is a nonvirtual method that contains no special handling for any particular messages. Customizations take place in WndProc, since each component type can override the method to suit its particular needs.
WndProc methods check for any special conditions that affect their processing so they can "trap" unwanted messages. For example, while being dragged, components ignore keyboard events, so the WndProc method of TWinControl passes along keyboard events only if the component is not being dragged. Ultimately, WndProc calls Dispatch, a nonvirtual method inherited from TObject, which determines which method to call to handle the message.
Dispatch uses the Msg field of the message structure to determine how to dispatch a particular message. If the component defines a handler for that particular message, Dispatch calls the method. If the component does not define a handler for that message, Dispatch calls DefaultHandler.