Home

Win32 Controls: The Button

 

Introduction to Command Buttons

 

Description

A button is a Windows control used to initiate an action. From the userís standpoint, a button is useful when clicked, in which case the user positions the mouse on it and presses one of the mouseís buttons. There are various kinds of buttons. The most common and most regularly used is a rectangular object. In some programming environments, the classic button is called a command button. There are other controls that can serve as click controls and initiate the same behavior as if a button were clicked. Such controls include a label, a static control, or a panel.

 

Practical LearningPractical Learning: Introducing Buttons

  1. Start Embarcadero RAD Studio
  2. To create a new project, in the Tool Palette, click C++Builder Projects and double-click VCL Forms Application
  3. In the Object Inspector, change the following properties:
    Caption: Salary Estimation
    Name:    frmEstimation
    Position: poScreenCenter
  4. To save the project, on the Standard toolbar, click the Save All button
  5. Click the New Folder button
  6. Type SalaryEstimation1 as the name of the folder and press Enter twice to select it
  7. Type Estimation as the name of the unit and click Save
  8. Type SalaryEstimation as the name of the project and click Save
  9. Design the form as follows:

    Salary Estimation
    Control Alignment Caption Name Text
    TLabel Directory List Box   Hourly Salary:    
    TEdit Edit taRightJustify   edtHourlySalary 0.00
    TLabel Directory List Box   &Daily Salary:    
    TEdit Edit  taRightJustify   edtDailySalary 0.00
    TLabel Directory List Box   Weekly Salary:    
    TEdit Edit  taRightJustify 0.00 edtWeeklySalary 0.00
    TLabel Directory List Box   Biweekly Salary:    
    TEdit Edit taRightJustify   edtBiweeklySalary 0.00
    TLabel Directory List Box   Monthly Salary:    
    TEdit Edit  taRightJustify   edtMonthlySalary 0.00
    TLabel Directory List Box   Yearly Salary:    
    TEdit Edit taRightJustify   edtYearlySalary 0.00
  10. Save all

Creating a Button

To support the command button, the VCL provides a class named TButton. The TButton class is derived from TCustomButton. The TCustomButton class is derived from a class named TButtonControl, which is of TWinControl type:

TButton Inheritance

Both the TCustomButton and the TButton classes are members of the StdCtrls library.

To visually create a button, in the Standard section of the Tool Palette, click the TButton control TButton and click a container. The container could be a form, a frame, etc. To programmatically get a button, create a pointer to TButton. Here is an example:

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
	TButton *btnSubmit;
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

To initialize the variable, specify its owner in the constructor; also specify its parent. Here is an example:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	btnSubmit = new TButton(Form1);
	btnSubmit->Parent = Form1;
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Creating Buttons

  1. In the Standard section of the Tool Palette, click TButton TButton
  2. Click the right side of the Hourly Salary edit box (the edit control on the right side of the Hourly Salary label)
  3. Again in the Standard section of the Tool Palette, click TButton TButton and click the right side of the Yearly Salary edit box

The Characteristics of a Command Button

 

The Caption of a Button

For a user, the only things important about a button are the message it displays and the action it performs. The default property of a button is the Caption: this is the word or group of words that display(s) on top of the control, showing the message that would direct the user as to what the button is used for. By default, after adding a button to a form, the Caption property of the Object Inspector has focus; this allows you to just type a caption.

 
When adding a button to a form, the Caption field would have focus only if the last action you performed on the Object Inspector was for a control that does not have Caption. If the last control you were working on has a Caption property but you were setting another property, when you add a button, the Caption field would not have focus.
 

The most popular captions are OK and Cancel. The OK caption is set for a form or a dialog box that informs the user of an error, an intermediary situation, or an acknowledgement of an action that was performed on the dialog that hosts the button. The Cancel caption is useful on a button whose main parent (the form) would ask a question or request a follow-up action from the user. Whenever a dialog box allows the user to dismiss it without continuing the action, you should provide a button with a Cancel caption.

The easiest way to change the caption on a control, on the Object Inspector, is to click the word Caption and type the desired text.

 

