The Application Kit is the starting point for all applications. Its classes establish an application as an identifiable entity--one that can cooperate and communicate with other applications (including the Browser). It lays a foundation for the other kits. Before designing and building your application, you should secure a breathing familiarity with this basic Kit.
There are four parts to the Application Kit:
The messaging mechanism is implemented by a set of collaborating classes: BMessage objects bundle information so that it can be posted to a thread within the same application or sent to a thread in another application. BLooper objects run message loops in threads, getting messages as they arrive and dispatching them to BHandler objects. The BHandler's job is to respond to the message.
The system employs the messaging mechanism to carry basic input to applications--from the keyboard and mouse, from the Browser, and from other external sources; system messages drive what most applications do. Every application will be on the receiving end of at least some of these messages and must have handlers ready to respond to them.
Applications can also use the mechanism to create threads with a messaging interface, arrange communication among the threads, or exchange information with and issue commands to other applications.
The BApplication object also runs the application's main message loop, where it receives messages that concern the application as a whole. Externally, this object represents the application to other applications; internally, it's the center where application-wide services and global information can be found. Because of it's pivotal role, it's assigned to a global variable, be_app, to make it easily accessible.
Other kits--the Interface Kit in particular--won't work until a BApplication object has been constructed.
The messaging framework and the fundamentals of setting up a Be application are described in the following sections of this introduction. The BApplication class is documented beginning on page 21. The other classes follow in alphabetical order.
At minimum, a messaging service must provide the means for:
BMessage objects are parcels of information that can be transferred between threads. The message source constructs a BMessage object, adds whatever information it wants to it, and then passes the parcel to a function that delivers it to a destination.
A BMessage can hold structured data of any type or amount. When you add data to a message, you assign it a name and a type code. If more than one item of data is added with the same name and type, the BMessage creates an array of data for that name. The name and an index into the array are used to retrieve the data from the message.
The object also contains a command constant that says what the message is about. It's stored as a public data member (called what). The constant may:
Not all messages have data entries, but all should have a command constant. Sometimes the constant is sufficient to convey the entire message.
Both the source and the destination of a message must agree upon its format --the command constant and the names and types of data entries. They must also agree on details of the exchange--when the message can be sent, whether it requires a response, what the format of the reply should be, what it means if an expected data item is omitted, and so on.
None of this is a problem for messages that are used only within an application; the application developer can keep track of the details. However, protocols must be published for messages that communicate between applications. You're urged to publish the specifications for all messages your application is willing to accept from outside sources and for all those that it can package for delivery to other applications. The more that message protocols are shared, the easier it is for applications to cooperate with each other and take advantage of each other's special features.
The software kits define protocols for a number of messages. They're discussed in the Message Protocols appendix.
Typically, when an application creates an object, it retains responsibility for it; it's up to the application to free the objects it allocates when they're no longer needed. However, BMessage objects are an exception to this rule. Whenever a BMessage is passed to the messaging mechanism, ownership is passed with it. It's a little like mailing a letter --once you drop it at the post office, it no longer belongs to you.
The system takes responsibility for a delivered BMessage object and will eventually delete it--after the receiver is finished responding to it. A message receiver can assert responsibility for a message--essentially replacing the system as its owner--by detaching it from the messaging mechanism (with BLooper's DetachCurrentMessage() function).
In the Be model, messages are delivered to threads running message loops . Arriving messages are placed in a queue, and are then taken from the queue one at a time. After getting a message from the queue, the thread decides how it should be handled and dispatches it to an object that can respond. When the response is finished, the thread deletes the message and takes the next one from the queue--or, if the queue is empty, waits until another message arrives.
The message loop therefore dominates the thread. The thread does nothing but get messages and respond to them; it's driven by message input.
BLooper objects set up these message loops. A BLooper spawns a thread and sets the loop in motion. Posting a message to the BLooper delivers it to the thread (places it in the queue). The BLooper removes messages from the queue and dispatches them to BHandler objects. BHandlers are the objects ultimately responsible for received messages. Everything that the thread does begins with a BHandler's response to a message.
Two hook functions come into play in this process--one defined in the BLooper class and one declared by BHandler:
There's a close relationship between the BLooper role of running a message loop and the BHandler role of responding to messages. The BLooper class inherits from BHandler, so the same object can fill both roles. The BLooper is the default handler for the messages it receives.
To be notified of an arriving message, a BHandler must "belong" to the BLooper; it must have been added to the BLooper's list of eligible handlers. The list can contain any number of objects, but at any given time a BHandler can belong to only one BLooper.
While