Topic : Buttons
Author : Unknown
Page : 1 Next >>
Go to page :


Buttons


Button is one of the most commonly used controls, almost every application needs to include one or more buttons. It seems that it is very easy to implement a standard button in a dialog box: all we need to do is adding a button resource to the dialog template, then using Class Wizard to generate message handlers. However, it is not very easy to further customize button's default properties.

In this chapter, we will discuss how to implement different type of customized buttons. At the end of this chapter, we will be able to include some eye-catching buttons in our applications.

1 Bitmap Button: Automatic Method

Generally, buttons display plain text on its interface. Sometimes it is more desirable to let them have graphic user interface. A typical application that uses this type of buttons would be a CD player, everyone would like the play button to have a graphic interface instead of just displaying text such as "play", "stop" (so that it looks like a real "play" button).

Button States

Before customizing button's default feature, it is important for us to understand some basics of buttons. Every button has four states. When a button is not clicked, is in "up" state (the most common state). When it is pressed down, it is in "down" state. To emphasis a button's 3D effect, a default button will recess when it is pressed by the mouse. Also, a button could be disabled, in this state, the button will not respond to any mouse clicking (As the default implementation, when a button is disabled, it will be drawn with "grayed" effect). Finally, a button has a "focused" or "unfocused" state. In the "focused" state, the button is an active window, and is accessible through using keyboard (ENTER or downward ARROW key). For the default implementation, a rectangle with dashed border will be drawn over a button's face when it has the current focus.

Owner-Draw Bitmap Button

We can use owner draw bitmap button to add graphics to the button. To distinguish among different states, we need to associate different states with different images if necessary.

The simplest way to create this type of button is to implement bitmap button using class CBitmapButton. To create a bitmap button, first we must set its "Owner Draw" style. This can be implemented by checking "Owner Draw" check box in the "Push Button Properties" property sheet when creating the button resource (We need to add button resource in order to create button, this is the same with a normal button. See Figure 4-1). For an owner-draw button, message WM_DRAWITEM will be sent to the button when it needs to be painted (remember, a button is also a window that can receive message). Upon receiving this message, the button will be drawn by the overridden function. For non-owner-draw button, its interface is implemented by the default method, and will display a plain text on the button's face.

Class CBitmapButton handles message trapping and processing; also, it contains member functions that can be used to paint the button. If we use this class to implement bitmaps buttons, all we need to do is preparing some bitmap resources, declaring variables using class CBitmapButton, and associating bitmap resources with the corresponding buttons.

Although every button has four states, we do not need to provide four bitmaps all the time. If one of the bitmaps is not available, class CBitmapButton will draw the button's corresponding state using the default bitmap, which is the bitmap associated with button's "up" state. So the bitmap used to represent a button's "up" state is required all the time and can not be omitted.

Automatic Method

We have two ways of associating bitmap images with different states of a bitmap button: we can either let class CBitmapButton handle this automatically or we can do it manually. To use the automatic method, the IDs of all four bitmap resources must be text strings, and must be formed by suffixing one of the following four letters to the button's caption text: 'U', 'D', 'F', 'X'. These letters represent "up", "down", "focused" and "disabled" state respectively. By naming the resource IDs this way, the rest thing we need to do is calling function CBitmapButton::AutoLoad() in the dialog box's initialization stage (within member function CDialog::OnInitDialog()). Please note that we cannot call this function in the constructor of class CDialog. At that time, the dialog box window is still not created (Therefore, the buttons are still not available), and the bitmaps cannot be associated with the button correctly.

Sample

Sample 1\Btn demonstrates how to create bitmap button using automatic method. It is a dialog-based application that is generated by the Application Wizard. First, the ID of default dialog template is changed to IDD_DIALOG_BTN. Also, the "OK" and "Cancel" buttons originally included in the template are deleted. Then a new button IDC_PLAY is added, whose caption text is set to "Play" (Figure 4-2). Since the button will be drawn using the bitmaps, it doesn't matter how big the button resource is. Besides this, we need to set button's style to "Owner draw".