After adding a button to a form (by design or with code), you can change its caption with code by calling the TControl::Caption property. For example, you can change the caption of a button as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::ChangeButtonCaption()
{
	btnSubmit = new TButton(Form1);
	btnSubmit->Parent = Form1;

	btnSubmit->Caption = "Submit";
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Configuring the Buttons

  1. Change the properties of the buttons as follows:
     
    Salary Estimation
    Control Caption Name
    TButton TButton Estimate btnEstimate
    TButton TButton Close btnClose
  2. Save all

The Click Event

The most regular action the user performs on a button is to click it. Based on this, the default event on a button is OnClick. To visually initiate the OnClick event on a button, you can double-click it. If you programmatically create the button, create a method that will handle its OnClick event. Pass a TObject pointer to the method. Here is an example:

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
private:	// User declarations
	TButton *btnSubmit;
	__fastcall void SubmitClicked(TObject *Sender);
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Implement the method, then assign it to the OnClick property of the button. Here is an example:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	btnSubmit = new TButton(Form1);
	btnSubmit->Parent = Form1;

	btnSubmit->Caption = "Submit";
	btnSubmit->OnClick = SubmitClicked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SubmitClicked(TObject *Sender)
{
	ShowMessage(L"The Submit button was clicked.");
}
//---------------------------------------------------------------------------

One of the most regular actions you will assign to a button is to close its parent form when the user clicks the button. There are different reasons you would want to close a form. If the form that hosts the button displays an intermediary message to the user, you should provide all the necessary code to follow up after the user has clicked the button; this is the case of property sheets or wizard pages, among others.

There are various ways you can close a dialog box from a button. The simplest way is to call the TCustomForm::Close() method. This dismisses the form. To close a form, you can also use the Win32 APIís PostQuitMessage() function. This function takes one argument that is an integer. The argument could be set to almost any integer value although it should be WM_QUIT.

The Button doest not have many methods to customize its behavior. This is because a button does not need more than what you would expect from it: point and click. Probably the only method you would use from a button is the constructor used to dynamically create a button. Most of the other methods used on a button are derived from member variables of the TWinControl class.

Practical LearningPractical Learning: Using the Buttons

  1. On the form, double-click the Estimate button
  2. Implement the OnClick event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmEstimation::btnEstimateClick(TObject *Sender)
    {
        double HourlySalary = 0.00;
        double DailySalary, WeeklySalary, BiweeklySalary,
    	   MonthlySalary, YearlySalary;
    
        try	{
    	// Get the value the user typed
    	HourlySalary = StrToFloat(this->edtHourlySalary->Text);
    
    	// Estimations
    	// Salary for 8-hour a day
    	DailySalary = HourlySalary * 8;
    	// Salary for 40 hours a week
    	WeeklySalary = HourlySalary * 40;
    	// Salary for 2 weeks
    	BiweeklySalary = WeeklySalary * 2;
    	// Salary for 1 month = 4 weeks = 20 days
    	MonthlySalary = WeeklySalary * 4;
    	// Salary for a year = 12 months
    	YearlySalary = MonthlySalary * 12;
    
    	// Show the results
    	this->edtDailySalary->Text = FloatToStrF(DailySalary,
    						 ffNumber, 6, 2);
    	this->edtWeeklySalary->Text = FloatToStrF(WeeklySalary,
    						  ffNumber, 6, 2);
    	this->edtBiweeklySalary->Text = FloatToStrF(BiweeklySalary,
    						    ffNumber, 6, 2);
    	this->edtMonthlySalary->Text = FloatToStrF(MonthlySalary,
    						   ffNumber, 6, 2);
    	this->edtYearlySalary->Text = FloatToStrF(YearlySalary,
    						  ffNumber, 6, 2);
        }
        catch(EConvertError *err)
        {
    	ShowMessage(err->Message + "\n"
    		   L"The value you entered for the "
    		   L"hourly salary is not acceptable.");
        }
    }
    //---------------------------------------------------------------------------
  3. Press F12 to display the form
  4. Double-click the Close button and implement its OnClick event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmEstimation::btnCloseClick(TObject *Sender)
    {
        this->Close();
    }
    //---------------------------------------------------------------------------
  5. Save all
  6. Press F9 to execute the application
  7. In the Hourly Salary edit control, type 22.85
  8. Click the Estimate button
     
    Salary Estimation
  9. Enter another value in the Hourly Salary edit box and click Estimate
     
    Salary Estimation
  10. Close the form and return to your programming environment

The Default Button

On a form or a dialog box, a button is said to be the default if its action would be activated if the user presses Enter. Such a button has a thick border.

To let you specify that a button would be the default, the TCustomButton class provides a Boolean property named Default:

__property bool Default = {read=FDefault,write=SetDefault};

If a form or dialog box has at least one button and you want to find out if a certain button is the default, get the value of its Default you property.

The Cancel Button

We already know that, to close a form or dialog box, you can call the TCustomForm::Close() method. Microsoft Windows provides a convenient means of closing a form or dialog box if you don't care about that changes that may have taken place on its own. The VCL supports this in a Boolean property named Cancel, which is a member of the TCustomButton class:

__property bool Cancel = {read=FCancel,write=FCancel};

To specify that a button will be used to close a dialog box following the above description, set its Cancel property to True. To close the dialog box, the user can simply press the Esc key. To find out whether a button is set to cancel a dialog box, get the value of its Cancel property.

The Modal Result of a Button

As mentioned already, a dialog box can be created with one or more buttons. If you create a modal dialog box and equip it with more than one button, when the user closes it, you must know what button the user had clicked. To support this, the VCL provides the ModalResult property. This property autonomously can control the behavior of the closing dialog box depending on the button that was clicked.

The ModalResult property is an integer defined as TModalResult and provides various values that each can be used on a button of a dialog box. To set the desired value, after adding a button to a dialog box and while the button is selected, on the Object Inspector, access its ModalResult property and select the desired value.

Modal Result

The possible values of the ModalResult property are:

Constant Value Description
mrNone 0 No special role
mrOk idOK The user clicked OK or pressed Enter (assuming the button has the Default property set to true) to close
mrCancel idCancel The used clicked Cancel or pressed Esc (assuming the button has the Cancel property set to true) to close
mrAbort idAbort The user clicked Abort to close
mrRetry idRetry The user clicked Retry to close
mrIgnore idIgnore The user clicked Ignore to close
mrYes idYes The user clicked Yes to close
mrNo idNo The user clicked No to close
mrAll mrNo + 1 The user clicked All to close
mrNoToAll mrAll + 1 The user clicked No To All to close
mrYesToAll mrNoToAll + 1 The user clicked Yes To All to close

If the form that is hosting the button is not the first form or dialog (in other words, if the form is accessed by a call from another form), you can use the ModalResult property to conveniently associate an action. By default, the ModalResul is set to mrNone.

The ModalResult property is an integer that represents a button that the user has clicked on a dependent dialog box. To use a button as a valid integral ModalResult value, set its ModalResult property. When coding the result of the user clicking one of the buttons, call the TForm::ShowModal() method (once again, the ShowModal() method actually belongs to the TCustomForm class) and assign it the corresponding value of the TModalResult integer.

The following example uses two forms. The first form has a button used to call the second. The second form has buttons with different ModalResult values. After the user clicks the button on the first form, the second would display, the program simply finds out what button was clicked, and the programmer can act accordingly:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	if( Form2->ShowModal() == mrOk )
		Caption = "I am OK now";
	else if( Form2->ShowModal() == mrCancel )
		Caption = "Soldier, dismiss!!!";
	else
	{
		Form2->Close();
		Caption = "What happened? Where are you?";
	}
}
//---------------------------------------------------------------------------

