Note: There is a mailing list that gets notification of new annotations on the Be Book. The idea is that people can discuss annotations, suggest improvements, and make yet more annotations! To subscribe, send mail to listar and say subscribe bebook in the subject line or body.
status_t GetPreferredApp(char *signature, app_verb verb = B_OPEN) constWhen there is no preferred app, you're supposed to get a NULL char *. That seems broken.The function does however return B_ENTRY_NOT_FOUND.
There's an additional constructor in the header that acts as a copy-constructor: BBitmap(BBitmap *).
GetIcon(), GetTrackerIcon don't tell you what BBitmap they require: 16x16 in B_CMAP8-colorspace, so that's a BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_CMAP8).see BMimeType::GetIcon() , SetIcon() where the Bitmap is specified.
BNodeInfo::GetPreferredApp() returns garbage, while BMimeType::GetPreferredApp() works fine.As a workaround, you can use BNodeInfo::GetType() and create a BMimeType-instance with the type, which calls GetPreferredApp().
Menu controls as labels:If you plan on using a pop-up menu for a label, ala the screen prefs window, make certain you use the BMenuField object. It'll save you the trial-and-error time of testing BMenu, BMenuBar, and BPopUpMenu.
OpenViewTransaction() and CloseViewTransaction() do not exist. Use the similar Begin- and End-() methods found in the headers instead.
The serial port driver in R5 is broken and will allow a serial port to be opened multiple times. This means that opening a BSerialPort will always succeed, but you'll be "sharing" the port with every other application that opened it!An alternative viewpoint is that this is the right behaviour, and that you should use O_EXCL mode if you want exclusive use of the serial port. In that case, BSerialPort is broken, because it does not do that (probably because at one point, a serial port really couldn't be opened more than once).
To work around this, you should try opening the serial port first in exclusive mode, to test if it's already being used. If it's not, you can close it again and open the BSerialPort. There is still a race-condition there, but it's better than nothing.
In the Play() function, the table lists items 15 and 16 as "RESERVED", this is not true, these are used for BShape drawing.The functions look like:
StrokeShape(void* user, BShape* shape);
and
FillShape(void* user, BShape* shape);
The book says that the Clipping Region for a view is only active when the view is attached to a window. It does also clip views attached to a Bitmap.
The book says...
Currently, GetNextDirents() only reads one dirent at a time, no matter how many you ask for.Actually, it does work. It's just that most underlying file systems only handle finding one directory entry at a time. For ones which do handle multiples (like AGMSRAMFileSystem), you need to use the d_reclen field and add it to the start of the first entry to get to the next entry in the buffer (the entries are variable sized - depending on the length of the file name and padding). Note that most of the ones which handle only 1 dirent set the d_reclen to inappropriate values.
dprintf also doesn't print octal numbers, so %o does nothing (not even print out an o). Not too important, except for conveniently printing out file permission bits (that rwxrwxrwx stuff).
in this exemple :WRONG : if (modifiers() | B_SHIFT_KEY) { /* a shift key is down */ }
you must change the OR ( | ) per AND ( & ) with or that will never working
GOOD : if (modifiers() & B_SHIFT_KEY) { /* a shift key is down */ }
When a BScrollView is resized, you may see some visual bugs, mostly with the focus (if any) rectangle. To fix this, don't forget to set B_WILL_DRAW and B_FRAME_EVENTS flags in the scrollview constructor:BListView * lv; BScrollView * sv; BRect rlv;rlv = Bounds();
rlv.right -= B_V_SCROLL_BAR_WIDTH;
lv = new BListView(rlv, "my_list", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES); sv = new BScrollView("my_list_scrollview", lv, B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS, false, true);
Uniqueness of Data, aka, why my first post was wrongIt turns out that BMessage's data is uniquely identified by *name* and not type. The BeBook isn't too clear on this. From the AddData() section:
These functions return ... B_BAD_TYPE if the data can't be added to an existing array because it's the wrong type...
Perhaps I just completely got the wrong idea into my head, but in case its not spelled out somewhere else, this subtle hint does mean that you cannot have two fields with the same name and different types, whether or not the first or second is indexed with multiple values. Each name, therefore, can be used to uniquely identify the fields involved (index optional).
Therefore, my first comment about orthogonal functions is incorrect, as the functions are as orthogonal as necessary (and possible).
RemoveName(), RemoveData() - indices are compacted as you remove them to keep them all contiguous and sequential. That is, if you remove index 2 out of 5, you now have data available at indicies 0, 1, 2, and 3. Smells like BList?
BMessage: Orthogonal functions, please!In case you're ever doing something very funky in terms of manipulating data, and you're considering using a BMessage as your data container, be aware that there are some inconsistencies with the functions that may give you a headache. The BeBook plainly states that fields are identified by type and name, and alternately, index. This level of specificity is supported for our favorite functions: Add...(), Find...(), Replace...(). However, for Remove...(), and GetInfo(), its a serious pain in the ass to find the exact same field you were talking about in the other functions. Just a warning - check it out before you end up writing an annoying wrapper layer to consistently manipulate the data.
Append vs. Output Operator <<I've run into trouble using the output operator with character strings (const char*). The following:
char output[50]; sprintf(output, "%d", 3.5 ); stringdata<
The B_QUIT_ON_WINDOW_CLOSE flag should work with R5.
Constructor:All arguments are copied, even though The Book isn't too specific about it. Specifically, the entry_ref and BMessengers are copied.
The book says "If the thread count is positive, the semaphore is available and the current acquisition succeeds." Shouldn't that be "If the thread count is >= the decrement value..." so that acquiring a semaphore with a decrement larger than 1 will wait until the count has gotten big enough? Otherwise the trick for allowing multiple readers and just one writer, which works by initialising the semaphore to N, having readers use a decrement of 1 and writers a decrement of N, just won't work.
MessageReceived() - I hope this isn't a big rehash for everyone, but after months of development I've just discovered a way to get everybody's favorite compiler to stop complaining when you declare variables inside a switch() statement. This is quite common in MessageReceived(), when handling a response to some incoming message. You cannot declare any new variables within the case statement itself, instead, you have a number of options:1) move all variable declarations up to the top of the switch() block, even those that conditionally aren't going to be used (no fun).
2) Branch out using an unobtrusive function call. I prefer inlining these functions, so I do end up a whole block of "inline void" functions that start with "Handle...". This gets really annoying when adding many cases. Your code ends up looking like:
case SOME_CASE_HERE: HandleSomething(msg); break;3) Use a block. This starts a new scope and GCC will be quiet if you declare variables within it. Your code looks like this:
case SOME_CASE_HERE: { //block brackets ... } break;I like option #3 - it saves you a lot of function declarations.
The EnqueueMessage() function actually takes possestion of the message you pass it, so do not try to delete it your self, or use a stack based BMessage instance with it.
If you have a media_raw_audio_format instance and want to make a media_format out of it, do the following:
format.type=B_MEDIA_RAW_AUDIO;
memcpy(&format.u.raw_audio, &raw_format, sizeof(media_raw_audio_format));
You can't use format.u.raw_audio=raw_format because format.u.raw_audio is actually a media_multi_audio_format and there is no assignment operator and no cast-operator to cast the right-hand side of the assignment. The bad thing is that casting the left-hand side of the assignment does compile, but doesn't work: the data doesn't get copied.
Since BTimedEventQueue only cleans up events when they are flushed and since BMediaEventLooper's control loop removes events from the event queues after they are handled by HandleEvent, the HandleEvent function has to clean up any events it handles. That means: it has to Recycle incoming buffers and it should clean up user events. You can call the virtual CleanUpEvent function to clean up user events, but you have to explicitly call Recycle to recycle a buffer (i.e. there is no way to clean up standard events).
Important: events are only "cleaned up" when they are flushed from a BTimedEventQueue. When an event is Removed, the cleanup code in the event is ignored.
Important: events are only "cleaned up" when they are flushed from a BTimedEventQueue. When an event is Removed, the cleanup code in the event is ignored.
Power PC systems are on fire for one second every 256 seconds. Intel systems of course are never on fire... :)
Don't call SetRunMode directly inside your node's code to change the current run mode. You need to call BMediaRoster::SetRunModeNode to do that. If you call your hook-function directly, the actual run mode will remain unchanged (calling hook-functions directly without help from the Media Roster is always a Bad Thing (TM)).
The notification messages received after calling BRoster::StartWatching() have the following fields:be:signature be:team be:thread be:flags be:ref
The GetNextOutput function must initialize the media_destination of the output to media_destination::null if the output is not connected to another media node. Just filling the media_destination with 0 is not sufficient.
The GetNextInput function must initialize the media_source of the input to media_source::null if the input is not connected to another media node. Just filling the media_source with 0 is not sufficient.
The GetFreeInputsFor and GetFreeOutputsFor functions respectively check for inputs/outputs that have their source/destination set to media_source::null/media_destination::null. Note that media_source::null and media_destination::null (contrary to what their name suggests) are NOT equal to a media_source/media_destination filled with 0.
The FormatProposal() function is not only called when connecting two nodes, but also when you call BMediaRoster::GetFormatFor with a media_output as parameter.FormatSuggestionRequested() is called when you call BMediaRoster::GetFormatFor with a media_node as parameter. By the way, the media_audio_format::wildcard and media_video_format::wildcard that are mentioned in the documentation for this function are really data, not functions.
The AcceptFormat function is not only called during connection of two nodes, but also when you call BMediaRoster::GetFormatFor() with a media_input as parameter.
Somewhere in the Be Book the BMediaRoster::SetOutputBuffersFor function is mentioned. This function has moved to BBufferConsumer
In BBufferConsumer::BufferReceived(), it is mentioned that your node may receive small buffers and you should recycle them before the function returns. This is confusing; after all small buffers don't ever belong to a Buffer Group so why should you recycle them?Answer: Small buffer objects that your BufferReceived hook-function receives, are destroyed after you return. So the remark really should be: if you receive a small buffer, you should handle it immediately before your BufferReceived function returns. If you derive from BMediaEventLooper, you cannot generate a B_HANDLE_BUFFER event and add it to the event queue, because the pointer to the buffer will be invalid once your HandleEvent function finds it. What you CAN do if you want to use HandleEvent to handle the buffer, is call DispatchEvent from your BufferReceived function if the incoming buffer is a small one. That function calls your HandleEvent hook-function so that small buffers can be handled in the same way as large ones. Before you call DispatchEvent, you need to use BTimeSource::SnoozeUntil to wait for the performance time of the buffer.
And for future compatibility, you should still call Recycle() on the buffer in BufferReceived, if it's a small buffer (like the Be Book says).
Something that the Be Book doesn't mention is that most hook-functions in the media kit are called with pointers that are guaranteed to be non-NULL. This is because the pointers that are passed to the functions, usually point into fixed-length structs that are used internally to pass data between nodes. In many code-examples on the Be website, almost no checks for NULL-pointers appear, and this is not just to simplify the example but also because it's not really necessary.
oops... here's that comment one more time...The HandleMessage() function mentions that you should call the HandleMessage function of BBufferProducer, BBufferConsumer and BMediaNode, and call the HandleBadMessage function if no-one can handle the message.
Actually this is not really necessary if your control loop uses WaitForMessage() or if you subclass your node from BMediaEventLooper (which uses WaitForMessage it its control loop): the WaitForMessage function knows how to dispatch messages to media nodes; your media node will only have to handle messages that no other class that you derive your node from, understands.
Of course that also means you can't intercept messages that are meant to be received by other classes that you derive from.
The WaitForMessage() or if you subclass your node from BMediaEventLooper (which uses WaitForMessage it its control loop): the WaitForMessage function knows how to dispatch messages to media nodes; your media node will only have to handle messages that no other class that you derive your node from, understands.Of course that also means you can't intercept messages that are meant to be received by other classes that you derive from.
BMediaNode::GetNodeAttributes() should really return the number of attributes that your hookup function filled in; returning B_OK would tell BeOS that you filled in 0 attributes.
DEBUG_ONLY( expression ) doesn't pay attention to whether SET_DEBUG_ENABLED() was set to true or false, so if this is your first time using this macro, you may be confused that "expression" is evaluated any time DEBUG is defined.To allow DEBUG_ONLY to function when PRINT does, you need to write the code: DEBUG_ONLY( if(IS_DEBUG_ENABLED()) { expression } );
How does one change the font size of all the menu items in a menu? Do you have to derive a class, and redefine Draw() or something?
That didn't work out so well....media_node is actually declared in MediaNode.h, not in MediaDefs.h
media_node is actually declared innot in
Beware, SetScale() seem to miswork when use on a bitmap child view.
If you want to print 64 bit integers with dprintf, the printf standard "%qd" won't work, but you can use "%Ld" instead (note the capital L).
The sample code for GetSupportingApps is incorrect (although the documentation is correct). Instead of:message.FindInt32("be:subs", &subs); message.FindInt32("be:supers", &supers);
it should be:message.FindInt32("be:sub", &subs); message.FindInt32("be:super", &supers);
On german keyboards there is a key labelled "<" and ">" between the left shift key and the Y. Its code is 0x69.
Remember, you want to add a BView to a BTab then add the BTab to a BTabView .. I have seen people get caught on this many times.
GetInstalledSupertypes() actually return the types in the "super_types" field of the passed in BMessage.
The network add-on API is at http://www-classic.be.com/documentation/be_book_r3/The%20Network%20Kit/. One warning: do NOT subclass BStandardPacket. If you do, bad things happen.
After writing my AGMSDeviceTest program (see BeBits.com), I figured out what the standard IOCtl operations do and added descriptions. Here's the list:
Standard IOCtl Codes and Their Meanings Name IOCtl # Data Size Description B_GET_DEVICE_SIZE 1 4 Returns a size_t in *Data with the device size in bytes. Obsolete, not 64 bits! Use B_GET_GEOMETRY instead and do the 64 bit math. B_SET_DEVICE_SIZE 2 4 Sets the device size (in bytes) to the size_t value pointed to by *Data. Probably obsolete since it's only 32 bits. Good for RAM disks I guess, since they use 32 bit pointers. B_SET_NONBLOCKING_IO 3 0 Sets the device to use nonblocking I/O (calls return immediately rather than waiting for the IO operation to complete). B_SET_BLOCKING_IO 4 0 Sets the device to use blocking I/O (calls to the driver return only once the operation is complete). B_GET_READ_STATUS 5 1 Returns a true bool in *Data if the device can read without blocking, otherwise sets *Data to false. I presume for blocking mode, this means true if there is some data ready in the buffers for you to read. B_GET_WRITE_STATUS 6 1 Returns a true bool in *Data if the device can write without blocking, otherwise sets *Data to false. I presume for blocking mode this means true if there are some empty intermediate buffers ready to receive your data. B_GET_GEOMETRY 7 20 Gets the device geometry (sector size / sectors / tracks / heads) and other characteristics of the device and writes it into the device_geometry structure the caller provided at *Data. If media isn't present, sizes could be zero. B_GET_DRIVER_FOR_DEVICE 8 256 Writes the path of the driver executable handling this device into the buffer the caller provided in *Data. Note that the header defines a buffer smaller than B_PATH_NAME_LENGTH (1024) for some reason. B_GET_PARTITION_INFO 9 284 Returns a partition_info structure for the device in *Data, fortunately it uses 64 bit values. The DevFS does this for you, making fake devices for partitions, so the driver writer doesn't have to handle this message. Only works when you use it on the partition's file: if your device is */raw, then */S_P (S is session, P is partition) are the partition files. For example */0_0 for the first partition, */0_1 for the second and so on. B_SET_PARTITION 10 284 Finishes setting up a user-defined partition. *Data points to a partition_info structure, fortunately with 64 bit values. The DevFS makes fake devices for partitions, when you "creat()" the */S_P file, where S is a session number (mostly for multisession CD-ROMs, else 0) and P is the partition number (0 & upwards). Then use this IOCtl operation to set the size and offset of the partition, with the device name field set to your */raw device. Note that sizes may have to be a multiple of cylinder size. See the article http://www-classic.be.com/aboutbe/benewsletter/volume_II/Issue23.html for details. B_FORMAT_DEVICE 11 1 Low level formats the device. This can erase everything, watch out! *Data points to a bool: true for full format, false for a quick format (device should test for presence of an existing format by attempting to read the first & last sectors, then do a full format if errors were encountered). B_EJECT_DEVICE 12 0 Ejects the media from the device. For CD-ROMs this means opening the tray or otherwise popping out the CD. You can guess what this does for Internet toasters. B_GET_ICON 13 8 Gets a graphic icon from the device. The device will use the device_icon structure pointed to by *Data to get the size desired (square icons this many pixels wide, usually 16 or 32) and the buffer to write the icon bitmap to (B_CMAP8 style bitmap). B_GET_BIOS_GEOMETRY 14 20 Fills out the device_geometry structure pointed to by *Data with a description of the device as the BIOS sees it. I presume it's mostly for disk type devices used during bootup, also may be needed when making partitions on a disk device. B_GET_MEDIA_STATUS 15 4 Writes the media status (ready, empty drive, door open, ...) into the status_t pointed to by *Data. Also clears the media changed flag, so read / write calls will start working again rather than returning B_DEV_MEDIA_CHANGED. B_LOAD_MEDIA 16 0 Loads the media into the drive. For CD-ROMs this closes the tray or sucks in the CD. May also be useful for Internet toaster appliances. Also see is_computer_on_fire(). B_GET_BIOS_DRIVE_ID 17 1 Returns the BIOS ID for disks in a single byte. $80 is usually the C: boot drive. B_SET_UNINTERRUPTABLE_IO 18 0 Prevents control-C and I presume other signals from interrupting I/O (well, maybe not SIGTERM?). The call to read/write will return when it is finished, not any earlier. B_SET_INTERRUPTABLE_IO 19 0 Allows control-C and I presume other signals to interrupt I/O. I presume that means that a call to read/write which is waiting for data can return with partial data or a B_INTERRUPTED error code or both (probably best to not do both since the C read() API can't represent both). B_FLUSH_DRIVE_CACHE 20 0 Flushes cached data from internal caches and lower level hardware caches to the actual media, then returns. This guarantees that your data has actually been written. Useful to do just before shutting off the power. B_GET_NEXT_OPEN_DEVICE 1000 260 Iterates through open devices. *Data points to an open_device_iterator structure which gives you a name for each open thing. Set the cookie to zero to start. Seems to only work if you apply it to /dev, giving you a list of all loaded devices. B_DEVICE_OP_CODES_END 9999 0 User defined control codes follow this one.
The above reference should probably be to SetFontSize()...
BFont::SetSize() makes a misleading refrence to "See also: BView::SetSize()", which, of course, does not exist. This will take about 10 minutes to find out using the BeBook (due to the whack nature of the BView section of the BeBook). If you look in the BView header, however, it is readily apparent.Makes one wonder what it was really referring to...
There are other attributes that are understood (some even required) by Tracker:
- attr:width : B_INT32_TYPE : default display width
- attr:alignment : B_INT32_TYPE : alignment (0=left, 1=right?)
- attr:viewable : replaces attr:public
- attr:extra : boolean : not sure what it's used for
The function tint_color() also seems to be undocumented.
It'd be nice if the spawn_thread() description linked to the Thread Priority Values instead of just mentioning it...
There appears to be a new undocumented function ItemAtFast(uint32).This function looks to be doing unchecked access to items in the list, that is, it does not make sure that the index that you pass is valid before trying to give you back the item.
So use this when you know how big the list is and want quick access, but be careful, it could cause a crash if you spin off the end.
There's some nice information on kernel and device driver programming at BeDriven. Some of it is in a language I don't parse (much less understand) but most of it is good, useful information collected from many sources (bedevtalk, the Be Book, newsletter articles, etc).
The description of write_hook() is misleading:write_hook()'s final argument should be size_t *len, and it should say that you return B_OK AND set *len to the amount of data writen, unless an error occurs in which case you return an error.
The description is correct in stating that it is not an error to write fewer bytes than requested. In this case you return B_OK (not an error) and set *len to the amount of data actually writen.
#It is not discussed what value comes back when this function fails. [...] #What, in fact, happens, is that you are returned a negative value #when it fails.The standard idiom when dealing with most, if not all, functions in the Be kits is:
ret = foo(); if (ret < B_OK) fprintf(stderr, "Damn. %s!", strerror(ret));So checking for B_ERROR in particular is not the goal (as there are many errors other than the generic B_ERROR which must be somehow indicated); instead check if the return values was "less than OK". Really a rather nice idiom if you ask me...
Watch out! SetTarget() is documented as accepting new targets either before or after the control has been attached to a window. In my experience, the earliest you can set a control's target is in AttachedToWindow().However, the control I'm working with is a liblayout class which derives from BTextControl, so perhaps I'm hitting a bug in liblayout.
Concerning load_add_on():It is not discussed what value comes back when this function fails. A curory look at the documentation would suggest that B_ERROR would be returned, but this is not the case.
What, in fact, happens, is that you are returned a negative value when it fails.
What this value means is a mystery to me, if I find out, you will be the first to know.
Regarding BFil::Seek().So there are these constants SEEK_END etc. however they are not defined in File.h, or Node.h or PositionIO.h, and there is no mention on this page (that I can find) of where they might be.
They are, in fact, in stdio.h. Who knew?
OK, last one, I promise.The *WatchingAll() functions work in conjunction. That is, StartWatchingAll() will watch everything, and StopWatchingAll() will stop that operation.
It does not work to watch specific constants and then use StopWatchingAll() to stop. You have to explicitly stop watching any explicity specified constants.
More news on the *Watching set of functions. It appears that the semantics of the functions is reversed when dealing with BHandler vs BMessenger, so if you are wanting to use a BHandler pointer the description is correct and you have to use the watched BHandler's pointer to call the function and pass in the watcher's pointer. weird.Information courtesy of Dianne Hackborn of Be Inc.
Any incorectness in this is my fault. =)
The function ui_color() seems undocumented, though obvious. Look in the global constants section of the UI refrence for the color_which constants.
There are a few things about the documentation for the Observer/Watcher functions that seem to need better clarification.1) SendNotices()
Is only described in the Release Notes for some reason.
It says that the 'what' param of the message sent to SendNotices gets clobbered, this is only partly true, the _copy_ of the message's what param getts clobbered, the original is stays the same.
2) StartWatching()
The wording states" ... registers the BMessenger or BHandler specified by watche to be notified whenever the state specified by what changes."
What I really think this means is that this function registers this to be notified when the watcher uses SendNotices() specifying what.
I think perhps there should be a column in the BMessage describing this if there is not already.
You will need to lock your looper if its running. A better way to do this is to call SetDivider before AddChild.
You will need to lock your looper if its running. A better way to do this is to call SetDivider before AddChild.
How to make the string half of the TextControl not clip at high sizes:
--
BTextControl *field = new BTextControl(..., "Left Text", ...);
AddChild(field);
field->SetDivider(be_plain_font->StringWidth("Left Text##"));
--
Tip numero uno: NEVER use just a pixel value for SetDivider(). Always check against be_plain_font so that the user can change the font size at will and have nothing clip.
How to make the string half of the MenuField not clip at high sizes: -- BMenuField *field = new BMenuField(..., "Left Text", ...); AddChild(field); field->SetDivider(be_plain_font->StringWidth("Left Text##")); -- Tip numero uno: NEVER use just a pixel value for SetDivider(). Always check against be_plain_font so that the user can change the font size at will and have nothing clip.
In my expierence it has been shown that you cannot create a window in one thread, and then call the first Show() (for window startup) in another.If you want to start up a window but not show it at the same time, use a Hide() call before the first Show() call, this will cause it to not show up, but still start.
The control hook function for a disk drive sometimes receives an unknown function, the value of the function equals 10199. I don't know it's purpose is, I just return a value of B_OK, and it seems to work fine.
Watch out! One of the AddItem calls is deprecated. Take a look at the Release Notes.
Trey Boudreau pointed out this useful bit of info:Note a missing bit of info about create_pool(): it does NOT fix the size of the pool at creation time. The size parameter specifies the MINIMUM increase in the size of the pool when it can't satisfy a malloc() or realloc(). Since it allocates memory out of areas, and the kernel sizes areas in multiples of B_PAGE_SIZE (4096 bytes, currently), the module will round up the size increase to the next multiple of B_PAGE_SIZE.
When init_driver() returns an error, the driver is unloaded, without calling uninit_driver(). So free your resources before you return an error!
Ports don't work right (at all) between kernel and user space in my experience.
Keep in mind that BWindow Screen will probably be deprecated in a future BeOS release. The "de facto" API for high performance graphics will be OpenGL.
There is an inaccuracy on how to use the "Debug tools". It IS possible to "#define DEBUG" in the IDE. Just add "-DDEBUG" in the "Enter additional desired gcc options:" field.
Thanks to Tony "Zippy" Martinez for the excellent new transparent warning icons that appear throughout the Be Book.
BFont::SetFace()The B_UNDERSCORE_FACE and B_STRIKEOUT_FACE are not implemented. B_ITALIC_FACE and B_BOLD_FACE are. Not sure about the others.
You can however use values returned by BFont::GetHeight() to draw your own underline/strikeout.
BFont::BoundingBox() returns a BRect which corresponds to an idealized 1-point font. You have to multiply the Rect by the point size to use it for layout...
Concerning the be_app_messenger global pointer. It is not a pointer.From Application.h
extern _IMPEXP_BE BMEssenger be_app_messenger;
One thing I have noticed about BView::SetViewCursor() is that it will not work in the constructor, AttachedToWindow(), AllAttached(), or WindowActivated(). Sheesh! In fact, the only place that it seems to work to use SetViewCursor() is in MouseMoved().
This kit is very out of date. Please use the Midi2 Kit to ensure compatiablity with other midi applications. Sadly, we don't have any Midi2 Kit documentation, so look at the headers, and patchbay example on Be's ftp site.
inspite of what the documentation for SetMenu says the menu actually used in the input server menu doesn't seem to be the menu you own if you change it(the menu you own) the change will not come into effect until you call SetMenu again - the only conclusion i came to is that the input server copies the menu
Beware... as of yet, BTabView's tabs are not font-sensitive. You might want to look into a better, third-party solution that is font-sensitive instead of using this one.
Remember to always put your BTextViews inside BScrollViews. The BScrollView is what adds that cool-looking bevel to the outside. So, use BScrollView even if you don't want to have it scroll.
For a background view (which just is painted gray and holds other controls), try using a BBox. For the bounds, take the window Bounds() and InsetBy(-1, -1). Doing this will make your dialog look classier and more professional.
Make sure to ALWAYS call ResizeToPreferred() on your buttons so that the text doesn't clip and the buttons are the correct size. Nothing worse than a hard-coded button size.
There is an extension to the BString class in the OpenTracker project, called TrackerString. It contains some pattern matching and more search facilities. It also fixes some bugs in the case-insensitive Find*() functions in R5.
minfo->configure(0, 10); Does not work for me. So far the code seem to needed to be written as: (*minfo->configure)(0, 10); Comments?