Derived from: public BObject
Declared in: <app/Message.h>
A BMessage bundles information so that it can be conveyed from one application to another, one thread of execution to another, or even one object to another. Servers use BMessage objects to notify applications about events. An application can use them to communicate with other applications or to initiate activity in a different thread of the same application. In the Interface Kit, BMessages package information that the user can drag from one location on-screen and drop on another. They also hold data that's copied to the clipboard. Behind the scenes in the Storage Kit, they convey queries and hand back requested information.
A BMessage is simply a container. The class defines functions that let you put information into a message, determine what kinds of information are present in a message that's been delivered to you, and get the information out. It also has a function that let's you reply to a message once it's received. But it doesn't have functions that can make the initial delivery. For that it depends on the help of other classes in the Application Kit, particularly BLooper and BMessenger. See Messaging of the chapter introduction for an overview of the messaging mechanism and how BMessage objects work with these other classes.
When information is added to a BMessage, it's copied into dynamically allocated memory and stored under a name. If more than one piece of information is added under the same name, the BMessage sets up an array of data for that name. The name (along with an optional index into the array) is then used to retrieve the data.
For example, this code adds a floating-point number to a BMessage under the name "pi",
BMessage *msg = new BMessage; msg->AddFloat("pi", 3.1416);
and this code locates it:
float pi = msg->FindFloat("pi");
Names can be arbitrarily assigned. There's no limit on the number of named entries a message can contain or on the size of an entry. However, since the search is linear, combing through a very long list of names to find a particular piece of data may be inefficient. Also, because of the amount of data that must be moved, an extremely large message (over 100,000 bytes, say) can slow the delivery mechanism. It's sometimes better to put some of the information in a file and just refer to the file in the message.
In addition to named data, a BMessage carries a coded constant that indicates what kind of message it is. The constant is stored in the object's one public data member, called what. For example, a message that notifies an application that the user pressed a key on the keyboard has B_KEY_DOWN as the what data member (and information about the event stored under names like "key", "char", and "modifiers"). An application-defined message that delivers a command to do something might have a constant such as SORT_ITEMS , CORRECT_SPELLING, or SCROLL_TO_BOTTOM in the what field. Simple messages can consist of just a constant and no data. A constant like RECEIPT_ACKNOWLEDGED or CANCEL may be enough to convey a complete message.
By convention, the constant alone is sufficient to identify a message. It's assumed that all messages with the same constant are used for the same purpose and contain the same kinds of data.
The what constant must be defined in a protocol known to both sender and receiver. The constants for system messages are defined in app/AppDefs.h. Each constant names a kind of event--such as B_KEY_DOWN, B_REFS_RECEIVED, B_PULSE, B_QUIT_REQUESTED, and B_VALUE_CHANGED--or it carries an instruction to do something (such as B_ZOOM and B_ACTIVATE ).
It's important that the constants you define for your own messages not be confused with the constants that identify system messages. For this reason, we've adopted a strict convention for assigning values to all Be-defined message constants. The value assigned will always be formed by combining four characters into a multicharacter constant; the characters are limited to uppercase letters and the underbar. For example, B_KEY_DOWN and B_VALUE_CHANGED are defined as follows:
enum { . . . B_KEY_DOWN = '_KYD', B_VALUE_CHANGED = '_VCH', . . . };
Use a different convention to define your own message constants (or you'll risk having your message misinterpreted as a report of, say, a mouse-moved event). Include some lowercase letters, numerals, or symbols (other than the underbar) in your multicharacter constants, or assign numeric values that can't be confused with the value of four concatenated characters.
Data added to a BMessage is associated with a name and stored with two relevant pieces of information:
Type codes are defined in app/AppDefs.h for the common data types listed below:
B_CHAR_TYPE | A single character |
B_SHORT_TYPE | A short integer |
B_LONG_TYPE | A long integer |
B_UCHAR_TYPE | An unsigned char (the uchar defined type) |
B_USHORT_TYPE | An unsigned short (the ushort defined type) |
B_ULONG_TYPE | An unsigned long (the ulong defined type) |
B_BOOL_TYPE | A boolean value (the bool defined type) |
B_FLOAT_TYPE | A float |
B_DOUBLE_TYPE | A double |
B_POINTER_TYPE | A pointer of some type (including void *) |
B_OBJECT_TYPE | An object pointer (such as BMessage *) |
B_MESSENGER_TYPE | A BMessenger object |
B_POINT_TYPE | A BPoint object |
B_RECT_TYPE | A BRect object |
B_RGB_COLOR_TYPE | An rgb_color structure |
B_PATTERN_TYPE | A pattern structure |
B_ASCII_TYPE | Text in ASCII format |
B_RTF_TYPE | Text in Rich Text Format |
B_STRING_TYPE | A null-terminated character string |
B_MONOCHROME_1_BIT_TYPE | Raw data for a monochrome bitmap (1 bit/pixel) |
B_GRAYSCALE_8_BIT_TYPE | Raw data for a grayscale bitmap (8 bits per pixel) |
B_COLOR_8_BIT_TYPE | Raw bitmap data in the B_COLOR_8_BIT color space |
B_RGB_24_BIT_TYPE | Raw bitmap data in the B_RGB_32_BIT color space |
B_TIFF_TYPE | Bitmap data in the Tag Image File Format |
B_REF_TYPE | A record_ref |
B_RECORD_TYPE | A record_id |
B_TIME_TYPE | A representation of a date |
B_MONEY_TYPE | A monetary amount |
B_RAW_TYPE | Raw, untyped data--a stream of bytes |
You can add data to a message even if its type isn't on this list. A BMessage will accept any kind of data; you must simply invent your own codes for unlisted types.
To prevent confusion, the values you assign to the type codes you invent shouldn't match any values assigned to the standard type codes listed above--nor should they match any codes that might be added to the list in the future. The value assigned to all Be-defined type codes is a multicharacter constant, with the characters restricted to uppercase letters and the underbar. For example, B_DOUBLE_TYPE and B_POINTER_TYPE are defined as follows:
enum { . . . B_DOUBLE_TYPE = 'DBLE', B_POINTER_TYPE = 'PNTR', . . . };
This is the same convention used for message constants. Be reserves all such combinations of uppercase letters and underbars for its own use.
Assign values to your constants that can't be mistaken for values that might be assigned in system software. If you assign multicharacter values, make sure at least one of the characters is a lowercase letter, a numeral, or some kind of symbol (other than an underbar). If you assign numeric values, make sure they don't fall in the range 0x41414141 through 0x5f5f5f5f. For example, you might safely define constants like these:
#define PRIVATE_TYPE 0x1f3d #define OWN_TYPE 'Rcrd'
The messaging system is most interesting--and most useful--when data types are shared by a variety of applications. Shared types open avenues for applications to cooperate with each other. You are therefore encouraged to publish the data types that your application defines and can accept in a BMessage, along with their assigned type codes.
Contact Be (devsupport@be.com) to register any types you intend to publish, so that you can be sure to choose a code that hasn't already been adopted by another developer, and we'll endeavor to make sure that no one else usurps the code you've chosen.
If your application can respond to certain kinds of remote messages, you should publish the message protocol--the constant that should initialize the what data member of the BMessage, the names of expected data entries, the types of data they contain, the number of data items allowed in each entry, and so on. If your application sends replies to these messages, you should publish the reply protocols as well.
By making the specifications for your messages public, you encourage other applications to make use of the services your application offers, and you contribute to an integrated set of applications on the BeBox.
BMessage functions that add, find, replace, or get information about message data set a descriptive error code for the object, which the Error() function returns. The code is set to B_NO_ERROR if all is well; otherwise it indicates what went wrong during the last function call. Some functions also return the error code directly, but some do not.
Before proceeding with the next operation, it's a good idea to call Error() to be sure there was no error on the last one.
ulong what | A coded constant that captures what the message is about. For example, a message that's delivered as the result of a mouse-down event will have B_MOUSE_DOWN as its what data member. An application that requests information from another application might put a TRANSMIT_DATA or SEND_INFO command in the what field. A message that's posted as the result of the user clicking a Cancel button might simply have CANCEL as the what data member and include no other information. |
BMessage(ulong command) BMessage(BMessage *message) BMessage(void)
Assigns command as the BMessage's what data member, and ensures that the object otherwise starts out empty. Given the definition of a message constant such as,
#define RECEIPT_ACKNOWLEDGED 0x80
a complete message can be created as simply as this:
BMessage *msg = new BMessage(RECEIPT_ACKNOWLEDGED);
As a public data member, what can also be set explicitly. The following two lines of code are equivalent to the one above:
BMessage *msg = new BMessage; msg->what = RECEIPT_ACKNOWLEDGED;
Other information can be added to the message by calling AddData() or a kindred function.
A BMessage can also be constructed as a copy of another message . It's necessary to copy any messages you receive that you want to keep, since the thread that receives the message automatically deletes it before getting the next message. (More typically, you'd copy any data you want to save from the message, but not the BMessage itself.)
As an alternative to copying a received message, you can sometimes detach it from the message loop so that it won't be deleted (see DetachCurrentMessage() in the BLooper class).
Messages should be dynamically allocated with the new operator, as shown in the examples above, rather than statically allocated on the stack (since they must live on after the functions that send them return).
See also: BLooper::DetachCurrentMessage()
virtual ~BMessage(void)
Frees all memory allocated to hold message data. If the message sender is expecting a reply but hasn't received one, a default reply (with B_NO_REPLY as the what data member) is sent before the message is destroyed.
Don't delete the messages that you post to a thread, send to another application, or assign to another object. Like letters or parcels sent through the mail, BMessage objects become the property of the receiver. Each message loop routinely deletes the BMessages it receives after the application is finished responding to them.
long AddData(const char *name, ulong type, const void *data, long numBytes) long AddBool(const char *name, bool aBool) long AddLong(const char *name, long aLong) long AddFloat(const char *name, float aFloat) long AddDouble(const char *name, double aDouble) long AddRef(const char *name, record_ref aRef) long AddMessenger(const char *name, BMessenger aRef) long AddPoint(const char *name, BPoint aPoint) long AddRect(const char *name, BRect aRect) long AddObject(const char *name, BObject *anObject) long AddString(const char *name, const char *aString)
These functions put data in the BMessage. AddData() copies numBytes of data into the object, and assigns the data a name and a type code. The type must be a specific data type; it should not be B_ANY_TYPE .
AddData() copies whatever the data pointer points to. For example, if you want to add a string of characters to the message, data should be the string pointer ( char *). If you want to add only the string pointer, not the characters themselves, data should be a pointer to the pointer (char **).
The other functions--AddBool(), AddLong() , AddFloat(), and so on--are simplified versions of AddData() . They each add a particular type of data to the message and register it under the appropriate type code, as shown below:
Function | Adds type | Assigns type code |
---|---|---|
AddBool() | a bool | B_BOOL_TYPE |
AddLong() | a long or ulong | B_LONG_TYPE |
AddFloat() | a float | B_FLOAT_TYPE |
AddDouble() | a double | B_DOUBLE_TYPE |
AddRef() | a record_ref | B_REF_TYPE |
AddMessenger() | a BMessenger object | B_MESSENGER_TYPE |
AddPoint() | a BPoint object | B_POINT_TYPE |
AddRect() | a BRect object | B_RECT_TYPE |
AddObject() | a pointer to an object | B_OBJECT_TYPE |
AddString() | a character string | B_STRING_TYPE |
Each of these ten type-specific functions calculates the number of bytes in the data they add. AddString(), like AddData(), takes a pointer to the data it adds. The string must be null-terminated; the null character is counted and copied into the message. The other functions are simply passed the data directly. For example, AddLong() takes a long and AddRef() a record_ref, whereas AddData() would be passed a pointer to a long and a pointer to a record_ref. AddObject() adds the object pointer it's passed to the message, not the object data structure; AddData() would take a pointer to the pointer.
If more than one item of data is added under the same name, the BMessage creates an array of data for that name. Each successive call appends another data element to the end of the array. For example, the following code creates an array named "primes" with 37 stored at index 0, 223 stored at index 1, and 1,049 stored at index 2.
BMessage *msg = new BMessage(NUMBERS); long x = 37; long y = 223; long z = 1049; msg->AddLong("primes", x); msg->AddFloat("pi", 3.1416); msg->AddLong("primes", y); msg->AddData("primes", B_LONG_TYPE, &z, sizeof(long));
Note that entering other data between some of the elements of an array --in this case, "pi"--doesn't increment the array index.
All elements in a named array must be of the same type; it's an error to try to mix types under the same name.
These functions return B_ERROR if the data is too massive to be added to the message, B_BAD_TYPE if the data can't be added to an existing array because it's the wrong type, or B_NO_ERROR if the operation was successful.
See also: FindData(), GetInfo()
long CountNames(ulong type)
Returns the number of named entries in the BMessage that store data of the specified type. An array of information held under a single name counts as one entry; each name is counted only once, no matter how many data items are stored under that name.
If type is B_ANY_TYPE, this function counts all named entries. If type is a specific type, it counts only entries that store data registered as that type.
See also: GetInfo()
long Error(void)
Returns an error code that specifies what went wrong with the last BMessage operation, or B_NO_ERROR if there wasn't an error. It's important to check for an error before continuing with any code that depends on the result of a BMessage function. For example:
float pi = msg->FindFloat("pi"); if ( msg->Error() == B_NO_ERROR ) { float circumference = pi * diameter; . . . }
The error code is reset each time a BMessage function is called that adds, finds, alters, or provides information about message data. It's also reset to B_NO_ERROR whenever Error() itself is called. Cache the return value if you write code that needs to check the current error code more than once.
Possible error returns include the following:
Error code | Is set when |
---|---|
B_NAME_NOT_FOUND | Trying to find, or get information about, data stored under an invalid name |
B_BAD_INDEX | Trying to find, or get information about, data stored at an index that's out-of-range |
B_BAD_TYPE | Attempting to add data of the wrong type to an existing array, or asking about named data of a given type when the name and type don't match |
B_BAD_REPLY | Trying to send a reply to a message that hasn't itself been sent. |
B_DUPLICATE_REPLY | Trying to send a reply when one has already been sent and received |
< B_MESSAGE_TO_SELF | Attempting to send a reply when the source and destination threads are the same > |
B_BAD_THREAD_ID | Attempting to send a reply to a thread that no longer exists |
B_ERROR | Attempting to add too much data to a message |
See also: AddData(), FindData(), HasData() , GetInfo()
void *FindData(const char *name, ulong type, long *numBytes) void *FindData(const char *name, ulong type, long index, long *numBytes) bool FindBool(const char *name, long index = 0) long FindLong(const char *name, long index = 0) float FindFloat(const char *name, long index = 0) double FindDouble(const char *name, long index = 0) record_ref FindRef(const char *name, long index = 0) BMessenger FindMessengerconst char *name, long index = 0) BPoint FindPoint(const char *name, long index = 0) BRect FindRect(const char *name, long index = 0) BObject *FindObject(const char *name, long index = 0) const char *FindString(const char *name, long index = 0)
These functions retrieve data from the BMessage. Each looks for data stored under the specified name. If more than one data item has the same name, an index can be provided to tell the function which item in the name array it should find. Indices begin at 0. If an index isn't provided, the function will find the first, or only, item in the array.
FindData() returns a pointer to the requested data item and records the size of the item (the number of bytes it takes up) in the variable referred to by numBytes. It asks for data of a specified type. If the type is B_ANY_TYPE, it returns a pointer to the data no matter what type it actually is. But if type is a specific data type, it returns the data only if the name entry holds data of that particular type.
It's important to keep in mind that FindData() always returns a pointer to the data, never the data itself. If the data is a pointer--for example, a pointer to an object --it returns a pointer to the pointer. The variable that's assigned the returned pointer must be doubly indirect. For example:
MyClass **object; long numBytes; object = (MyClass **)message->FindData("name", B_OBJECT_TYPE, &numBytes); if ( message->Error() == B_NO_ERROR ) { (*object)->GetSomeInformation(); . . . }
The other functions similarly return the requested item--but do so as a specifically declared data type. They match the corresponding Add...() functions and search for named data of the declared type, as described below:
Function | Finds data | Registered as type |
---|---|---|
FindBool() | a bool | B_BOOL_TYPE |
FindLong() | a long or ulong | B_LONG_TYPE |
FindFloat() | a float | B_FLOAT_TYPE |
FindDouble) | a double | B_DOUBLE_TYPE |
FindRef() | a record_ref | B_REF_TYPE |
FindMessenger() | a BMessenger object | B_MESSENGER_TYPE |
FindPoint() | a BPoint object | B_POINT_TYPE |
FindRect() | a BRect object | B_RECT_TYPE |
FindObject() | a pointer to an object | B_OBJECT_TYPE |
FindString() | a character string | B_STRING_TYPE |
FindString() returns a pointer to a null-terminated string of characters (as would FindData()); it expects the null-terminator to have been copied into the message. The rest of the functions return the data directly, not through a pointer. For example, FindLong() returns a long, whereas FindData() would return a pointer to a long. FindObject() returns a pointer to an object, whereas FindData(), as illustrated above, would return a pointer to the pointer to the object.
If you want to keep the data returned by FindData() and FindString(), you must copy it; it will be destroyed when the BMessage is deleted.
If these functions can't find any data associated with name , or if they can't find data in the name array at index, or if they can't find name data of the requested type (or the type the function returns), they register an error. You can rely on the values they return only if Error() reports B_NO_ERROR and the data was correctly recorded when it was added to the message.
When they fail, FindData(), FindString() , and FindObject() return NULL pointers. FindRect() returns an invalid rectangle and FindRef() returns an invalid record_ref with both data members set to -1. The other functions return values set to 0, which may be indistinguishable from valid values.
Finding a data item doesn't remove it from the BMessage.
See also: GetInfo(), AddData()
void Flatten(char **stream, long *numBytes) void Unflatten(const char *stream)
These functions write the data stored in a BMessage to a "flat" (untyped) stream of bytes, and reconstruct a BMessage object from such a stream.
Flatten() allocates enough memory to hold all the information stored in the BMessage object, then copies the information to that memory. It places a pointer to the allocated memory in the variable referred to by the stream argument, and writes the number of bytes that were allocated to the variable referred to by numBytes. It's the responsibility of the caller to free the memory that Flatten() allocates when it's no longer needed. (Since the stream is allocated by malloc(), call free() to get rid of it.)
Unflatten() empties the BMessage of any information it may happen to contain, then initializes the object from information stored in stream. The pointer passed to Unflatten() must be to the start of a stream that Flatten() allocated and initialized. Neither function frees the stream.
bool GetInfo(const char *name, ulong *typeFound, long *countFound = NULL) bool GetInfo(ulong type, long index, char **nameFound, ulong *typeFound, long *countFound = NULL)
Provides information about the data entries stored in the BMessage.
When passed a name that matches a name within the BMessage, GetInfo() places the type code for data stored under that name in the variable referred to by typeFound and writes the number of data items with that name into the variable referred to by countFound. It then returns TRUE. If it can't find a name entry within the BMessage, it registers an error, sets the countFound variable to 0, and returns FALSE (without modifying the typeFound variable).
When passed a type and an index, GetInfo() looks only at entries that store data of the requested type and provides information about the entry at the requested index. Indices begin at 0 and are type specific. For example, if the requested type is B_LONG_TYPE and the BMessage contains a total of three named entries that store long data, the first entry would be at index 0, the second at 1, and the third at 2 --no matter what other types of data actually separate them in the BMessage, and no matter how many data items each entry contains. (Note that the index in this case ranges over entries, each with a different name, not over the data items within a particular named entry.) If the requested type is B_ANY_TYPE, this function looks at all entries and gets information about the one at index whatever its type.
If successful in finding data of the type requested at index , GetInfo() returns TRUE. It provides information about the entry through the last three arguments:
If GetInfo() can't find data of the requested type at index, it registers an error, sets the countFound variable to 0, and returns FALSE.
This version of GetInfo() can be used to iterate through all the BMessage's data. For example:
char *name; ulong type; long count; for ( long i = 0; msg->GetInfo(B_ANY_TYPE, i, &name, &type, &count); i++ ) { . . . }
If the index is incremented from 0 in this way, all data of the requested type will have been read when GetInfo() returns FALSE. If the requested type is B_ANY_TYPE, as shown above, it will reveal the name and type of every entry in the BMessage.
See also: HasData(), AddData(), FindData()
bool HasData(const char *name, ulong type, long index = 0) bool HasBool(const char *name, long index = 0) bool HasLong(const char *name, long index = 0) bool HasFloat(const char *name, long index = 0) bool HasDouble(const char *name, long index = 0) bool HasRef(const char *name, long index = 0) bool HasMessengerconst char *name, long index = 0) bool HasPoint(const char *name, long index = 0) bool HasRect(const char *name, long index = 0) bool HasObject(const char *name, long index = 0) bool HasString(const char *name, long index = 0)
These functions test whether the BMessage contains data of a given name and type.
If type is B_ANY_TYPE and no index is provided, HasData() returns TRUE if the BMessage stores any data at all under the specified name, regardless of its type, and FALSE if the name passed doesn't match any within the object.
If type is a particular type code, HasData() returns TRUE only if the BMessage has a name entry that stores data of that type. If the type and name don't match, it returns FALSE.
If an index is supplied, HasData() returns TRUE only if the BMessage has a name entry that stores a data item of the specified type at that particular index. If the index is out of range, it returns FALSE.
The other functions--HasBool(), HasFloat() , HasPoint(), and so on--are specialized versions of HasData(). They test for a particular type of data stored under the specified name.
An error code is set (which Error() will return) whenever any of these functions returns FALSE.
See also: GetInfo()
bool IsSystem(void)
Returns TRUE if the what data member of the BMessage object identifies it as a system- defined message, and FALSE if not.
Unlike the GetInfo() and HasData() functions, a return of FALSE does not indicate an error. IsSystem() resets the error code that Error() returns to B_NO_ERROR whether the BMessage is a system message or not.
long MakeEmpty(void) bool IsEmpty(void)
MakeEmpty() removes and frees all data that has been added to the BMessage, without altering the what constant. It returns B_NO_ERROR .
IsEmpty() returns TRUE if the BMessage has no data (whether or not it was emptied by MakeEmpty()), and FALSE if it has some.
Both functions reset the error code to B_NO_ERROR in all cases.
See also: RemoveName()
void PrintToStream(void) const
Prints information about the BMessage to the standard output stream ( stdout). Each entry of named data is reported in the following format,
#entry name, type = type, count = count
where name is the name that the data is registered under, type is the constant that indicates what type of data it is, and count is the number of data items in the named array.
bool RemoveName(const char *name)
Removes all data entered in the BMessage under name, frees the memory that was allocated to hold the data, and returns TRUE. If there is no data entered under name, this function registers an error (B_NAME_NOT_FOUND) and returns FALSE.
See also: MakeEmpty()
long ReplaceData(const char *name, ulong type, const void *data, long numBytes) long ReplaceData(const char *name, ulong type, long index, const void *data, long numBytes) long ReplaceBool(const char *name, bool aBool) long ReplaceBool(const char *name, long index, bool aBool) long ReplaceLong(const char *name, long aLong) long ReplaceLong(const char *name, long index, long aLong) long ReplaceFloat(const char *name, float aFloat) long ReplaceFloat(const char *name, long index, float aFloat) long ReplaceDouble(const char *name, double aDouble) long ReplaceDouble(const char *name, long index, double aDouble) long ReplaceRef(const char *name, record_ref aRef) long ReplaceRef(const char *name, long index, record_ref aRef) long ReplaceMessenger(const char *name, BMessenger aMessenger) long ReplaceMessenger(const char *name, long index, BMessenger aMessenger) long ReplacePoint(const char *name, BPoint aPoint) long ReplacePoint(const char *name, long index, BPoint aPoint) long ReplaceRect(const char *name, BRect aRect) long ReplaceRect(const char *name, long index, BRect aRect) long ReplaceObject(const char *name, BObject *anObject) long ReplaceObject(const char *name, long index, BObject *anObject) long ReplaceString(const char *name, const char *aString) long ReplaceString(const char *name, long index, const char *aString)
These functions replace a data item in the name entry with another item passed as an argument. If an index is provided, they replace the item in the name array at that index; if an index isn't mentioned, they replace the first (or only) item stored under name. If an index is provided but it's out-of-range, the replacement fails.
ReplaceData() replaces an item in the name entry with numBytes of data, but only if the type code that's specified for the data matches the type of data that's already stored in the entry. The type must be specific; it can't be B_ANY_TYPE.
The other functions are simplified versions of ReplaceData() . They each handle the specific type of data declared for their last arguments. They succeed if this type matches the type of data already in the name entry, and fail if it does not.
If successful, all these functions return B_NO_ERROR . If unsuccessful, they register and return an error code--B_BAD_INDEX if the index is out-of-range, B_NAME_NOT_FOUND if the name entry doesn't exist, or B_BAD_TYPE if the entry doesn't contain data of the specified type.
See also: AddData()
long SendReply(BMessage *message, BMessage **reply) long SendReply(ulong command, BMessage **reply) long SendReply(BMessage *message, BHandler *replyTarget = NULL) long SendReply(ulong command, BHandler *replyTarget = NULL)
Sends a reply message back to the sender of the BMessage (in the case of a synchronous reply) or to a target BHandler (in the case of an asynchronous reply). Whether the reply is synchronous or asynchronous depends on how the message it replies to was sent:
SendReply() works only for BMessage objects that have been processed through a message loop and delivered to you. However, it doesn't work for messages that were posted to the loop, only for those that were sent or dragged. If it's called when a reply isn't allowed, the message is deleted and an error is recorded.
The message that's passed to SendReply() should not be modified, passed to another messaging function, used as a model message, or deleted. It becomes the responsibility of the messaging service and the eventual receiver.
If a command is passed rather than a message, SendReply() constructs the reply BMessage, initializes its what data member with the command constant, and sends it just like any other reply.
If you want to delay sending a reply and keep the BMessage object beyond the time it's scheduled to be deleted, you may be able to detach it from the message loop. See DetachCurrentMessage() in the BLooper class.
SendReply() sends a message--a reply message, to be sure, but a message nonetheless. It therefore is just another message-sending function. It behaves exactly like the other message-sending function, BMessenger's SendMessage():
This function returns B_NO_ERROR if the reply is successfully sent. If not, it returns one of the error codes explained under the Error() function.
See also: BMessenger::SendMessage(), BLooper::DetachCurrentMessage(), WasSent() , Error()
bool WasDropped(void) BPoint DropPoint(BPoint *offset = NULL)
WasDropped() returns TRUE if the user delivered the BMessage by dragging and dropping it, and FALSE if the message was posted or sent in application code or if it hasn't yet been delivered at all.
DropPoint() reports the point where the cursor was located when the message was dropped (when the user released the mouse button). It directly returns the point in the screen coordinate system and, if an offset argument is provided, returns it by reference in coordinates based on the image or rectangle the user dragged. The offset assumes a coordinate system with (0.0, 0.0) at the left top corner of the dragged rectangle or image.
Since any value can be a valid coordinate, DropPoint() produces reliable results only if WasDropped() returns TRUE.
See also: BView::DragMessage()
bool WasSent(void) bool IsSourceRemote(void) bool IsSourceWaiting(void) bool IsReply(void) BMessage *Previous(void) BMessenger ReturnAddress(void)
These functions can help if you're engaged in an exchange of messages or managing an ongoing communication.
WasSent() indicates whether it's possible to send a reply to a message. It returns TRUE for a BMessage that was sent or dropped, and FALSE for a message that was posted or has not yet been delivered by any means. (When, in a future release, it's possible to reply to a posted message, this function would be more clearly named WasDelivered() .) Regardless of the return value, WasSent() sets the current error code to B_NO_ERROR.
IsSourceRemote() returns TRUE if the message had its source in another application, and FALSE if the source is local or the message hasn't been delivered yet. It resets the error code to B_NO_ERROR in both cases.
IsSourceWaiting() returns TRUE if the message sender is waiting for a synchronous reply, and FALSE if not. The sender can request and wait for a reply when calling either BMessenger's SendMessage() or BMessage's SendReply() function.
IsReply() returns TRUE if the BMessage is a reply to a previous message (if it was sent by the SendReply() function), and FALSE if not. It resets the error code to B_NO_ERROR in either case.
Previous() returns the previous message, or NULL if the BMessage isn't a reply.
ReturnAddress() returns a BMessenger that can be used to reply to the BMessage. Calling the BMessenger's SendMessage() function is equivalent to calling SendReply() , except that the return message won't be marked as a reply. If a reply isn't allowed (if the BMessage wasn't sent or dropped), a B_BAD_VALUE error is registered to indicate that the returned BMessenger is invalid. Call Error() to check. If the BMessenger is valid, Error() will return B_NO_ERROR.
If you want to use the ReturnAddress() BMessenger to send a synchronous reply, you must do so before the BMessage is deleted and default reply is sent.
See also: BMessenger::SendMessage(), SendReply()
void *operator new(size_t numBytes)
Allocates memory for a BMessage object, or takes the memory from a previously allocated cache. The caching mechanism is an efficient way of managing memory for objects that are created frequently and used for short periods of time, as BMessages typically are.
void operator delete(void *memory, size_t numBytes)
Frees memory allocated by the BMessage version of new , which may mean restoring the memory to the cache.
The Be Book, HTML Edition, for Developer Release 8 of the Be Operating System.
Copyright © 1996 Be, Inc. All rights reserved.
Be, the Be logo, BeBox, BeOS, BeWare, and GeekPort are trademarks of Be, Inc.
Last modified September 6, 1996.