A Picture on a Button

 

Introduction

Besides, or instead of, a caption, you can display a picture on a button. To make it possible, the TCustomButton class is equipped with the Images property:

__property Imglist::TCustomImageList * Images = {read=FImages,write=SetImages};

As you can see, you must first have an image list, which you can visually or programmatically create. Once you have an image list, assign it to the Images property of the button. To actually use the image(s), you have many options.

Practical LearningPractical Learning: Introducing Picture Buttons

  1. To create a new project, on the main menu, click File -> New -> VCL Forms Application - C++Builder
  2. In the Object Inspector, change the following properties:
    Caption: Simple Interest
    Name:    frmCalculation
    Position: poScreenCenter
  3. To save the project, on the Standard toolbar, click the Save All button
  4. Click the New Folder button
  5. Type SimpleInterest1 as the name of the folder and press Enter twice to select it
  6. Type Calculation as the name of the unit and click Save
  7. Type SimpleInterest as the name of the project and click Save
  8. Design the form as follows:

    Simple Interest
    Control Name Caption/Text Other Properties
    TBevel TBevel      
    TLabel Directory List Box   &Principal:  
    TEdit Edit edtPrincipal 0.00 Alignment: taRightJustify
    TLabel Directory List Box   &Interest Rate:  
    TEdit Edit edtInterestRate 0.00 Alignment: taRightJustify
    TLabel Directory List Box   %  
    TLabel Directory List Box   P&eriods:  
    TEdit Edit edtPeriods 0.00 Alignment: taRightJustify
    TLabel Directory List Box   Months  
    TButton TBitBtn btnCalculate C&alculate  
    TBevel TBevel      
    TLabel Directory List Box   Interest Earned:  
    TEdit Edit edtInterestEarned 0.00 Alignment: taRightJustify
    TLabel Directory List Box   Future Value:  
    TEdit Edit edtFutureValue 0.00 Alignment: taRightJustify
    TButton TBitBtn btnClose Close  

