Be Developers' Conference Approaching Be Apps Doug Wright |
Mr. Kimpton: My turn to sit down and let Doug Wright talk. He's the one with the hair. So I'll go sit down.
Mr. Wright: All right. So as Andrew told you before, I'm a developer technical support engineer here at Be. As you will all probably wind up having questions about the BeOS after this session and all the other ones, you know, when you get back home and you're in front of your machine, just don't understand something, you'll probably wind up sending your questions to me at Dev Support at Be.com, so feel free to make as much use of that as possible.
So Approaching BeOS Applications, what am I going to tell you about? I'm going to go a little bit more in depth into the basic pieces that you need to build application in the BeOS. Hello. There we are.
Okay. The BeOS provides you with a framework, simple building blocks that you use to put together applications, objects like application object, window object, menu object, messages. They all fit together to allow you to build applications that let you -- they give you instant multithreading.
They let your -- your Windows and your applications each run in their own thread, so that you have a really responsive user interface. They give you easy messaging systems so that you can send messages back and forth between Windows applications, your application, other people's application. And it winds up, you know, communicates with the system in a really seamless way.
So there are five major building blocks, let's say, that every application will wind up using. You're going to need to use these in order to build an application, especially GUI applications. You're going to wind up using every single one of these over and over and over again.
There are many other pieces of the framework that work together, but once you have an understanding of these five classes, you'll really be on your way to building an application.
So where does an application start? You've all probably -- well, hopefully, programmed C and C++ before, know every application starts in a main function. Well, here's your typical main for a BApplication. Here we're creating an instance of it's actually a class derived from BApplication, just called MyApplication.
Notice we're using a MIME stream to identify ourselves to the system. When you create this application object it gets registered with the system as a running application, so that other applications can find you and communicate with your application and, you know, simultaneously other applications are then available for you to find by other MIME streams so that you can communicate with them.
And then we call run. Run starts the applications thread running. This application has its own thread and runs with that thread running and it goes on until that thread finally exits and gets deleted and then you're down there at the bottom, Return.
So what do you get when you create this BApplication object? Well, like I said before, you get a thread and what's going on in that thread is an event loop and there's a message cue where your messages can be posted and the event loop pulls messages out of that cue, processes those messages, hands them off to message handlers.
Now, an application object is itself also a message handler and that handler can receive messages, you know, messages that show up in the cue. Where do those messages come from? They come from the system. Messages like Refs Received. That's a message you get when you're launched with -- either somebody double-clicks a document that has your application specified as the preferred application for that document or if somebody, you know, drags a bunch of documents to your app, you'll get a big Refs Received message that contains the names of all those files and their paths and you'll have a function that you can override to deal with those files.
And also the application can handle your own messages. There's a message received hook that you override in order to process messages of your own design. Play, you know, stop, move this window, you know, stuff -- stuff that you create so that enhances your application or, you know, performs functions that you design.
Now, when you create this application, like I said, you get registered with the system. That system service is called the roster, and be_roster is a global that's created when you create that application object in your applications base. And so you can use the be_roster to launch other applications, to get messengers so that you can send messages to other applications and in general communicate with other parts of the system, other applications running on the system.
You also get another global called be_app and that's a global pointer in your application space to the BApplication object itself, so that you can easily, from anywhere within your application, communicate with the application object.
So let's create a window in our application. Very first thing pretty much anybody's going to do in their application is put up a window. And if you look up there at the top, we get our signature and we're inherited from BApplication.
Here we create a window pointer, that's just a BWindow, again over derived object from a BWindow, and we create a rectangle, which is where our window is going to live in the screen space. Now, the coordinate system of the screen is pretty usual, starts 00 in the top left-hand corner and whatever resolution it is.
Here we use a window constructor to create a new window. We use that rectangle, we give the window a title. Here is the type of window that you're going to try to create.
Now, previously you could just create four or five different types of windows, a document window, an alert window, those sorts of things. Now we've actually gone in and separated the type of window into two pieces, the look of the window and the feel of the window and this is the old style constructor, which you can still use or you can use the new style where you actually design a look and the feel.
And then some flags. This window happens to accept first click. In other words, if you click in the window that message, the click message, the MouseDown message, is sent to the view inside that window on that very first click. You don't have to make the window active and then click again to do, you know, whatever action you needed to do. Very nice feature.
And then down here we call show and that unlocks the window after its been constructed, displays it on the screen.
So what do you get when you create a BWindow object? Well, guess what? You get another thread so automatically, you know, create an application, create a window, you've got two threads running and this thread has its own event loop, has its own message cue, pulls messages out of its own message cues and sends them off to handlers.
BWindow is also a message handler and it can also receive system messages and your own messages that you create now. A window might receive different messages than just a -- just an application object. It could probably receive the same Refs Received message where somebody's dragged a file straight to your window.
The window object in that case may receive that message and it may respond to it directly or it may just pass that message back to the application object, because you have the handling code for Refs Received in your application object. Or it might receive the MouseDown message, you know, mouse moved message, mouse inside of window message, drag message, those sorts of things or your own messages of your own design.
So instant multithreading. As we said before, it's really easy to use and get multithreading in the BeOS. Create an application object, create a window object, two windows, three windows, four windows. You've got four-window threads and that, you know, gives you instant ability to take advantage of multiple processors and it also makes your user interface really responsive, because any one of those windows has their own thread to receive messages. So one window can be doing some totally crazy process, then you go click on the other window, it's totally responsive, ready to handle all the input that you can give it, because it's not off busy doing something else.
So what else do you get in a window? Well, you get a coordinate system and a container for drawing views. Now, when you create a window in the BeOS you don't actually draw in that window; you draw in a view that you place in that window. And the coordinate system in a window is based 00 from the top left corner of that window. So you don't have to do a calculation to where you want it to be on the screen, you just go straight to that window and add views to the window to draw different objects inside that window.
So let's add a view to a window. So here we are in the window constructor. Here we're going to create another rectangle. Again, this is in the coordinates inside the window. Going to create a new -- this is a little typo. I think I invented some new shorthand for creating objects. Now I needed to new that view, but I dropped that when I was typing it into the presentation tool, just not quite the same as the IDE.
And then before you just add that child to the window and you need to lock it, and an important thing to remember when you're going and locking things is to check the return value when you call a lock, because if you call a lock return value, returns false, you didn't get the lock and then you go ahead and try to add your view, then you try to unlock the window, you might be unlocking someone else's lock.
A Speaker: You're locking the window thread at that point?
Mr. Wright: You're locking the window thread, yeah, so that you have a window object that's communicating as an entity inside the operating system, somebody else could be trying to change that window simultaneously.
Mr. Kimpton: Let me just reiterate that. We called the inherited constructor of our BWindow. So the BWindow itself has been constructed, the thread has been built and it's running even now, even now in the lower part of this code in the constructor of our own design code.
Mr. Wright: Another question?
(Inaudible question.)
Mr. Wright: Yeah, those are all member functions of the BWindow class. Our window is already created and running.
Now, the window doesn't actually get unlocked until you show it the first time, so this lock is kind of an extra protection mechanism there, but you can't be sure that somebody hasn't shown you the window already. If, say, this wasn't a derivative of BWindow, it's a derivative of somebody, Bob's window and Bob happens to call show at the bottom of his constructor, which is quite common, then the window would already be unlocked and running and so, you know, it could be modified by somebody else while you're trying to add a child to it.
So you just need to always make sure you lock, check the return value, do what you need to do and unlock the window.
One more question.
A Speaker: Do you need to check the return value if you don't lock the child?
Mr. Wright: The regular lock window is locked. Okay. Let's move on.
So what do you get when you create a view? One more question.
A Speaker: When you lock that means that that window object won't get any messages, like none of the data that's on there can be latched?
Mr. Wright: Yeah, it's thread isn't running, so nothing else is going to happen during that lock.
A Speaker: You always subclass BWindow and BView and make your own subtype?
Mr. Wright: A BWindow that hasn't been subclassed isn't going to deal with any, you know... yes. Let's put it that way. You're pretty much always going to drag from BWindow and BView, because BView you want to draw from something and the raw view box doesn't actually draw anything to the screen.
A Speaker: They're virtual; right?
Mr. Wright: I don't know for sure if you can instantiate a raw BWindow or BView. Peter? You can?
Mr. Potrebic: If you have a simple app or a simple window you might use a plain window and then stuff your specific view classes in there and you'll be fine, because you don't need your window to respond to any particular messages that you've created, to have any particular behavior and you might use a plain view in a group, a bunch of views together, but for the most part you would be subclassing.
(Inaudible question.)
Mr. Wright: Can you use plain vanilla BWindows and BViews. And yeah, If you're doing a very simple app, yeah, you could just create a BWindow and throw a bunch of views inside that window, if you don't want the window to respond to any special message.
You can create a plain Jane BView and just use that as a container for other views, because a view, as you'll see here, it's another view container, so you can create a plain BView, add a bunch of other views to it and it will actually never wind up handling any messages that aren't already built in.
So what do you get when you create a view? Well, you don't get a thread this time. I'm sorry, that's just for windows. You do get another message handler, though. So an app can handle messages, window can handle messages and every view handles messages.
So your window pulls messages out of the message loop and passes it to whatever handler seems appropriate and in a lot of cases that's a particular view. You have a slider inside a window and somebody clicks on that slider. That message is going to show up on that window message cue and it's going to send it straight to the slider, because that's the object that somebody was busy clicking on.
So view again handles system messages, MouseDown, mouse moved. There was lots of system messages. Yes?
A Speaker: Does the view container border automatically for you, got multiple views as a border?
Mr. Wright: No, you can specify a border, but it's not an automatic thing. There's not -- there's no -- I think the default border isn't on.
Yeah?
A Speaker: Can you spawn threads?
Mr. Wright: Yes, that's down there in the kernel. So you can have your BView spawn its own thread when you start it, but it's not going to be a message handling, it's not going to have an event loop built into it. You want to put whatever you want to happen inside that, inside that thread.
So you get another coordinate system inside every view, so you don't have to translate to window coordinates if you want to move stuff around inside of a view, just draw straight inside of a view, again it starts at 00 in the top left corner. Already told you it's a view container. You add children to a view just like you add children to a window.
So you're starting to see probably the progression of simplicity that is in the BeOS. The application object thread, it's an event loop, it's a handler, window, thread, event loop, handler, view. It's not a thread and event loop, but it is a handler and they all -- all the function calls are very similar in each one of them. They're all built on each other.
The most important function, well, at least if you want the view to display anything, is probably draw. That's the first thing you're going to override when you create a view, except for maybe the constructor and that's where you do your drawing routines and that's the function that gets called any time the view needs to be updated.
So when, you know, you've got a window here and you drag another window across it, the view gets -- the draw gets draw called on and each time that needs to update and you can actually programmatically call invalidate so that that view needs to be updated next time the draw cycle comes around.
And part of what a view gives you are a bunch of drawing routines, primitives, stroke lines, fill rects, that kind of thing. So gives you all that, plus font capabilities. You can change the font size and color and the font that's specified for a particular view and draw streams, et cetera. So there's lots of good stuff in view. It's a big class with all kinds of fun functions in it.
So here's the simple view that you would override, just to show you the three most likely things you'd do inside a view override draw, MouseDown and MessageReceived.
MessageReceived is the function that gets -- well, I'll start with draw. I already told you about draw. It's where you do your drawing when it's necessary.
MouseDown is one of those system book functions, so when a message gets passed to your handler that is one of those system messages, it calls straight to one of the system handling functions in your view and you override those functions as necessary.
So if we wanted to deal with MouseDown messages in this view you'd override MouseDown. Then all the other messages that aren't system messages get passed to MessageReceived. So typically you have a switch statement in MessageReceived that cases off the what of a message, which I'll cover in a minute, and you determine what the message is about and deal with it. Okay.
So there's a whole bunch of BView descendants. This is not even close to the whole list, buttons, CheckBoxes, all the typical GUI controls. The one thing to notice there is that there is this object called BControl. This is a generic the control object and the things like button and CheckBoxes are derived from that. Well, BControl is derived from view, so all those things are derived from BControl.
So let's take a look at what BControl is and how you deal with that. What do you get when you create a control? Well, you get a BView, plus an Invoker. An Invoker is an object that sends a particular message when it gets invoked. In the case of a button, when you click on the button it's going to send a message someplace; right?
So an Invoker gives you a storage space for what the target handler for that message is. So when you click on that button, who gets the message that that button sends? Of course you're going to need the message that you're going to send, so it gives you a message that you pass to it on construction and you can actually change that message once that control already exists and it typically gives you some kind of state information, like in the case of a slider where the slider is. In the case of a toggle button, like whether it's on or off, that sort of thing.
So let's go take a little -- take a look at a little code example. Work space one. Walk you through a window constructor where we're actually adding a bunch of controls. In particular, a menu bar and the menus that go in that menu bar and show you just how simple and easy that is.
So we create a bunch of pointers. We create a rect. Notice it's 15 high and 1000 long. That's just so that our menu bar goes on for a long time. We create a new menu bar object, that's one of those BControls I told you about. We create a new BMenu called Palette and we add several items to that menu.
So there's a, you know, a list of things for the menu, each one of the things in a menu is a menu item. And we add the menu to the menu bar as an item. So menu bar is kind of like an uber menu, as you would think, and you can add items to a menu bar. In this case you add menus to the menu bar. You can do the same thing to a menu to wind up with sub.
Here we take this item that we happen to specify there inside of that, in case you missed that, set it as marked so it adds a check to that menu item and we set the menu to be a radio mode. So now we have a simple list menu where you select one of them and uncheck whatever we checked, checks the new one. So super simple.
We're going to do pretty much the same exact thing again here with another menu and add that item to the menu bar and then we're going to call AddChild on this menu bar.
Now, you'll notice we're calling AddChild -- if you go back up to the top where there's a subclass of BWindow. So we created a BWindow object, but we know that BWindow doesn't start running until you show it for the first time, and so no show has been called so the thread's not running so we don't need to lock it, just so you know, because we talked about the lock thing a bunch before.
So let's go back down. Now, here we're just checking out the height of a -- of the menu bar and we're using that height to create another -- to change the dimensions of our rectangle and we're using that to create a new view at that size.
So here we're -- we've got an overridden BView. This code is straight out of the Mandelbrot demo and the sample code for that is on the CD code you received before, so if you want to go back and look at this later.
Then we create a scroll view, which is another kind of a view that actually includes scroll bars, and one of the things that you pass to it is the view that you want to target, so notice MyView over there. That's the -- we added this view to the scroll_view and then we add the scroll_view to the window. We set some size limits, resize the window to fit the size of the view based on these predetermined formats and we update the scroll bars and then we're done.
So we have a couple of menus. They just have CheckBoxes, we have a view, we have scroll bars resized. The scroll bars are live, are set up. It was all in that one little page of code. That's all you needed to do this. So there you go.
A Speaker: Yeah, what about manuscripted resources, things in the code like that?
Mr. Wright: You can use resources. We don't have, like, your reset that type application to create those kinds of things. There are a couple of third party applications, both app_sketcher and interface elements allow you to build those presetup menus and windows.
Mr. Kimpton: The following session from this one we're going to talk a little about development tools, not just the IDE board, but what else is there. And the topic of resources and resource added to type things will come up again there and we'll discuss it a little further in the following session from this point.
Was there another one?
(Inaudible question.)
Mr. Wright: Yeah, Benoit writes fast code and when you go fast sometimes you crash, but --
Mr. Kimpton: Benoit writes code fastly or better quickly, actually maybe is the better point.
Mr. Wright: What he's doing actually here, yes, he's newing a BMessage and as the what of the BMessage, he's just passing actually the integer value that he needs out of that message. So rather than using the name/value pairs that most of us normal people would use in the BMessage, he's just sticking it right there in the what. And if you look later in his code he just pulls it right out of the what to change that value.
Mr. Kimpton: You could write that sound-mixing demo in three days if you're Benoit. You needn't necessarily want to, you might want to take a little longer. Is he in the room yet or is he about to throw something at me?
A Speaker: Can you go over the flags that you're passing the views there?
Mr. Wright: Okay. FollowAll. When you create a view, one of the flags that you pass it is the type of behavior you want it to follow related to its parent, and BFollowAll means that the view's sides will follow all the sides of the view when you resize it. So if you add this view straight to the window rather than to these scroll bars, if you add this view straight to the window and you resize the window, the views edges will follow that window and that's why what at the scroll view has BFollowAll as well. BeWillDraw is pretty self-explanatory. It means that the view actually has something to draw. Most views that you add will be a drawing view and will have that flag set.
BNoBorder. There's that border flag and I don't recall exactly what the true and true are. The BBook is really clear and easy to understand. It's on the CD that you got. Check it out.
(Inaudible question.)
Mr. Wright: Horizontal and vertical, so if you just wanted a horizontal scroll bar you make the other one false, there you go.
From the back of the room.
A Speaker: You mentioned you have to be careful with locking and unlocking. What actually happens if you make a pretty bad programming error, how badly does it crash? Is it like a MacApplication system, they quit?
Mr. Wright: He's asking so what exactly happens if you do -- if you program it badly and the application then crashes, what sort of thing happens at that point.
In the case of locking and unlocking windows, you'd probably will get some weird behavior, some other thread was modifying the window at the same time you were. Possibly if it did crash your application would give you this little box that said your application has behaved badly, ShowDetails. There's a button for ShowDetails and okay, I don't care button. If you hit the show details you get the debugger, whether you're a developer or not. Hopefully it will scare people away once they get that.
Mr. Kimpton: There are some specific areas of the operating system where if you attempt to manipulate a quantity, which you should have locked beforehand, it will automatically go to a debugger or through the error box and say object must be locked and somebody confirm -- Peter, is the object must be locked mechanism done through exceptions?
Mr. Potrebic: No.
Mr. Kimpton: Do we just do a debug type?
Mr. Potrebic: Yeah, just do the debugger. Another possible crash would be if you end up with an exception, there's an outer exception handling routine which will give the person a dialogue saying an unexpected error occurred, do you want to continue running or just quit?
And so it's kind of like on the Mac, where you have the zoom button, but ours is always enable, which gives the user the option to let the window still run, maybe it's still in a valid state or they can just click the other button and it will just terminate the application. But in all cases none of your other apps will be affected if you don't handle the locking and unlocking properly in your observe app.
Mr. Kimpton: We have a real operating system. One application can die without affecting other ones. That's an important feature. Yes, definitely an important feature.
Mr. Wright: Let me get to the last bit here. I keep talking about all these messages that are getting passed around and message handlers and message cues, but you really need to know about the object that we use in that implementation and that's a BMessage. So what do you get in a BMessage, why do you need this BMessage?
Well, you get a description, the "what" field of BMessage and that is a defined constant that you've created that let's you know what's going on. There's a bunch of system-defined constants and there's some rules for the constants that you should create when you create these messages and that was the little rule that Benoit wasn't necessarily using when he was just using integer values for that one value, but hey, it works.
So what else do you need besides a description? Well, in some cases all you need is the description, because your message just doesn't come in. Maybe it's just play or open or something like that and you don't need any other data on the other end of that message or maybe you're actually passing a bunch of data or you need something a little bit more specific like play "when" and you need the "when" value, a time value in that data container.
So the BMessage provides you with this data container in the form of name/value pairs and there are routines that add those name/value pairs of different forms of data, as well as specific defined system types, as well as just a pointer to data and size of the data and you stick that data in there and you need to know what format that data is in.
And it also provides you with an archiving mechanism for saving that message in sort of a flat format so that you can do things like transfer it, save it on disk, transfer it over the network, that sort of thing and then rehydrate that message and the contents of that message later.
So let's create a message. Pretty simple. In Benoit's app, you saw that he was newing those BMessages. In many instances on the BeOS it's much preferred if you create the message on the stack, because the thing that you pass that message to makes a copy of it.
In the case of the BControl or the -- the menu item, it actually takes that message that you've given it and so you need to new that message. But all that is spelled out very specifically and clearly in the BBook, but any time some function or object takes a BMessage or you need to give a BMessage to another object, just go and check and see which kind it is, whether it takes over that object or whether it makes a copy of it. And if it makes a copy of it, create that message on the stack, because then you won't have to worry about did I delete it or not, that sort of thing.
So here we create a BMessage. The parameter is the "what" field, so this is some constant that we've defined called STOP_TIME and we call message AddInt64 to add a 64-bit integer. We're calling the field "when" and we call system_time to stick the current 64-bit system_time in microseconds into that "when" field, so then later we call FindInt to get that data right back out of that message.
So we've got BApplication, BWindow, BView. All these things put together give you a really easy way of receiving and responding to system messages, our own custom messages and as well as interapplication messages, because remember that be_roster thing that the BApplication object registers with and can talk to and that object allows you to communicate the messages with other applications by getting a messenger to those other applications.
So all of these things combined, you have this great way of passing messages around all over the place in the system and that is really the key to the scripting power that we also provide in all these kits. And to know more about, to really get in depth with the messaging inscripting, I have a session again at four o'clock called, appropriately, Approaching Messaging and Scripting, so if you want to really get in deep on this stuff, come to that one.
Mr. Osadzinski: That's at five o'clock, not four.
Mr. Wright: Five o'clock. Terribly sorry.
So it's easy to build applications using our simple building blocks, a nice framework for putting together applications. It's consistent, the pieces, parts fit together and make sense in a nice hierarchical way, you know, add children to this and that.
You get instant multithreading, you know, you create four windows, you've got four threads. If you have two processors, then each document you have is running at its own thread and you can have two documents basically doing their thing simultaneously on the processors and they'll be switching in and out as necessary. You have a really easy simple view messaging system for passing messages in your app, between your system and your app and between other applications.
So there you have it. Anybody else have any questions?
A Speaker: I saw an interesting exhibit of why you need a lock with your views. With that Mandelbrot_app you can get multiple threads drawing in the same window; have you done that?
Mr. Wright: Uh-huh, yeah.
A Speaker: Just keep selecting the palette without drawing the whole thing. You can have four or six. You can keep drawing, which is just an example of why you need to lock when you write to that window. You can pull it up and show it possibly.
Mr. Kimpton: The question was that one of the things that you can do with the Mandelbrot application is if I -- I'm just going to try to get it to do this slowly. Doing anything slowly on this platform is actually a bit tricky, so you have to bear with me.
Mr. Wright: You're going to have to turn off the processor.
Mr. Kimpton: Sorry, where's the -- let's make this machine slower.
Mr. Wright: You've got to do that and then your application.
Mr. Kimpton: You can see as I --
Mr. Wright: There you go. You got it.
Mr. Kimpton: Where's Benoit? Where's the author of this code?
One of the things that the question was saying that this is an example where if you failed to lock your application or thread-specific data, then threads can actually sort of do the wrong thing or do something unexpected.
There are multiple threads created to draw into this window for performance sake and it's quite possible for you to change that palette whilst their drawing and in which case you've got the example as I say here. Each time I change palette it redraws, but as I change palette it sort of continues to draw and gets very, very confused in terms of the color areas that are being displayed.
A Speaker: Eventually with this app all the threads will catch up with your last palette selected?
Mr. Kimpton: Indeed.
A Speaker: But on a very slow processor -- I've had four of them just kind of crawling down the screen when I was iterated in. They were all over writing each other, so that's why you have a lock. It takes a while.
Mr. Kimpton: Could we fix the bug, Benoit?
Mr. Wright: No, it's interesting, wouldn't ever change that. It's good to show. Few years old?
Mr. Kimpton: Five.
Mr. Wright: Five years old? Wow.
Mr. Kimpton: You can tell actually the progression that Be has made actually in that statement. So two or three years ago we were using this application to demonstrate how powerful BeOS is and now it's reduced to the lonely level of sample code.
Mr. Wright: And imperfect at that.
Mr. Kimpton: So if you really want to know how that music demo that you saw earlier works, if you'd all like to come back around about the turn of the century, then it will be being used as sample code, we can divulge those secrets then. Benoit promised to reveal all and he's going to show us the code, too.
Any other questions about --
(Inaudible question.)
Mr. Wright: Is there a default way the messages get passed between parents and children?
(Inaudible question.)
Mr. Wright: If the child ignores the message does it get passed to the parent?
Well, remember the BWindow in the BApplication are the objects that actually have message handling loops, the threads that hold the messages.
Now, they pass those -- they pass those messages to the appropriate handler. Now, if that handler doesn't respond to that message then it goes back to the -- the window, the -- yeah, Peter? Sorry.
Mr. Potrebic: Yeah. If some view gets a message and it doesn't handle it and your code calls inherited when you don't handle a message, it will then percolate to the parent view and if the parent view is anywhere in the hierarchy, the class hierarchy, it will go all the way up to the window, so a message will percolate up the view chain.
(Inaudible question.)
Mr. Potrebic: No, once it gets to the window and that's it.
Mr. Kimpton: It is a common feature in your code and one you should follow, that MessageReceived. Basically the guts of MessageReceived is a switch statement where you case on each of the ones that you, in that particular view or window, really care about.
And then at the very bottom is a default when you call, you inherited your parents MessageReceived, and if you observed that sort of behavior then you will get the right thing happening, whereby if the inherited view also does not handle that message then it will percolate through the layers until it reaches, in our case, the BWindow at the top.
And so that's a good behavior for you to follow; although, there may be reasons why you don't want that to happen.
Mr. Wright: Another question?
(Inaudible question.)
Mr. Wright: No, he's using the term "inherited" in the sense that you call the class from which you inherited, so in the case of the view that's inherited from BView, call BViewMessageReceived.
Now, the Metrowerks -- inherited was set up in the compiler and it still turns blue when you type "inherited." It still recognizes a keyword, but it didn't make it in the ANSI spec of C++, so their compiler -- actually, there's a switch you have to throw in order to use it, but in order to make sure that your code is portable from Metrowerks compiler to somebody else's or, you know, to other platforms at some point using BViews, I don't know, in order to make sure that you can move it from compiler to compiler, maybe one that doesn't have inherited switch, then just call BView. Plus it will be clear when you read it where that class came from.
Mr. Kimpton: Yes.
(Inaudible question.)
Mr. Wright: So if it wasn't exactly clear where the message went when a control was invoked, where does that message get sent?
You pass a control target handler, another BView that needs to be a child of the same view or window that it's a child of, that makes it an eligible handler. And, you know, if you want the message to actually exit the window you need to send the message to the window and have the window pass it on to wherever it needs to go.
Mr. Potrebic: The default for a control is that the message gets posted, sent directly to the window that the control lives in. There's function -- there's member functions to BControl where you can change that default target and it can be any object in the -- any handler in the system. It doesn't have to be in the same window. It can be another application, it can be another view in another application or another window in your application.
Mr. Kimpton: You can simply call SET_TARGET with the control and pass to it the pointer to any other handler, however it was you managed to get hold of it.
Mr. Potrebic: Or one of these messenger objects.
Mr. Wright: To another application.
Mr. Potrebic: Which you can learn more about in the five o'clock talk.
Mr. Kimpton: If it sounds like we're just standing up here, giving a plug for everybody else's sessions, then you're correct, that is the purpose of these two hours.
Mr. Wright: Anything else? All right. Then get some water.
Mr. Kimpton: Thank you very much.
(Session concluded.)