Two bitmap resources are added to the application whose IDs are "PLAYU" and "PLAYD" respectively (Figure 4-3). They correspond to button's "up" and "down" states. In addition, the sizes of the two bitmaps are exactly the same.

A CBitmapButton type variable is declared in class CBtnDlg to implement this bitmap button:

class CBtnDlg : public CDialog

{

......

protected:

......

CBitmapButton m_btnPlay;

......

};


Within function CBtnDlg::OnInitDialog(), function CBitmapButton::AutoLoad(...) is called to initialize the bitmap button and associate it with the corresponding bitmap resources. After this call, we don't need to do anything. The bitmap button will be created and its states will be set automatically:

BOOL CBtnDlg::OnInitDialog()

{

......

m_btnPlay.AutoLoad(IDC_PLAY, this);

......

}


Function CBitmapButton::AutoLoad(...) has two parameters, first of which is the button's resource ID, and the second is a pointer to the button's parent window.

In the sample application only two bitmap images are prepared. We may add two other bitmaps whose IDs are "PLAYF" and "PLAYX". Then we can enable or disable the button to see what will happen to the button's interface.

2 Bitmap Check Box and Radio Button: Method 1

The bitmap button implemented this way behaves like a push button. Unfortunately, in MFC, there is no class such as CBitmapCheckBox and CBitmapRadioButton to let us implement bitmap check box or radio button. However, check box and radio button are another two types of buttons, both of them can be implemented using class CButton.

A button implemented by class CButton can display either plain text or bitmap. Actually, there is a member function of CButton that allows us to associate button with a bitmap: CButton::SetBitmap(...).

If a button implemented by class CButton can also be associated with a bitmap, what is the difference between CBitmapButton and CButton? First, CBitmapButton is derived from CButton, so it has more features than CButton. For example, with CBitmapButton, we can use automatic method to associate button with bitmap resources by calling function CBitmapButton::AutoLoad(...). Second, CButton allows only one bitmap to be associated with a button at any time, and it always implement the focus state of the button by drawing a dash-bordered rectangle over button's face.

Although only one bitmap could be associated with a button at any time, we still can manage to represent a button's different states using different bitmaps.

The trick here is to change button's associated bitmap whenever its state changes. To achieve this, we must implement a WM_COMMAND message handler for the button. For example, in the case of check box, we can find out whether the current state of the check box is "Checked" or "Unchecked". Based on this information, we can decide which bitmap should be used.

Sample 2\Btn demonstrates the above method. It is based on sample 1\Btn. In the sample, three new buttons are added: one of them is implemented as a check box; the rest are implemented as radio buttons. The following describes how the bitmap check box and radio buttons are implemented in the sample:

1) Add a check box and two radio buttons to the dialog template. Name the IDs of new controls IDC_CHECK, IDC_RADIO_A and IDC_RADIO_B respectively. In the property sheet that lets us customize control's properties, check "Bitmap" check box (Figure 4-4).

(Figure omitted)

2) Add two bitmap resources, one for checked state and one for unchecked state. Their resource IDs are ID_BITMAP_CHECK and ID_BITMAO_UNCHECK respectively. The bitmaps must have a same size.

3) Declare two CBitmap type variables m_bmpCheck and m_bmpUnCheck in class CBtnDlg, in function CBtnDlg::OnInitDlg(), call CBitmap::LoadBitmap(...) to load the two bitmap resources. Then call function CButton::SetBitmap(...) to set bitmap for the check box and radio buttons. In the sample, all of the new controls are initialized to unchecked state (In order to do this, we need to associate buttons with m_bmpUnCheck instead of m_bmpCheck). The following code fragment shows the modified class CBtnDlg and the function CBtnDlg::OnInitDialog(...):

(Code omitted)

4) Declare a new member function CBtnDlg::SetCheckBitmap(...). We will use it to set a button's bitmap according to its current state. The function has one parameter nID that identifies the control. Within the function, first the button's current state is examined, if it is

Page : 1 Next >>