Assigning an Image to a Button

To set the picture that should display on the button, specify its index using the ImageIndex property.

Practical LearningPractical Learning: Assigning an Image to a Button

  1. In the Win32 section of the Tool Palette, click Win32 and click the form
  2. Double-click the image list
  3. From the resources that accompany these lessons, select the Calculate.bmp and the Exit1.bmp bitmaps
  4. On the form, click the Calculate button
  5. In the Object Inspector, change the following properties:
    Image: ImageList1
    ImageIndex: 0
  6. On the form, click the Close button
  7. In the Object Inspector, change the following properties:
    Image: ImageList1
    ImageIndex: 2
  8. Save all

The Image Alignment

To align the picture with regards to the client area of the button, you use the the ImageAlignment property, which is of type TImageAlignment:

__property Stdctrls::TImageAlignment ImageAlignment =
{
	read=FImageAlignment,
	write=SetImageAlignment
};

The TImageAlignment enumeration has the following members:

enum TImageAlignment{
	iaLeft,
	iaRight,
	iaTop,
	iaBottom,
	iaCenter
};

You can use a combination of the caption and the image or omit one of them. If you don't use a caption, you can use picture-only button where the image must indicate the role of the button to the user.

The Image Margin

If you decide to display both the caption and the picture on a button, in some cases, the image may appear too far from the caption, especially if the button is big. In some other cases, mostly when the ImageAlignment property is set to a value other than iaCenter, the image may appear too close to the border of the button, up to touching the border and consequently hiding part of the image. If you want, you can change the margin of the image. To let you specify the margin amount, the TCustomButton class provides the ImageMargins property that is of type TImageMargins:

__property Stdctrls::TImageMargins * ImageMargins = 
{
	read=FImageMargins,
	write=SetImageMargins
};

TImageMargins is a simple class derived from TPersistent. It is only equipped with four properties named Bottom, Left, Right, Top, and an event named OnChange. Each of the properties is of type int. To specify a margin amount for the picture of a button, access the desired TImageMargins property from the ImageMargins property of the button and assign the desired value:

Image Margin

Practical LearningPractical Learning: Using a Button

  1. On the form, double-click the Calculate button
  2. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmCalculator::Button1Click(TObject *Sender)
    {
    	double Principal    = 0.00,
    		   InterestRate = 0.00,
    		   InterestEarned,
    		   FutureValue,
    		   Periods = 0.00;
    
    	try	{
    		   Principal = StrToFloat(edtPrincipal->Text);
    	}
    	catch(EConvertError *err)
    	{
    		   ShowMessage(L"The value you entered for the "
    					   L"principal is not valid");
    	}
    
    	try	{
    		   InterestRate = StrToFloat(edtInterestRate->Text);
    	}
    	catch (EConvertError *err)
    	{
    		   ShowMessage(L"Wrong Value: The interest rate must "
    					   L"be a value between 0 and 100");
    	}
    
    	try	{
    		   Periods = StrToFloat(edtPeriods->Text);
    	}
    	catch (EConvertError *err)
    	{
    		  ShowMessage(L"You entered an invalid value for the periods");
    	}
    
    	double I = InterestRate / 100;
    	double p = Periods / 12;
    	InterestEarned = Principal * I  * p;
    	FutureValue    = Principal + InterestEarned;
    
    	TVarRec ie[1] = { InterestEarned };
    	edtInterestEarned->Text = Format(L"%8.2f", ie, 2);
    
    	TVarRec fv[1] = { FutureValue };
    	edtFutureValue->Text = Format(L"%8.2f", fv, 2);
    }
    //---------------------------------------------------------------------------
  3. Return to the form and double-click the Close button
  4. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmCalculator::btnCloseClick(TObject *Sender)
    {
    	Close();
    }
    //---------------------------------------------------------------------------
  5. Save all
  6. Press F9 to execute the application
     
    Simple Interest
     
    Simple Interest
  7. Close the form and return to your programming environment

The Styles of a Button

Microsoft Windows Vista introduced new features to command buttons. It makes it possible for a button to appear with either a link or a menu, increasing its usefulness and aesthetics. This is done through a style.

To let you specify the style of a button, the TCustomButton class is equipped with the Style property, which is of type TButtonStyle. It gives you three options. The buttons we have used so far are referred to as push buttons. To support this type, the TButtonStyle enumeration has the bsPushButton member. This the default value of the Style property. To use another style, access the Style property of the button and and change its value.

 
 
 
 

Home Copyright © 2010-2011 FunctionX, Inc.