When you create a control such as a button object fromthe BButton class, define a unique message type that becomes associated withthat one control.. In thischapter, you’ll read about the
Trang 1Chapter 5, Drawing, described the color control and the BColorControl class
used to create such controls This chapter discusses other control types and theclasses used to create each Also discussed is the BControl class, the class fromwhich all other control classes are derived
When the user clicks on a control, the system responds by sending a message tothe window that holds the control This message indicates exactly which controlhas been clicked The message is received by the window’s MessageReceived()hook function, where it is handled Since the BWindow version ofMessageReceived() won’t know how to go about responding to messages thatoriginate from your controls, you’ll override this routine Your application thengains control of how such messages are handled, and can include any code neces-sary to carry out the task you want the control to perform This chapter includesexamples that demonstrate how to create controls and how to overrideMessageReceived() such that the function handles mouse clicks on controls ofany of the standard types
Introduction to Controls
When a BWindow object receives a message, it either handles the message itself orlets one of its views handle it To handle a message, the window invokes aBWindow hook function For example, a B_ZOOM message delivered to a window
Trang 2results in that window invoking the BWindow hook function Zoom() to shrink orenlarge the window To allocate the handling of a message to one of its views, thewindow passes the message to the affected view, and the view then invokes theappropriate BView hook function For example, a B_MOUSE_DOWN message results
in the affected view invoking the BView hook function MouseDown()
Besides being the recipient of system messages, a window is also capable ofreceiving application-defined messages This lets you implement controls in yourapplication’s windows When you create a control (such as a button object fromthe BButton class), define a unique message type that becomes associated withthat one control Also, add the control to a window When the user operates thecontrol (typically by clicking on it, as for a button), the system passes the applica-tion-defined message to the window How the window handles the message isdetermined by the code you include in the BWindow member functionMessageReceived()
Control Types
You can include a number of different types of controls in your windows Eachcontrol is created from a class derived from the abstract class BControl TheBControl class provides the basic features common to all controls, and theBControl-derived classes add capabilities unique to each control type In thischapter, you’ll read about the following control types:
Button
The BButton class is used to create a standard button, sometimes referred to
as a push button Clicking on a button results in some immediate action ing place
tak-Picture button
The BPictureButton class is used to create a button that can have any size,shape, and look to it While picture buttons can have an infinite variety oflooks, they act in the same manner as a push button—a mouse click results in
an action taking place
Checkbox
The BCheckBox class creates a checkbox A checkbox has two states: on andoff Clicking a checkbox always toggles the control to its opposite state orvalue Clicking on a checkbox usually doesn’t immediately impact the pro-gram Instead, a program typically waits until some other action takes place(such as the click of a certain push button) before gathering the current state
of the checkbox At that time, some program setting or feature is adjustedbased on the value in the checkbox
Trang 3Introduction to Controls 179
Radio button
The BRadioButton class is used to create a radio button Like a checkbox, aradio button has two states: on and off Unlike a checkbox, a radio button isnever found alone Radio buttons are grouped together in a set that is used tocontrol an option or feature of a program Clicking on a radio button turns offwhatever radio button was on at the time of the mouse click, and turns on thenewly clicked radio button Use a checkbox in a yes or no or true or false sit-uation Use radio buttons for a condition that offers multiple choices that aremutually exclusive (since only one button can be on at any given time)
Text field
The BTextControl class is used to create a text field A text field is a controlconsisting of a static string on the left and an editable text area on the right.The static text acts as a label that provides the user with information aboutwhat is to be typed in the editable text area of the control Typing text in theeditable text area of a control can have an immediate effect on the program,but it’s more common practice to wait until some other action takes place (like
a click on a push button) before the program reads the user-entered text
Color control
The BColorControl class, shown in Chapter 5, creates color controls A colorcontrol displays the 256 system colors, each in a small square The user canchoose a color by clicking on it A program can, at any time, check to seewhich color the user has currently selected, and perform some action based
on that choice Often the selected color is used in the next, or all subsequent,drawing operation the program performs
Figure 6-1 shows four of the six types of controls available to you In the upperleft of the figure is a button The control in the upper right is a text field Thelower left of the figure shows a checkbox in both its on and off states, while thelower right of the figure shows a radio button in both its states A picture buttoncan have any size and look you want, so it’s not shown All the buttons are associ-ated with labels that appear on or next to the controls themselves
The sixth control type, the color control based on the BColorControl class, isn’tshown either—it was described in detail in Chapter 5 and will only be mentioned
in passing in this chapter
A control can be in an enabled statewhere the user can interact with itor adisabled state A disabled control will appear dim, and clicking on the control willhave no effect Figure 6-2 shows a button control in both its enabled state (left-most in the figure) and its disabled state (rightmost in the figure) Also shown iswhat an enabled button looks like when it is selected using the Tab key (middle
in the figure) A user can press the Tab key to cycle through controls, making eachone in turn the current control As shown in Figure 6-2, a button’s label will be
Trang 4underlined when it’s current Once current, other key presses (typically the Returnand Enter key) affect that control.
Creating a Control
A control is created from one of six Interface Kit classes—each of which is ered in detail in this chapter Let us start by examining the BControl class fromwhich they are derived
cov-The BControl class
The BControl class is an abstract class derived from the BView and BInvokerclasses Control objects are created from BControl-derived classes, so all controlsare types of views
It’s possible to create controls that aren’t based on the BControl
class In fact, the Be API does that for the BListView and
BMenuItem classes These are exceptions, though You’ll do best by
basing each of your application’s controls on one of the six
BControl-derived classes Doing so means your controls will
behave as expected by the user.
BControlis an abstract class, so your project will create BControl-derived classobjects rather than BControl objects However, because the constructor of eachBControl-derived class invokes the BControl constructor, a study of theBControl constructor is a worthwhile endeavor Here’s the prototype:
BControl(BRect frame,
Figure 6-1 Examples of button, text field, checkbox, and radio button controls
Figure 6-2 A button control that’s (from left to right) enabled, current, and disabled
Trang 5param-in Chapter 4, Wparam-indows, Views, and Messages, so here I’ll offer only a brief recap of
their purposes The frame parameter is a rectangle that defines the boundaries ofthe view The name parameter establishes a name by which the view can be iden-tified at any time The resizingMode parameter is a mask that defines the behav-ior of the view should the size of the view’s parent view change The flagsparameter is a mask consisting of one or more Be-defined constants that deter-mine the kinds of notifications (such as update) the view is to be aware of
The remaining two BControl constructor parameters are specific to the control.The label parameter is a string that defines the text associated with it Forinstance, for a button control, the label holds the words that appear on the but-ton The message parameter is a BMessage object that provides a means for thesystem to recognize the control as a unique entity When the control is selected bythe user, it is this message that the system will send to the window that holds thecontrol
Your project won’t create BControl objects, so a sample call to the BControlconstructor isn’t useful here Instead, let’s look at the simplest type of BControl-derived object: the BButton
The BButton class
Creating a new push button involves creating a new BButton object TheBButton constructor parameters are an exact match of those used by theBControl constructor:
BButton(BRect frame,
const char *name,
const char *label,
BMessage *message,
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_WILL_DRAW | B_NAVIGABLE)
The BButton constructor invokes the BControl constructor, passing all of itsarguments to that routine The BControl constructor uses the label argument toinitialize the button’s label, and uses the message argument to assign a uniquemessage to the button The BControl constructor then invokes the BView con-structor, passing along the remaining four arguments it received from the BButtonconstructor The BView constructor then sets up the button as a view After the
Trang 6BControl and BView constructors have executed, the BButton constructor ries on with its creation of a button object by implementing button-specific tasks.This is, in essence, how the constructor for each of the BControl-derived classesworks.
car-Creating a button
A button is created by defining the arguments that are passed to the BButton structor and then invoking that constructor using new To become functional, thebutton must then be added to a window That’s what’s taking place in this snippet:
con-#define BUTTON_OK_MSG 'btmg'
BRect buttonRect(20.0, 20.0, 120.0, 50.0);
const char* buttonName = "OKButton";
const char* buttonLabel = "OK";
BButton *buttonOK;
buttonOK = new BButton(buttonRect, buttonName,
buttonLabel, new BMessage(BUTTON_OK_MSG));
aView->AddChild(buttonOK);
In the above code, the BRect variable buttonRect defines the size and location
of the button This push button will be 100 pixels wide by 30 pixels high ThebuttonNamestring gives the button the name “OKButton.” This is the name used
to locate and access the button by view name using the BView member functionFindView() The name that actually appears on the button itself, “OK,” is defined
by the buttonLabel string The message associated with the new button control
is a new BMessage object of type BUTTON_OK_MSG I’ll explain the BMessage class
in a minute Here it suffices to say that, as shown above, creating a new messagecan be as easy as defining a four-character string and passing this constant to theBMessage constructor
The BButton constructor prototype lists six parameters, yet the above invocation
of that constructor passes only four arguments The fifth and sixth parameters,resizingMode and flags, offer default values that are used when these argu-ments are omitted The default resizingMode value (B_FOLLOW_LEFT |B_FOLLOW_TOP) creates a button that will remain a fixed distance from the left andtop edges of the control’s parent view should the parent view be resized Thedefault flags value (B_WILL_DRAW | B_NAVIGABLE) specifies that the controlneeds to be redrawn if altered, and that it can become the focus view in response
to keyboard actions
Adding a control to a window means adding the control to a view In the abovesnippet, it’s assumed that a view (perhaps an object of the application-definedBView-derived MyDrawView class) has already been created
Trang 7Introduction to Controls 183
Enabling and disabling a control
When a control is created, it is initially enabled—the user can click on the control
to select it If you want a control to be disabled, invoke the control’sSetEnabled() member function The following line of code disables thebuttonOK button control that was created in the previous snippet:
buttonOK->SetEnabled(false);
SetEnabled() can be invoked on a control at any time, but if the control is tostart out disabled, call SetEnabled() before displaying the window the controlappears in To again enable a control, call SetEnabled() with an argument oftrue
This chapter’s CheckBoxNow project demonstrates the enabling and disabling of abutton The technique in that example can be used on any type of control
Turning a control on and off
Checkboxes and radio buttons are two-state controls—they can be on or off.When a control of either of these two types is created, it is initially off If you wantthe control on (to check a checkbox or fill in a radio button), invoke theBControl member function SetValue() Passing SetValue() the Be-definedconstant B_CONTROL_ON sets the control to on Turning a control on and off inresponse to a user action in the control is the responsibility of the system—notyour program So after creating a control and setting it to the state you want, youwill seldom need to call SetValue() If you want your program to “manually”turn a control off (as opposed to doing so in response to a user action), have thecontrol invoke its SetValue() function with an argument of B_CONTROL_OFF
A button is a one-state device, so turning a button on or off doesn’t make sense.Instead, this snippet turns on a two-state control—a checkbox:
requirePasswordCheckBox->SetValue(B_CONTROL_ON)
Creating checkboxes hasn’t been covered yet, so you’ll want to look at the Box example project later in this chapter to see the complete code for creating andturning on a checkbox
Check-Technically, a button is also a two-state control When it is not being
clicked, it’s off When the control is being clicked (and before the
user releases the mouse button), it’s on This point is merely an
aside, though, as it’s unlikely that your program will ever need to
check the state of a button in the way it will check the state of a
checkbox or radio button.
Trang 8To check the current state of a control, invoke the BControl member functionValue() This routine returns an int32 value that is either B_CONTROL_ON (which
is defined to be 1) or B_CONTROL_OFF (which is defined to be 0) This snippetobtains the current state of a checkbox, then compares the value of the state to theBe-defined constant B_CONTROL_ON:
int32 controlState;
controlState = requirePasswordCheckBox->Value();
if (controlState == B_CONTROL_ON)
// password required, display password text field
Changing a control’s label
Both checkboxes and radio buttons have a label that appears to the right of thecontrol A text field has a label to the left of the control The control’s label is setwhen the control is created, but it can be changed on the fly
The BControl member function SetLabel() accepts a single argument: the textthat is to be used in place of the control’s existing label In this next snippet, abutton’s label is initially set to read “Click,” but is changed to the string “ClickAgain” at some point in the program’s execution:
BRect buttonRect(20.0, 20.0, 120.0, 50.0);
const char *buttonName = "ClickButton";
const char *buttonLabel = "Click";
BButton *buttonClick;
buttonOK = new BButton(buttonRect, buttonName,
buttonLabel, new BMessage(BUTTON_CLICK_MSG));
Trang 9Introduction to Controls 185
window That message will be your program’s prompt to perform whatever action
is appropriate
Messages and the BMessage class
When the Application Server delivers a system message to an applicationwindow, that message arrives in the form of a BMessage object Your code deter-mines how to handle a system message simply by overriding a BView hook func-tion (such as MouseDown()) Because the routing of a message from the Applica-tion Server to a window and then possibly to a view’s hook function isautomatically handled for you, the fact that the message is a BMessage object maynot have been important (or even known) to you A control also makes use of aBMessageobject However, in the case of a control, you need to know a little bitabout working with BMessage objects
The BMessage class defines a message object as a container that holds tion Referring to the BMessage class description in the Application Kit chapter ofthe Be Book, you’ll find that this information consists of a name, some number ofbytes of data, and a type code You’ll be pleased to find out that when using aBMessagein conjunction with a control, a thorough knowledge of these details ofthe BMessage class isn’t generally necessary (complex applications aside) Instead,all you need to know of this class is how to create a BMessage object The snip-pet a few pages back that created a BButton object illustrated how that’s done:
informa-#define BUTTON_OK_MSG 'btmg'
// variable declarations here
buttonOK = new BButton(buttonRect, buttonName,
buttonLabel, new BMessage(BUTTON_OK_MSG));
The only information you need to create a BMessage object is a four-character eral, as in the above definition of BUTTON_OK_MSG as ‘btmg’ This value, whichwill serve as the what field of the message, is actually a uint32 So you candefine the constant as an unsigned 32-bit integer, though most programmers find iteasier to remember a literal than the unsigned numeric equivalent This value thenbecomes the argument to the BMessage constructor in the BButton constructor.This newly created message object won’t hold any other information
lit-The BMessage class defines a single public data member named what lit-The whatdata member holds the four-character string that distinguishes the message from allother message types—including system messages—the application will use In theprevious snippet, the constant btmg becomes the what data member of theBMessage object created when invoking the BButton constructor
Trang 10When the program refers to a system message by its Be-defined constant, such asB_QUIT_REQUESTED or B_KEY_DOWN, what’s really of interest is the what datamember of the system message The value of each Be-defined message constant is
a four-character string composed of a combination of only uppercase charactersand, optionally, one or more underscore characters Here’s how Be defines a few
of the system message constants:
“MSG” for “message.” The value of each constant may hint at the message type(for instance, ‘plSD’ for “play sound”), but aside from avoiding all uppercase char-acters, the value is somewhat arbitrary These two examples illustrate the conven-tion I use:
#define BUTTON_PLAY_SOUND_MSG 'plSD'
#define CALCULATE_VALUES 'calc'
Messages and the MessageReceived() member function
The BWindow class is derived from the BLooper class, so a window is a type oflooper—an object that runs a message loop that receives messages from the Appli-cation Server The BLooper class is derived from the BHandler class, so a win-dow is also a handler—an object that can handle messages that are dispatchedfrom a message loop A window can both receive messages and handle them.For the most part, system messages are handled automatically; for instance, when
a B_ZOOM message is received, the operating system zooms the window But youcannot completely entrust the handling of an application-defined message to thesystem
Trang 11Introduction to Controls 187
When a user selects a control, the Application Server delivers a message objectwith the appropriate what data member value to the affected BWindow object.You’ve just seen a snippet that created a BButton associated with a BMessageobject That BMessage had a what data member of ‘btmg’ If the user clicked onthe button that results from this object, the Application Server would deliver such
a message to the affected BWindow It’s up to the window to include code thatwatches for, and responds to, this type of message The BWindow class memberfunction MessageReceived() is used for this purpose
When an application-defined message reaches a window, it looks for aMessageReceived() function This routine receives the message, examines themessage’s what data member, and responds depending on its value TheBHandler class defines such a MessageReceived() function The BHandler-derived class BWindow inherits this function and overrides it The BWindow ver-sion includes a call to the base class BHandler version, thus augmenting whatBHandler offers If the BWindow version of MessageReceived() can’t handle amessage, it passes it up to the BHandler version of this routine Figure 6-3 showshow a message that can’t be handled by one version of MessageReceived() getspassed up to the next version of this function
Here is how the MessageReceived() looks in BWindow:
void BWindow::MessageReceived(BMessage* message)
BWindow-derived version
MessageReceived() BWindow version
MessageReceived() BHandler version
message
message
Trang 12void MyHelloWindow::MessageReceived(BMessage* message)
void MyHelloWindow::MessageReceived(BMessage* message)
The particular code that appears under the control’s case label depends entirely
on what action you want to occur in response to the control being clicked Forsimplicity, assume that we want a click on the OK button to do nothing more thansound a beep The completed version of MessageReceived() looks like this:
Trang 13oper-Creating a Button
The BButton constructor has six parameters, each of which was described in the
“The BButton class” section of this chapter:
BButton(BRect frame,
const char *name,
const char *label,
BMessage *message,
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_WILL_DRAW | B_NAVIGABLE)
The BButton constructor calls the BControl constructor, which in turn calls theBView constructor Together, these routines set up and initialize a BButton object.After attaching the button to a window, the height of the button may automati-cally be adjusted to accommodate the height of the text of the button’s label andthe border of the button If the values of the frame rectangle coordinates result in
a button that isn’t high enough, the BButton constructor will increase the buttonheight by increasing the value of the frame rectangle’s bottom value The exactheight of the button depends on the font in which the button label is displayed.For the example button creation code, assume that a window is keeping track ofBViewand BButton objects in data members named fView and fButton, respec-tively, and that the button’s message type is defined by the constant BUTTON_MSG:
#define BUTTON_MSG 'bttn'
class MyWindow : public BWindow {
Trang 14fButton = new BButton(buttonRect, "MyButton",
"Click Me", new BMessage(BUTTON_MSG));
fView->AddChild(fButton);
Making a Button the Default Button
One button in a window can be made the default button—a button that the usercan select either by clicking or by pressing the Enter key If a button is the defaultbutton, it is given a wider border so that the user recognizes it as such a button
To make a button the default button, call the BButton member functionMakeDefault():
fButton->MakeDefault(true);
If the window that holds the new default button already had a default button, theold default button automatically loses its default status and becomes a “normal”button The system handles this task to ensure that a window has only one defaultbutton
While granting one button default status may be a user-friendly gesture, it mightalso not make sense in many cases Thus, a window isn’t required to have adefault button
Button Example Project
The TwoButtons project demonstrates how to create a window that holds two tons Looking at Figure 6-4, you can guess that a click on the leftmost button(which is the default button) results in the playing of the system sound a singletime, while a click on the other button produces the beep twice
but-Preparing the window class for the buttons
A few additions to the code in the MyHelloWindow.h file are in order First, a pair
of constants are defined to be used later when the buttons are created The choice
of constant names and values is unimportant, provided that the names don’t beginwith “B_” and that the constant values don’t consist of all uppercase characters
Trang 15Buttons 191
#define BUTTON_BEEP_1_MSG 'bep1'
#define BUTTON_BEEP_2_MSG 'bep2'
To keep track of the window’s two buttons, a pair of data members of typeBButtonare added to the already present data member of type MyDrawView Andnow that the window will be receiving and responding to application-definedmessages, the BWindow-inherited member function MessageReceived() needs tooverridden:
class MyHelloWindow : public BWindow {
public:
MyHelloWindow(BRect frame);
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
Creating the buttons
The buttons are created and added to the window in the MyHelloWindow structor Before doing that, the constructor declares several variables that will beused in the pair of calls to the BButton constructor and assigns them values:
con-BRect buttonBeep1Rect(20.0, 60.0, 110.0, 90.0);
BRect buttonBeep2Rect(130.0, 60.0, 220.0, 90.0);
const char *buttonBeep1Name = "Beep1";
const char *buttonBeep2Name = "Beep2";
const char *buttonBeep1Label = "Beep One";
const char *buttonBeep2Label = "Beep Two";
In the past, you’ve seen that I normally declare a variable within the routine thatuses it, just before its use Here I’ve declared the six variables that are used asBButton constructor arguments outside of the MyHelloWindow constructor—butthey could just as well have been declared within the MyHelloWindow construc-tor I opted to do things this way to get in the habit of grouping all of a window’s
Figure 6-4 The window that results from running the TwoButtons program
Trang 16layout-defining code together Grouping all the button boundary rectangles,names, and labels together makes it easier to lay out the buttons in relation to oneanother and to supply them with logical, related names and labels This technique
is especially helpful when a window holds several controls
The buttons will be added to the fMyView view Recall that this view is of theBView-derived application-defined class MyDrawView and occupies the entire con-tent area of a MyHelloWindow In the MyHelloWindow constructor, the view iscreated first, and then the buttons are created and added to the view:
Handling button clicks
MessageReceived() always has a similar format The Application Server passesthis function a message as an argument The message data member what holdsthe message type, so that data member should be examined in a switch state-ment, with the result compared to any application-defined message types the win-dow is capable of handling A window of type MyHelloWindow can handle aBUTTON_BEEP_1_MSGand a BUTTON_BEEP_2_MSG If a different type of message isencountered, it gets passed on to the BWindow version of MessageReceived():
void MyHelloWindow::MessageReceived(BMessage* message)
Trang 17The BPictureButton class is used to create a picture button Associated with oneBPictureButtonobject are two BPicture objects One of the pictures acts as thebutton when the button is in its normal state (that is, when the user isn’t clicking
on it) The other picture acts as the button when the user clicks on the button.You’ll supply a BPictureButton object with the two pictures, and the system will
be responsible for switching back and forth between the pictures in response tothe user’s actions
Creating a Picture Button
A picture button is created by the BPictureButton constructor As is the case forother controls, this constructor invokes the BControl constructor, which in turninvokes the BView constructor:
uint32 behavior = B_ONE_STATE_BUTTON,
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_WILL_DRAW | B_NAVIGABLE)
The BPictureButton constructor has eight parameters, five of which you’realready familiar with The frame, name, resizingMode, and flags parametersget passed to the BView constructor and are used in setting up the picture button
as a view The message parameter is used by the BControl constructor to assign
a message type to the picture button The remaining three parameters, off, on,and behavior, are specific to the creation of a picture button
Trang 18The off and on parameters are BPicture objects that define the two pictures to
be used to display the button In Chapter 5, you saw how to create a BPictureobject using the BPicture member functions BeginPicture() andEndPicture() Here I create a picture composed of a white circle within a blackcircle:
For more compelling graphic images, you can use bitmaps for
but-ton pictures Once a bitmap exists, all that needs to appear between
the BeginPicture() and EndPicture() calls is a call to the BView
member function DrawBitMap() Chapter 10, Files, discusses
bit-maps.
Picture buttons are actually more versatile than described in this section Here thepicture button is treated as a one-state device—just as a standard push button is.The BPictureButton class can also be used, however, to create a picture buttonthat is a two-state control Setting the behavior parameter to the constant B_TWO_STATE_BUTTON tells the BPictureButton constructor to create a picture buttonthat, when clicked on, toggles between the two pictures represented by theBPictureparameters off and on Clicking on such a picture button displays onepicture Clicking on the button again displays the second picture The displayedpicture indicates to the user the current state of the button To see a good real-world use of a two-state picture button, run the BeIDE Then choose Find fromthe Edit menu In the lower-left area of the Find window you’ll find a button thathas a picture of a small file icon on it Click on the button and it will now have apicture of two small file icons on it This button is used to toggle between twosearch options: search only the currently open, active file, and search all filespresent in the Find window list Figure 6-5 shows both of this button’s two states
Trang 19Picture Buttons 195
Picture Button Example Project
The PictureButton project creates a program that displays a window that holds asingle picture button Figure 6-6 shows this one window under two different con-ditions The leftmost window in the figure shows the button in its normal state.The rightmost window shows that when the button is clicked it gets slightlysmaller and its center is filled in
The picture button can include other pictures, which will be used if
the program lets the button be disabled Now that you know the
basics of working with the BPictureButton class, the details of
enhancing your picture buttons will be a quick read in the
BPictureButton section of the Interface Kit chapter of the Be
Book.
Figure 6-5 The Find window of the BeIDE provides an example of a picture button
Figure 6-6 The window that results from running the PictureButton program
The two states of the same
picture button
Trang 20Preparing the window class for the picture button
This chapter’s TwoButtons example project (presented in the “Buttons” section)provided a plan for adding a control, and support of that control, to a window
Here’s how the window class header file (the MyHelloWindow.h file for this
project) is set up for a new control:
• Define a constant to be used to represent an application-defined message type
• Override MessageReceived() in the window class declaration
• Add a control data member in the window class declaration
Here’s how the MyHelloWindow class is affected by the addition of a picture ton to a window of this class type:
but-#define PICTURE_BEEP_MSG 'bep1'
class MyHelloWindow : public BWindow {
public:
MyHelloWindow(BRect frame);
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
private:
MyDrawView *fMyView;
BPictureButton *fPicButtonBeep;
};
I’ve defined the PICTURE_BEEP_MSG constant to have a value of
' bep1 ' Looking back at the TwoButtons example project, you’ll see
that this is the same value I gave to that project’s BUTTON_BEEP_1_
MSG constant If both controls were present in the same application,
I’d give one of these two constants a different value so that the
MessageReceived() function could distinguish between a click on
the Beep One push button and a click on the picture button.
Creating the picture button
The process of creating a control can also be expressed in a number of steps All
of the following affect the window source code file (the MyHelloWindow.cpp file
in this particular example):
• Declare and assign values to the variables to be used in the control’s structor
con-• Create the control using new and the control’s constructor
• Attach the control to the window by adding it to one of the window’s views
Trang 21Show();
}
The two BPicture objects are defined using a few of the basic drawing niques covered in Chapter 5 As you read the following, refer back to the picturebutton in its off state (normal, or unclicked) and on state (being clicked) inFigure 6-5
tech-The off picture fills in a rectangle with the B_SOLID_LOW pattern (solid white) toerase the on picture that might currently be displayed (if the user has just clicked
Trang 22the picture button, the on picture will be serving as the picture button) Then arectangle is outlined to serve as the off button.
The on picture erases the off picture (should it be currently drawn to the window
as the picture button) by drawing a white (B_SOLID_LOW) rectangle outline withthe boundaries of the off picture rectangle That rectangle is then inset two pixels
in each direction and a new rectangle is framed in black (B_SOLID_HIGH) Therectangle is then inset two more pixels, and this new area is filled with black
Handling a picture button click
To handle a click on the picture button, MessageReceived() now looks for amessage of type PICTURE_BEEP_MSG Should that message reach the window, thecomputer sounds the system beep one time:
void MyHelloWindow::MessageReceived(BMessage* message)
Whether a click results in a checkbox being turned on (checked) or off(unchecked), a message is sent to the window that holds the checkbox While aprogram can immediately respond to a click on a checkbox, it is more typical forthe program to wait until some other action takes place before responding Forinstance, the setting of some program feature could be done via a checkbox.Clicking the checkbox wouldn’t, however, immediately change the setting Instead,when the user dismisses the window the checkbox resides in, the value of thecheckbox can be queried and the setting of the program feature could be per-formed at that time
Trang 23Checkboxes 199
Creating a Checkbox
The BCheckBox constructor has six parameters:
BCheckBox(BRect frame,
const char *name,
const char *label,
BMessage *message,
uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_WILL_DRAW | B_NAVIGABLE)
The BCheckBox parameters match those used in the BButton constructor—if youknow how to create a button, you know how to create a checkbox Adding to thesimilarities is that after you attach the checkbox to a window, the control’s heightwill be automatically adjusted to accommodate the height of the text of the con-trol’s label If the values of the frame rectangle coordinates don’t produce arectangle with a height sufficient to display the checkbox label, the BCheckBoxconstructor will increase the checkbox boundary rectangle height by increasing thevalue of the frame rectangle’s bottom value The exact height of the checkboxdepends on the font in which the control’s label is displayed
As for other control types, you’ll define a message constant that is to be pairedwith the control For instance:
fCheckBox = new BCheckBox(checkBoxRect,"MyCheckbox"
"Check Me", new BMessage(CHECKBOX_MSG));
fMyView->AddChild(fCheckBox);
Checkbox (Action Now) Example Project
Clicking a checkbox may have an immediate effect on some aspect of the gram, or it may not have an impact on the program until the user confirms thecheckbox selection—usually by a click on a button The former use of a check-
Trang 24pro-box is demonstrated in the example project described here: CheckBoxNow For anexample of the other usage, a checkbox that has an effect after another action istaken, look over the next example, the CheckBoxLater project.
The use of a checkbox to initiate an immediate action is often in practice whensome area of the window the checkbox resides in is to be altered For instance, ifsome controls in a window are to be rendered unusable in certain conditions, acheckbox can be used to disable (and then later enable) these controls This ishow the checkbox in the CheckBoxNow example works The CheckBoxNowproject creates a program with a window that holds two controls: a button and acheckbox When the program launches, both controls are enabled, and the check-box is unchecked—as shown in the top window in Figure 6-7 As expected, click-ing on the Beep One button produces a single system beep Clicking on thecheckbox disables beeping by disabling the button The bottom window inFigure 6-7 shows how the program’s one window looks after clicking the DisableBeeping checkbox
Preparing the Window class for the checkbox
The MyHelloWindow.h file prepares for the window’s support of a button and a
checkbox by defining a constant for each control’s message:
#define BUTTON_BEEP_1_MSG 'bep1'
#define CHECKBOX_SET_BEEP_MSG 'stbp'
The MyHelloWindow class now holds three data members:
class MyHelloWindow : public BWindow {
public:
MyHelloWindow(BRect frame);
virtual bool QuitRequested();
virtual void MessageReceived(BMessage* message);
private:
Figure 6-7 The windows that result from running the CheckBoxNow program