VCLBook

Download as pdf or txt
Download as pdf or txt
You are on page 1of 462

Table of Contents Borland C++ Builder

Table of Contents

CONVENTIONS USED IN THIS BOOK.................................................... 8


The Mouse ............................................................................................. 8
The Keyboard ........................................................................................ 9
Words and Acronyms ............................................................................ 9

CHAPTER 1: BORLAND C++ BUILDER IDE........................................ 10


1.1 Introduction to Borland C++ Builder ............................................ 11
1.1.1 Launching Borland C++ Builder............................................. 11
1.2 Integrated Development Environment........................................... 12
1.2.1 The Title Bar ........................................................................... 12
1.2.2 The Main Menu....................................................................... 12
1.2.3 The Toolbars ........................................................................... 14
1.2.4 The Component Palette........................................................... 16
1.2.5 The Starting Form ................................................................... 16
1.2.6 The Code Editor...................................................................... 17
1.2.7 The Class Explorer.................................................................. 18
1.2.8 The Object Inspector............................................................... 19
1.3 Introduction to C++ ....................................................................... 19
1.3.1 Executing Programs ................................................................ 19
1.3.2 Saving A Project ..................................................................... 20
1.4 Borland C++ Builder Help ............................................................ 20
1.4.1 Online Help............................................................................. 20
1.4.2 Internet Help ........................................................................... 21

CHAPTER 2: APPLICATIONS FUNDAMENTALS............................... 22


2.1 Introduction to Applications .......................................................... 23
2.1.1 Creating Applications ............................................................. 23
2.1.2 Design and Run Times............................................................ 23
2.2 The Form ....................................................................................... 24
2.2.1 Creating a Form ...................................................................... 24
2.2.2 Form Design ........................................................................... 25
2.3 Designing the User Interface ......................................................... 26
2.3.1 Adding Controls to a Form ..................................................... 27
2.3.2 Selecting Controls ................................................................... 30
2.3.3 Moving Controls ..................................................................... 33
2.3.4 Resizing Controls.................................................................... 35
2.4 Introduction to Controls Properties ............................................... 36
2.4.1 Setting Properties .................................................................... 36
2.4.2 Form Properties....................................................................... 38
2.4.3 Form Navigation ..................................................................... 45
2.5 Controls Events ............................................................................. 47
2.5.1 Mouse Events.......................................................................... 48
2.5.2 Keyboard Events ..................................................................... 50
2.5.3 Other Events............................................................................ 50
2.5.4 Controlling and Programming Events..................................... 50
2.5.5 The Structure of an Event ....................................................... 51
2.5.6 Form Events ............................................................................ 52

1 © FunctionX, Inc.
Table of Contents Borland C++ Builder

2.6 Dynamic Forms ............................................................................. 56


2.6.1 Dynamic Local Forms............................................................. 56
2.6.2 Dynamic Global Forms........................................................... 57
2.6.3 Customizing Dynamic Forms ................................................. 58
2.7 Form’s Scroll Bars......................................................................... 59
2.7.1 The Form’s Scroll Bars Properties.......................................... 60
2.7.2 The TControlScrollBar Class.................................................. 61
2.7.3 TControlScrollBar Methods.................................................... 62
2.8 Exercises.........................................Error! Bookmark not defined.

CHAPTER 3: FUNDAMENTAL CONTROLS ........................................ 63


3.1 Command Buttons ......................................................................... 64
3.1.1 The Command Button............................................................. 64
3.1.2 Button Properties .................................................................... 64
3.1.3 Button Events.......................................................................... 68
3.1.4 Button Methods....................................................................... 74
3.1.5 Dynamic Buttons .................................................................... 74
3.2 Bevels ............................................................................................ 75
3.2.1 Bevel Properties ...................................................................... 75
3.2.2 Bevel Methods ........................................................................ 77
3.3 The Panel Control.......................................................................... 78
3.3.1 The Panel and its Properties.................................................... 78
3.4 Affiche........................................................................................... 81
3.5 Exercises........................................................................................ 83

CHAPTER 4: INTRODUCTION TO TEXT CONTROLS...................... 84


4.1 The Label Control.......................................................................... 85
4.1.1 Label Properties ...................................................................... 85
4.1.2 Label Methods ........................................................................ 89
4.1.3 Label Events............................................................................ 90
4.2 Edit Boxes ..................................................................................... 91
4.2.1 Edit Box Properties ................................................................. 91
4.2.2 Edit Control Methods and Events ........................................... 93
4.2.3 Keyboard Events: Another Review......................................... 93
4.3 The MaskEdit Control ................................................................... 97
4.3.1 MaskEdit Properties................................................................ 97
4.3.2 MaskEdit Methods ................................................................ 101
4.3.3 MaskEdit Events ................................................................... 102
4.4 The Memo Control ...................................................................... 102
4.4.1 Memo Properties................................................................... 102
4.4.2 Memo Methods ..................................................................... 105
4.4.3 Memo Events ........................................................................ 108

CHAPTER 5: A STUDY OF VCL STRINGS ........................................ 109


5.1 Constructing Strings .................................................................... 110
5.1.1 Declaring a String ................................................................. 110
5.1.2 Initializing a String ............................................................... 110
5.2 General Purpose String Functions ............................................... 111
5.2.1 Checking Whether a String is Empty.................................... 111
5.2.2 Trimming a String Left ......................................................... 112
5.2.3 Trimming a String Right ....................................................... 112
5.2.4 Trimming a String on Both Sides.......................................... 113
5.3 Fundamental String Conversions................................................. 113
5.3.1 Converting Regular Data Types to AnsiString ..................... 114

2 © FunctionX, Inc.
Table of Contents Borland C++ Builder

5.3.2 AnsiString and C-Strings ...................................................... 115


5.3.3 Requesting an AnsiString From the User.............................. 115
5.4 Changing Strings Cases ............................................................... 116
5.4.1 Converting from Lowercase to Uppercase............................ 116
5.4.2 Converting from Uppercase to Lowercase............................ 118
5.5 Adding and Appending Strings ................................................... 119
5.5.1 Using the + Operator............................................................. 119
5.5.2 Appending Strings ................................................................ 120
5.6 Strings and their Length .............................................................. 121
5.6.1 Getting the Length of a String............................................... 121
5.6.2 Controlling the Length of a String ........................................ 121
5.7 Strings Comparison Functions..................................................... 122
5.7.1 Checking the Same Text ....................................................... 122
5.7.2 String Comparison With Case-Sensitivity ............................ 123
5.7.3 String Comparison With Case-Insensitivity.......................... 124
5.8 Strings Boolean Comparisons...................................................... 125
5.8.1 Getting the Same String ........................................................ 125
5.8.2 AnsiString Boolean Operators .............................................. 126
5.8.3 Operations on Strings............................................................ 127
5.8.4 AnsiString Individual Characters.......................................... 128
5.8.5 Last Character of a String ..................................................... 128
5.8.6 Deleting Characters............................................................... 128
5.9 String Quotations......................................................................... 129
5.9.1 The AnsiQuotedStr Function ................................................ 129
5.9.2 Adding a Single Quote to a String ........................................ 129
5.9.3 Removing the Quotes on a String ......................................... 130
5.10 Working With Substrings .......................................................... 130
5.10.1 Getting a Substring.............................................................. 130
5.10.2 The Position of a Substring ................................................. 131
5.10.3 Console and AnsiString Objects ......................................... 131
5.10.4 Finding and Replacing a character or Substring ................. 132

CHAPTER 6: APPLICATIONS ACCESSORIES ................................. 133


6.1 WinHelp Anatomy....................................................................... 134
6.1.1 WinHelp Description ............................................................ 134
6.1.2 Creating The Source File ...................................................... 135
6.1.3 Creating Page Breaks ............................................................ 136
6.1.4 Topics Titles.......................................................................... 137
6.1.5 Creating Topic ID ................................................................. 137
6.1.6 Topics Keywords .................................................................. 138

CHAPTER 7: DIALOG BOXES............................................................... 139


7.1 C++ Dialog Boxes ....................................................................... 140
7.1.1 Creating a Dialog Box........................................................... 140
7.2 Windows Common Dialogs......................................................... 141
7.2.1 The Color Dialog Box........................................................... 142
7.3 Accessory Dialogs ....................................................................... 145
7.3.1 The Folder Browser .............................................................. 145
7.3.2 The Directory Selector .......................................................... 147
7.4 Message Boxes ............................................................................ 149
7.4.1 The ShowMessage Function ................................................. 149
7.4.2 The MessageBox Function.................................................... 151
7.4.3 The MessageDlg Function .................................................... 156
7.4.4 The MessageDlgPos Function .............................................. 158
7.4.5 The CreateMessageDialog .................................................... 159

3 © FunctionX, Inc.
Table of Contents Borland C++ Builder

7.4.6 The Input Dialog Box ........................................................... 161


7.4.7 The InputQuery Request ....................................................... 163

CHAPTER 8: THE MATH LIBRARIES................................................ 165


8.1 The Math Libraries ...................................................................... 166
8.1.1 Converting a String to an Integer: ToInt() ............................ 166
8.1.2 Converting a String to an Integer: StrToInt()........................ 167
8.1.3 Converting an Integer to String............................................. 167
8.1.4 Converting a String to a Float-Point Number ....................... 167
8.1.5 Formatting a Float to Display Decimals ............................... 168
8.2 Arithmetic Functions ................................................................... 169
8.2.1 Absolute Values .................................................................... 169
8.2.2 The Ceiling of Numbers........................................................ 170
8.2.3 The floor and the Floor Functions......................................... 172
8.2.4 The frexp(), the frexpl(), and the Frexp() Functions ............. 173
8.2.5 The Power Functions ............................................................ 174
8.2.6 The Exponential .................................................................... 176
8.2.7 The Ldexp functions ............................................................. 176
8.2.8 LnXP1................................................................................... 177
8.2.9 Log10 .................................................................................... 178
8.2.10 Log2 .................................................................................... 178
8.2.11 LogN ................................................................................... 179
8.2.12 The Square Root ................................................................. 179
8.3 Business Functions ...................................................................... 181
8.3.1 DoubleDecliningBalance ...................................................... 181
8.3.2 SLNDepreciation .................................................................. 183
8.3.3 SYDDepreciation .................................................................. 183
8.4 Finance Functions........................................................................ 185
8.4.1 The Future Value of an Investment....................................... 186
8.4.2 The Number of Periods of an Investment ............................. 187
8.4.3 Making an Investment or Paying a Loan .............................. 188
8.4.4 The Amount Paid as Principal .............................................. 189
8.4.5 The Present Value of an Investment ..................................... 190
8.4.6 The Amount Paid As Interest................................................ 190
8.4.7 The Interest Rate ................................................................... 191
8.4.8 The Internal Rate of Return .................................................. 192
8.4.9 NetPresentValue ................................................................... 194
8.5 Measurement Functions............................................................... 195
8.5.1 Pi ........................................................................................... 196
8.5.2 CycleToRad .......................................................................... 196
8.5.3 DegToRad ............................................................................. 197
8.5.4 RadToCycle .......................................................................... 198
8.5.5 RadToDeg............................................................................. 198
8.6 Statistics....................................................................................... 199
8.6.1 MaxIntValue ......................................................................... 199
8.6.2 MaxValue.............................................................................. 200
8.6.3 Mean ..................................................................................... 201
8.6.4 MinIntValue.......................................................................... 201
8.6.5 MinValue .............................................................................. 202
8.6.6 Sum ....................................................................................... 203
8.6.7 SumInt................................................................................... 204
8.6.8 SumOfSquares ...................................................................... 205
8.6.9 SumsAndSquares .................................................................. 206
8.7 Trigonotric Functions .................................................................. 207
8.7.1 The Cosine Functions ........................................................... 207

4 © FunctionX, Inc.
Table of Contents Borland C++ Builder

8.7.2 The Sine Functions ............................................................... 208


8.7.3 The Tangent Functions.......................................................... 209

CHAPTER 9: DATE AND TIME............................................................. 211


9.1 Dates............................................................................................ 212
9.1.1 Declaring a Date ................................................................... 212
9.1.2 The Date() Function .............................................................. 212
9.2 Date, String, and Numeric Conversions ...................................... 213
9.2.1 Converting a String to Date .................................................. 213
9.2.2 Converting a Date to a String................................................ 214
9.2.3 Converting a Date to a Double-Precision Number................ 215
9.2.4 Converting a Date to an Integer ............................................ 216
9.3 The Computer’s System of Displaying Dates.............................. 217
9.3.1 The Short Date Format.......................................................... 218
9.3.2 The Long Date Format.......................................................... 221
9.4 Using Dates ................................................................................. 222
9.4.1 Displaying Dates ................................................................... 222
9.4.2 Decoding a Date.................................................................... 223
9.4.3 Encoding a Date .................................................................... 225
9.4.4 Finding Out the Leap Year.................................................... 226
9.4.5 The Day of the Week ............................................................ 227
9.4.6 Increasing Months on a Date ................................................ 229
9.4.7 Replacing a Date ................................................................... 230
9.5 Comparison Operations on Dates ................................................ 231
9.5.1 The Comparison for Equality................................................ 231
9.5.2 The Comparison for Inequality ............................................. 232
9.5.3 The Comparison for Inferiority............................................. 233
9.5.4 The Comparison for Inferiority or Equality .......................... 234
9.5.5 The Comparison for Superiorty ............................................ 235
9.5.6 The Comparison for Superiority or Equality......................... 236
9.6 Operations on Dates..................................................................... 237
9.6.1 Assigning One Date to Another ............................................ 237
9.6.2 Adding Values to a Date ....................................................... 239
9.6.3 Assigning an Added Date ..................................................... 241
9.6.4 Subtracting Dates .................................................................. 242
9.6.5 Assigning a Subtracted Date ................................................. 244
9.6.6 Decrementing a Date............................................................. 244
9.6.7 Incrementing a Date .............................................................. 245
9.7 Formatting and Controlling the Display of Dates........................ 246
9.7.1 The Default Display .............................................................. 247
9.7.2 Displaying the Numeric Day................................................. 247
9.7.3 Displaying Weekday Names ................................................. 248
9.7.4 Displaying Numeric Months ................................................. 250
9.7.5 Displaying Months Names.................................................... 251
9.7.6 Displaying the Year .............................................................. 253
9.8 Doing Time.................................................................................. 254
9.8.1 Declaring Time Variables ..................................................... 255
9.8.2 The Time() Function ............................................................. 257
9.8.3 Converting a String to Time.................................................. 257
9.8.4 Converting a Time Value to a String .................................... 258
9.8.5 Converting a Time Value to a Double-Precision Number .... 259
9.9 Using Time .................................................................................. 260
9.9.1 Displaying the Time.............................................................. 260
9.9.2 Decoding a Time................................................................... 260
9.9.3 Encoding a Time ................................................................... 262

5 © FunctionX, Inc.
Table of Contents Borland C++ Builder

9.9.4 Replacing a Time Value........................................................ 263


9.10 Comparison Operations On Time Values.................................. 263
9.10.1 The Comparison for Equality.............................................. 264
9.10.2 The Comparison for Difference .......................................... 264
9.10.3 The Comparison for Previous Occurrence .......................... 265
9.10.4 The Comparison for Previous or Equal Occurrence............ 265
9.10.5 The Comparison for Subsequent Occurrence...................... 265
9.10.6 The Comparison for Latter or Same Time .......................... 266
9.11 Controlling Time Display.......................................................... 266
9.11.1 Displaying in Default Format.............................................. 267
9.11.2 Displaying the Leading Zero............................................... 267
9.12 Combining Date and Time ....................................................... 269
9.12.1 Fundamental Functions: Now()........................................... 269
9.12.2 Converting a String to Date and Time ................................ 269
9.12.3 Converting a Date and Time to a String.............................. 270

CHAPTER 10: USING C++ IN VCL APPLICATIONS ....................... 272


10.1 Programmer Defined Objects, Functions, and Variables........... 273
10.1.1 Programmer Defined Functions and Variables ................... 273
10.1.2 Local Variables ................................................................... 273
10.1.3 Local Functions................................................................... 276
10.2 Global Variables and Functions................................................. 284
10.2.1 The Karyne Restaurant Application.................................... 285
10.2.2 Designing the Application .................................................. 285
10.2.3 Coding the Application ....................................................... 292
10.3 Programmer Created Classes..................................................... 301

CHAPTER 11: PROGRESS CONTROLS ............................................. 302


11.1 The UpDown Control ................................................................ 303
11.1.1 The UpDown Control Properties ........................................ 303
11.1.2 The UpDown Methods........................................................ 305
11.1.3 The UpDown Control Events.............................................. 306
11.2 The Spin Button......................................................................... 310
11.2.1 The Spin Button Properties ................................................. 310
11.2.2 The Spin Button Methods ................................................... 310
11.2.3 The Spin Button Events ...................................................... 311
11.3 The Spin Edit Control................................................................ 312
11.3.1 The SpinEdit Properties ...................................................... 312
11.3.2 The Spin Edit Methods ....................................................... 312
11.4 Track Bars ................................................................................. 313
Trackbar Properties............................................................................ 313
11.4.1 Designing a Track Bar ........................................................ 315
11.4.2 Track Bar Events................................................................. 315
11.5 Progress Bars ............................................................................. 316
11.6 ScrollBars .................................................................................. 317
11.6.1 The ScrollBar Properties..................................................... 317
11.6.2 The ScrollBar Methods ....................................................... 320
11.6.3 Scroll Bar Events ................................................................ 321

CHAPTER 12: SELECTION CONTROLS............................................ 326


12.1 Selection Controls ..................................................................... 327
12.1.1 Descriptions ........................................................................ 327
12.1.2 Radio Button and Check Box Containers ........................... 328
12.2 Radio Buttons ............................................................................ 328

6 © FunctionX, Inc.
Table of Contents Borland C++ Builder

12.2.1 Adding a Radio Button ....................................................... 328


12.2.2 Radio Button Properties ...................................................... 329
12.2.3 Radio Buttons Methods....................................................... 334
12.2.4 Radio Button Events ........................................................... 335
12.3 Check Boxes.............................................................................. 338
12.3.1 Check Box Properties.......................................................... 339
12.3.2 Check Box Methods and Events ......................................... 341
12.3.3 Project: The Danilo Pizza Application................................ 342
12.4 Reviews ..................................................................................... 353
12.4.1 Exercises ............................................................................. 353

CHAPTER 13: LISTS CONTROLS......................................................... 355


13.1 List Boxes.................................................................................. 356
13.1.1 Creating a ListBox Control ................................................. 356
13.1.2 ListBox Properties............................................................... 356
13.1.3 ListBox Methods................................................................. 358
13.1.4 Operations on List Boxes .................................................... 362
13.2 Checked List Boxes ................................................................... 366
13.3 Combo Boxes ............................................................................ 366
13.3.1 Combo Box Properties ........................................................ 367
13.3.2 ComboBox Methods ........................................................... 374
13.3.3 Operations on Combo Box Using Events ........................... 375

CHAPTER 14: MANAGING VIEWS ...................................................... 390


1.1 Tree Views................................................................................... 391
14.1.1 Tree View Design ............................................................... 392
14.1.2 Code Creating a TreeView.................................................. 396
14.1.3 Adding Images to Nodes..................................................... 398
1.2 List Views.................................................................................... 400
14.1.4 List View Design ................................................................ 401
14.1.5 Code Creating a ListView................................................... 405
1.3 Splitter Bars ................................................................................. 408
1.4 Speed Buttons.............................................................................. 409
14.1.6 Creating and Designing Speed Buttons............................... 409

CHAPTER 15: LISTS CLASSES ............................................................. 411


15.1 Lists ........................................................................................... 412
1.1.1 Categories of Lists ................................................................ 412
1.1.2 Using Lists ............................................................................ 415
15.2 The TStrings Class .................................................................... 416
15.2.1 Working With Individual Strings........................................ 417
15.2.2 Working With Strings Positions.......................................... 420
15.2.3 Working With a Group of Strings ....................................... 427
15.3 The TStringList Class................................................................ 432
15.3.1 Creating a TStringList Object ............................................. 433
15.3.2 Using a TStringList Object ................................................. 434
15.4 Creating a List ........................................................................... 437
15.4.1 TStrings and TStringList Based Lists ................................. 437
15.5 Reviews ..................................................................................... 456
15.5.1 Exercises ............................................................................. 456

INDEX ......................................................................................................... 458

7 © FunctionX, Inc.
Table of Contents Borland C++ Builder

Conventions Used In This Book


The Mouse

Position

Place your mouse pointer on top of the indicated item.

Click

Refers to clicking the left mouse button once.

Double-click

Refers to double-clicking the left mouse button.

Right-click

Refers to clicking the right mouse button once.

Drag

Click and hold down the left mouse button, then move the mouse to the new,
indicated location.

For one word or a group of words, position the mouse on one end and drag it to the
other end until the dragged section changes color.

For more techniques on using the mouse, the keyboard, or a combination, refer to the
Introduction to Microsoft Windows tutorial.

Highlight

8 © FunctionX, Inc.
Table of Contents Borland C++ Builder

The Keyboard

The actions performed on the keyboard are referred to as “press”

Type
Type a character or numeric value

N
Press the indicated to cause an action.

I+°
Press both keys simultaneously and release.

I+~
Press and hold the first key, then type the other key.

Words and Acronyms

The following abbreviations are regularly used in this book


Abbreviation Means
Bcb Borland C++ Builder 5
MSVC Microsoft Visual C++
MSVB Microsoft Visual Basic

9 © FunctionX, Inc.
Table of Contents Borland C++ Builder

Chapter 1:
Borland C++ Builder IDE

10 © FunctionX, Inc.
Introduction to Objects Borland C++ Builder

1.1 Introduction to Borland C++ Builder


Borland C++ Builder offers a practical and easy means of creating computer applications
for the Microsoft Windows operating systems. It uses the C++ computer language as its
core syntax and programming logic, adhering to ANSI Standard with a lot of
improvements of customized items of the Win32 library.

There are various you can launch the program. The most common way consists of
clicking.

To create a shortcut on the desktop, in Microsoft Windows higher than Win95, click Start
 Programs  Borland C++ Builder, right-click C++ Builder 6 and click Send To 
Desktop (Create Shortcut)

1.1.1 Launching Borland C++ Builder


1. To start Borland C++ Builder, click Start  Programs  Borland C++ Builder 6
 C++ Builder 6

Figure 1: Borland C++ Builder IDE

11 © FunctionX, Inc.
Windows Events Borland C++ Builder

1.2 Integrated Development Environment

An Integrated Development Environment (IDE) is an application that provides a friendly


interface for creating computer programs.

Bcb’s IDE is structurally classical application. On top, there is a title bar that displays the
name of the application and the program currently running. The title bar itself is made of
three sections.

1.2.1 The Title Bar


1. Click the application icon . The system icon is used to identify the
application you are using. Almost every application has its own system icon.
The system icon holds its own list of actions; for example, it can be used to
move, minimize, maximize or close (when double-clicked) a window.
2. To see an example, while the system menu is displaying, click Minimize.
3. To bring back the IDE, on the Task bar, click C++ Builder

Fig 1.2
Title bar
4. The main section of the title bar displays the C++ Builder 5 name of the
application, and the name of the program that is running. A C++ Builder
program is called a project. When Bcb starts, it creates a starting project
immediately, and it names the starting project, Project1. If or when you add
other projects, they take subsequent names such as Project2, Project3, etc. This
main section of the title bar is also used to move, minimize, maximize the top
section of the IDE, or to close Bcb. On the right section of the title bar, there are
three system buttons with the following roles

Button Role
Minimizes the window
Maximizes the window
Restores the window
Closes the window

1.2.2 The Main Menu

Under the title bar, there is a range of words located on a gray bar; this is called
the menu.

In this book, the word “Main Menu” refers to the menu on top of
the IDE.

To use a menu, you click one of the words and the menu expands.
1. Click File. There are four main types of menus you will encounter.

12 © FunctionX, Inc.
Windows Events Borland C++ Builder

When clicked, the behavior of a menu that


stands alone depends on the actions prior to clicking it. Under the File menu,
examples include Save, Close All or Exit. For example, if you click Close All,
Bcb will find whether the project had been saved already. If it were, the project
would be closed; otherwise, you would be asked whether you want to save it.

2. To see an example, click Save.


3. When you are asked to save, click Cancel.

4. A menu that is disabled is not accessible at the


moment. This kind of menu depends on another action or the availability of
something else.
To see an example, click Edit and notice Undelete, Redo, Cut, Copy, and Paste.

5. A menu with three dots means an action is


required in order to apply its setting(s). Usually, this menu would call a dialog
box where the user would have to make a decision.

As an example, on the main menu, click Tools and click Editor Options…
6. On the Editor Options dialog, click OK.

7. A menu with an arrow holds submenu. To


use such a menu, position the mouse on it to display its submenu.

For example, on the main menu, click Edit and position the mouse on Flip
Children.
8. To dismiss the menu, click Edit.
9. To dismiss the menu, click Edit again.

This book uses the  arrow for the menu requests.


From now on, in this book,
Request Means
Edit  Copy Click Edit then click Copy
View  Toolbars  Custom Click View, position the mouse on
Toolbars, and then click Custom.

10. Notice that on the main menu (and any menu), there is one letter underlined on
each word. Examples are F in File, E in Edit, etc. The underlined letter is called
an access key. It allows you to access the same menu item using the keyboard.
In order to use an access key, the menu should have focus first. The menu is
given focus by pressing either the Alt or the F10 keys.
To see an example, press Alt.
11. Notice that one of the items on the menu, namely File, has its border raised. This
means the menu has focus.
12. Press p and notice that the Project menu is expanded.
13. When the menu has focus and you want to dismiss it, press Esc.
For example, press Esc.
14. Notice that the Project menu has collapsed but the menu still has focus.

13 © FunctionX, Inc.
Windows Events Borland C++ Builder

15. Press f then press o. Notice that the Open dialog displays.
16. On most or all dialog boxes that have either an OK, Open, or Save buttons,
when you press Enter, the OK, Open, or Save button is activated. On the other
hand, most of those dialog boxes also have a Cancel button. You can dismiss
those dialogs by clicking Cancel or pressing Esc.
As an example, press Esc to dismiss the Open dialog.
17. On some menu items, there is a combination of keys we call a shortcut. This key
or this combination allows you to perform the same action on that menu using
the keyboard.

If the shortcut is made of one key only, you can just press it. If the shortcut is
made of two keys, press and hold the first one, while you are holding the first,
press the second key once and release the first key. Some shortcuts are a
combination of three keys.

To apply an example, press and hold Ctrl, then press S, and release Ctrl.
18. Notice that the Save As dialog box opens. To dismiss it, press Esc.

From now on, in this book,


Press Means
T Press the T key
Alt, G Press and release Alt. Then press G
Ctrl + H Press and hold Ctrl. While you are still holding Ctrl,
press H once. Then release Ctrl
Ctrl + Shift + E Press and hold Ctrl. Then press and hold Shift. Then
press E once. Release Ctrl and Shift

1.2.3 The Toolbars


A toolbar is an object made of buttons. These buttons provide the same features you
would get from the menu, only faster. Under the menu, the IDE is equipped with a lot of
toolbars. For example, to create a new project, you could click File  New… on the
main menu, but a toolbar equipped with the New button allows you to proceed a little
faster.
By default, Bcb displays or starts with 6 toolbars. Every toolbar has a name. One way
you can find out the name of a toolbar is to click and hold the mouse on its gripper bar
and drag it away from its position

Click here then 1. Drag the grippers of one toolbar down and right:
drag down and
right

2. Notice that the toolbar has moved


Fig 1.3
Standard
Toolbar

3. Borland’s toolbars (and almost anything you see) can be positioned anywhere on
the screen. To position the toolbar back or to somewhere else, drag its title bar to
the desired location.

14 © FunctionX, Inc.
Windows Events Borland C++ Builder

4. You can get a list of the toolbars that are currently displaying if you right-click
any button on any toolbar or menu.
For example, right-click a toolbar and notice the list of toolbars:

Fig 1.4
List of
Toolbars

5. To dismiss the menu, press Esc.

In this book, every toolbar is referred to by its name

6. A toolbar is equipped with buttons that could be unpredictable. Just looking at


one is not obvious. The solution into knowing what a button is used for is by
position the mouse on top of it. A tool tip that Borland calls a hint will come up
and display for a few seconds.

As an example, position the mouse (don’t click) on the button that looks like a
piece of paper bent on its top right corner and see the hint:
Fig 1.5
Hint

7. Without clicking, move the mouse to another button and to other buttons. Notice
that some button’s hints also display a shortcut that would lead to the same
action.

8. To use a toolbar’s button, you click it. For example, click the New button .
Notice that the action calls the New Items dialog box.
9. Press Esc to dismiss the New Items dialog box.
10. Some buttons present an arrow on their right side. This arrow represents a menu.
To see an example, position the mouse on the Open button . Click the
arrow that appears and observe the menu.
11. Press Esc to dismiss the menu.

15 © FunctionX, Inc.
Windows Events Borland C++ Builder

1.2.4 The Component Palette


On the right side of the toolbars, there is a bar with multiple tabs; this is called the
Component Palette.

Fig 1.6
The
Component
Palette
The Component Palette holds many objects that you will be using to create your
applications. The Component Palette, like a toolbar, can be moved to any location on the
screen; but it is a good idea, if possible, to always keep it at its default location.
The Component Palette is made of objects categorized in different tabs. To display a
particular tab, you click it.

Practical Learning
1. For example, click the Win32 tab.

Whenever the Component Palette cannot display all of its tabs; there are two
horizontal arrows that allow you to reveal the hidden tabs .
To reveal more tabs, click the right pointing arrow.
2. Click the ActiveX tab.
3. Click the Standard tab.
4. Once again, it is obvious to predict what a button is used for. The best
alternative is to position the mouse on a button for a few seconds until a hint
appears.
Position the mouse on any button on the Component Palette and observe the hint
that appears.

From now on, each button of a toolbar or the Component Palette


will be referred to by its hint. The hint will represent the name of
the button. Therefore, “Click New” means, “Click the New
button.”

1.2.5 The Starting Form


Under the Component Palette, there is a gray box called a form. The form is an object
that allows you to create an application that would allow the user of your program to
interact with the computer. When you start Borland C++ Builder, it creates a readily
available form for you. This form, although not highly functional, is a complete
application.

An application can consist of one form or as many forms as necessary.


Notice that the current form has its own application icon, a title bar, the system buttons,
and it has a body, which is the area with grids.

1. To see what the current application looks like, on the main menu, click Run 
Run.

16 © FunctionX, Inc.
Windows Events Borland C++ Builder

2. Notice that a dialog box displays showing the evolution of compiling the
application:

Fig 1.7
Compilation
Process

3. Once the project is ready, it displays the ready form.


To close the form, click its close button .
4. A form is made of two parts, its “physical” part called the form and its code
section called a unit.
To toggle between the form and its unit, press F12.
5. Notice that the form goes to the back.

1.2.6 The Code Editor

Besides designing forms (and applications), one of your most regular jobs will consist of
writing code that directs the computer as to what to do, when, and how. This is done in an
appropriate window called the Code Editor.

The Code Editor is featured text editor adapted for coding purposes. It is programmed to
recognize the parts of a program that are recognized by C++ or not. To access the Code
Editor, if you have a form opened, you can press F12. The Code Editor manages your
jobs by organizing them into property pages (also called tabs). If your project contains
Fig 1.8 more than one file, you can click the desired tab to access one of the files. The basic
building block of a program is called a C++ file, and Borland calls it a Unit. Whenever
The Code
you start Bcb, C++ Builder creates a starting project that has a C++ file called Unit1
Editor
while the project is called Project. Eventually, you will change these names to those you
window
like. A typical code of a form, such as the one we have now, is built from at least two
files: a header file and a source file. The file displaying now is called the source file; it
gives direct instructions to the computer as to what to do on the form and why. The
foundation of this source file (which is also the foundation of the form is in a file called
the header file. By default, Bcb does not display this file at startup; you have to request it.

To display the header file of the form, you can right-click the source file and click Open
Source/Header File. Indeed, this action is used to toggle both displays. Since the source
and the header go in pairs (when using classes), they hold the same name but different
extensions.

17 © FunctionX, Inc.
Windows Events Borland C++ Builder

Practical Learning: Exploring the Code Editor

1. To display the header file, press Ctrl + F6


2. Notice that the header file is called Unit1.h
3. To toggle between the form and its unit, press F12
4. To bring back the Code Editor, press F12.
5. Click Unit1.cpp.
6. Click Unit1.h
7. To bring back the form, press F12.

1.2.7 The Class Explorer

What is called an object in real world is referred to as an object in C++, and an object is
build using a class. To organize the objects involved in a program, C++ Builder uses a
special window called the Class Explorer. As its name implies, it is used to navigate to
various objects.

The Class Explorer is positioned on the left side (or section) of the Code Editor. It is
organized in a tree view format with the name of the project as the root. To view the
objects that part of a project, expand the tree.

You can close or hide the Class Explorer any time and bring it back at will. You can also
permanently hide or for a while, which we will do at this time.

Practical Learning: The Class Explorer


1. Click the + sign on the Project1 - Classes.
2. Click the + sign on TForm1
3. Since we will not use the classes for a while, to close the Class Explorer, click
its Close button.

18 © FunctionX, Inc.
Windows Events Borland C++ Builder

4. To bring back Class Expplorer, on the main menu, click View -> Class Explorer
5. To permanently hide the Class Explorer (for a while), on the main menu, click
Tools -> Environment Options…
6. Click ClassExplorer
7. Uncheck the Automatically Show Explorer
8. Click OK.

1.2.8 The Object Inspector

One of the best (if not the best) features of Borland C++ Builder (and other compilers of
the company) and its easy of use and accessibility of designing objects. This is even
enhanced by the presence of another special window called the Object Inspector. This is a
window that lists the characteristics of the object that you are using to design an
application.

We will review the various uses of the Object Inspector when we can take advantage of
them.

1.3 Introduction to C++

1.3.1 Executing Programs

A program would not mean much unless it accomplishes the desired purpose. To examine
how your development is proceeding, as a beginning programmer, you should regularly
ask C++ to show you the result.

The (small) program we have written is really plain English, something we can read and
analyze. Unfortunately, the computer does not understand what it means; this is because
the computer "speaks" its own language called Machine Language. For the computer to
understand what your program means, you need an intermediary program that can
translate your English to machine language and vice versa. This program is called a
compiler, and it is supplied to you. The process of executing a program is done in various
steps that Borland C++ Builder can resume as one.

There are three ways you can execute a program in Borland C++ Builder. To execute a
program, you can press F9, you can also use the main menu where you would click Run ª
Run. On the toolbar, you can also click the Run button

Practical Learning: Executing a Program

1. On the Debug toolbar, click the Run button . As you see, the program does not
do much because we did not write a formal assignment.
2. To close the DOS window, press any key on your keyboard.

19 © FunctionX, Inc.
Windows Events Borland C++ Builder

1.3.2 Saving A Project

A program in Borland C++ Builder is called a project. As an application, it is saved in a


few steps. To save a project, on the Standard toolbar, click the Save All button.

Practical Learning: Saving A Project

1. On the Standard toolbar, click Save All .


2. Type Exercise to replace the name of the Unit1.
3. Click the arrow of the Save In combo box and click the (C:) drive.

4. Click the Create New Folder button .


5. Type Exercise01 and press Enter.
6. Double-click Exercise1 to display it in the Save In combo box.
7. Click Save
8. Type Exercise01 to replace the name of the project.
9. Click Save.

1.4 Borland C++ Builder Help

There are two main sources of help available for Borland C++ Builder. The first source
of help is provided with the compiler, this is from the Borland Company. This help is
mainly electronic and hardly printed. Fortunately, you have access to this help even if
you are not designing an application. Everything considered, this is the closest and the
highest documentation that the compiler provides.

To access C++ Builder help, on the task bar, click Start  Program  Borland C++
Builder  Help, and make your choice from the categories.

Another place you can find information is on the Internet. Fortunately, most of that help
is free. On the Borland’s help site, the company provides a list of some sites that deal
with Borland compilers. Unfortunately, many of these sites tend to treat C++ Builder and
Delphi as one entity, which is not the case.

Although the best challenger to Microsoft Visual C++, C++ Builder does not enjoy the
number of (independent) books that are published for MSVC. Fortunately, since there is a
good presence of Win32 API in C++ Builder, it is very important that you have access to
the Microsoft Developer Network documentation. It is available free from
http://msdn.microsoft.com and on CD-ROM or DVD.

1.4.1 Online Help

1. On the main menu, click Help  C++ Builder Help.


2. In the Contents tab, double-click Programming With C++ Builder to expand it.

20 © FunctionX, Inc.
Windows Events Borland C++ Builder

3. Double-click C++ Builder Programming Fundamentals


4. Double-click Types of Events

5. Notice that the help window displays, click the advance button .

6. After reading, click Help Topics


7. Click the Index tab.
8. Type OnMo
9. Notice that the OnMouseDown display in the list.
10. Press Enter.
11. After reading the text, click the TControl link.

12. After reading, click the Back button .


13. Click See Also.
14. Double-click TControl::OnClick
15. After reading, click Example.

16. To close the Help system, click its Close button .

1.4.2 Internet Help

Perform the following exercise if you have access to the Internet.


1. Log on to http://www.borland.com
2. Look for and click C++ Builder.
3. After finding some information and reading, change the address in the Address
box to http://msdn.microsoft.com and press Enter.
4. Position the mouse on Libraries and click Developer

21 © FunctionX, Inc.
Windows Events Borland C++ Builder

Chapter 2:
Applications Fundamentals

22 © FunctionX, Inc.
Windows Events Borland C++ Builder

2.1 Introduction to Applications


An application, also called a computer application, a program or a computer program, is a
set of instructions designed to help the computer perform a specific task. Although you
can design an program that would do (almost) anything, this is not realistic and not cost
effective. Each program should be customized to address a particular need such as word
processing, database, spreadsheet, web design, presentations, personal information
management (PIM) , communication, etc.

2.1.1 Creating Applications


The most fundamental program in C++ Builder is called an application. The easiest and
fastest way to create an application is to click File  New  Application from the main
menu. You can also click the New button on the Standard toolbar. From the New Items
dialog box, also called the Opject Repository, you can click the type of application or file
you would like to create. Instead of describing what each icon does, we will address each
as needed.

A Windows control is a graphical object that allows the user to interact with the
computer. These controls are as varied as the needs and the goals are. Although controls
are meant to ease the user’s experience, their design and creation are left to the computer
programmer. Each company that publishes a compiler provides a set of controls that are
not necessarily available on other compilers. Borland C++ builder is enjoying the
reputation of providing (one of) the richest development environments in the world of
Windows.

Controls can be set by categories based on their function or role.

A container is a control whose main purpose is to host other controls. To design it, you
pick up objects from the Component Palette and drop them where desired. The most
common and the most widely used container is the form. In Bcb, a form can be
configured to display like a regular dialog box or to become a Single Document Interface
(SDI).

2.1.2 Design and Run Times


To create your applications, there are two settings you will be using. If a control is
displaying on the screen and you are designing it, this is referred to as Design Time; this
means that you have the ability to manipulate the control. You can visually control the
control’s appearance (its location), its size, and other necessary or available characterics.
The design view is usually the most used and the easiest because you can glance at what
you see, have a realistic display of the control and configure its properties.

The other system you will be using to control a window is with code, writing the
program. This is done by typing commands or instructions using the keyboard. This is
considered or referred to as Run Time. This is the only way you can control an object’s
behavior while the user is interacting with the computer and your program.

Even as the design and the run times provide the means of creating or testing your
application, there are three ways you can add a control to a program. The visual design is
the technique that allows you to visually add a control and manipulate its display. This is
the most popular, the most regularly used, and the easiest technique. Unfortunately,

23 © FunctionX, Inc.
Windows Events Borland C++ Builder

sometimes you will not be able to add a control when designing the application.
Therefore, the other technique consists of creating a control using code.

2.2 The Form

The form is the most fundamental control of Windows applications. By itself, a form
means nothing and is almost useless. Its importance is on its being a host for other
controls. Therefore, a form is considered a container.

There are various ways you can create a form in Borland C++ Builder. The easiest way is
provided by the IDE which automatically opens with a readily available form. Another
means of creating a form is by clicking the New Form button on the View toolbar.

2.2.1 Creating a Form


When you launch Borland C++ Builder, it displays a form ready made and waiting for
you to customize it. As every control of your application possesses a name, the default
name of the starting form is Form1.

If one form is not enough, you can add another and other forms to your application. To
do this, you have three options. You can click the New Form button on the View
toolbar. From the main menu, you can also click File  New  Form. As a third option,
you can either click the New button on the Standard toolbar, or on the main menu, you
click File  New  Other… When the New Items dialog box, also called the Object
Repopsitory, displays, you can double-click the Form icon. Any of these techniques adds
a new form to your application. The names of the forms are incremental, by default. For
example, the second form you visually add to your application is named Form2, the third
would be Form3, etc. Using the control properties, you can change the names of your
controls.

If you visually add two (or more) forms to your application, you will need to link them,
allow them to exchange information. Since each form is created in its own unit, to let one
form know the existence of another, you must include its unit. A form or unit that wants
to communicate with another is called a client of the form. For example, if Unit2 wants to
use information stored in, or controlled by, Unit1, Unit2 needs to include Unit1 in its list
of header files; and Unit2 becomes a client of Unit1. There are two simple ways you can

24 © FunctionX, Inc.
Windows Events Borland C++ Builder

do this. Imagine you have created Form1 stored in Unit1 and Form2 stored in Unit2. If
you want to have access to Form2 from Form1, using C++, on top of the source file of
Unit1, include Unit2’s header file:

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

C++ Builder provides another technique. After making sure that either Form1 displays on
the screen or a Unit1 tab is displaying, on the main menu, click File  Include Unit
Hdr… From the Use Unit dialog box, click the unit name you want to include to the
current unit and click OK. Bcb will automatically add the right and selected header to the
client.

2.2.2 Form Design


To design a form and improve your application, you will be adding window controls, also
called controls, to it. Most of the controls you will use reside on the Component Palette.
There are various techniques you use to add a control to a form.

There are various categories of controls and objects on the Component Palette, some of
which you will hardly use.

Practical Learning: Introduction to Form Design


1. To add your first control, on the Component Palette, click the Standard tab

2. From the Standard tab, double-click Button .


3. Notice that a button control is added to the form.

4. To add another control, double-click Edit .


5. Notice that the second control is positioned on top of the first because whenever
you double-click a control from the Component Palette, it gets positioned in the
middle of the form

Actually when you double-click a control on the Component Palette,


it gets positioned in the middle of the selected container. If the
selected control on the form is not a container, the control you double-
click would be positioned in the middle of the form.

25 © FunctionX, Inc.
Windows Events Borland C++ Builder

6. To add another control, on the Component Palette, click Memo .


7. To draw a Memo on the form, position the mouse in the top middle section of
the form, then click and hold the mouse. Drag to the center right section of the
form:

Figure 2: Drawing a Control

8. Release the mouse. Notice that a memo has been added to the form.
9. There are other controls that do not use dimensions. You just click them and
click on the form. Their presence is more important on a form than their
physical location.
To see an example, on the Component Palette, click the Dialogs tab.

10. Click the ColorDialog button


11. Click and drag on the form to draw a big rectangular box and release the mouse.
12. Notice that the icon keeps its set width and height.
13. To display the code for the form, press F12. Notice that although we have added
controls, none of their code has been written.
14. To display the header file for the form, on the lower section of the Code Editor,
click the unit1.h tab
15. Notice the list of the objects that were added and their names set by Bcb.
16. To display the form, press F12 and click on an unoccupied area on the form.

2.3 Designing the User Interface


Creating a good-looking application is a combination of art and logic. Not all IDEs
provide the same features but Borland can boast for what is available on C++ Builder: a
host of controls to fit almost any assignment. We will learn how to configure various
controls as we move on. The first thing to do is to get familiar with what can ease the
user’s experience with your application.

26 © FunctionX, Inc.
Windows Events Borland C++ Builder

When designing an application, you will usually position the desired controls on a form.
This is when you decide which control you need, where it will be positioned on the form
and with regard to other controls, and what behavior should be customized.

2.3.1 Adding Controls to a Form


When Borland C++ Builder starts, it creates a starting form. This is usually your starting
point. Once you have a form, you can place the other controls that would participate in
your application. The easiest way to add a control to a form is to locate it on the
Component Palette, click it and click on the form.

Practical Learning: Adding Controls


1. To start a new program, on the main menu, click File  New  Application. If
you are asked whether you want to save your project, click No.
2. On the Component Palette, click the Standard tab.

3. Click the Edit control .


4. Click on the center-top section of the form (it is not important how it is
positioned):

Figure 3: Adding a control to a form

5. On the Component Palette, click the Edit control again.


6. This time, click on the middle left section of the form (again, the position is not
important):

27 © FunctionX, Inc.
Windows Events Borland C++ Builder

Figure 4: Adding another control to a form

7. Once again, on the Standard tab, click the Edit control.


8. This time, click in the lower-left section of the form and hold the mouse down.
9. Drag in the opposite directions to draw a tall and wide rectangle:

Fig 1.15
Drawing a
Control

10. Release the mouse


11. Notice that the control gets the same height as the other edit boxes.

12. On the Standard tab again, click the Memo control .


13. Click and drag on the form from the lower-right section to the upper-center
section of the form and release the mouse.
14. Notice that this time, the memo keeps the drawn dimensions.

28 © FunctionX, Inc.
Windows Events Borland C++ Builder

15. To add another control, on the Standard tab, click the ActionList control .
16. Click and drag on the form to draw a tall and wide rectangle. Then release the
mouse.
17. Notice that the new control keeps a constant shape.

18. To add another form, on the View toolbar, click New Form .
19. While Form2 has focus, on the Standard tab, double-click the Edit control to
place it on Form2

20. On the Standard tab, click the Panel control .


21. On the form, click in the lower right section of the form and drag to the upper-
center section of the form to draw a rectangle that partially covers the edit box.
Release the mouse:

Figure 5: Drawing a control on top of another

22. Make sure the new panel is still selected. From the Standard tab, double-click
the Edit control:

Fig 2.17
Adding a
control to a
container

29 © FunctionX, Inc.
Windows Events Borland C++ Builder

23. Notice that the new edit box is positioned in the center of the panel and not in
the center of the form. This is because the Panel control is a “container” and can
hold its own controls.
24. On the Standard tab, click the Edit control.
25. Click inside the panel but just above the Edit2 edit box.

Figure 6: Adding a control to a container

2.3.2 Selecting Controls


While you are designing a form and it is hosting controls, it is important to always know
what particular control is selected. Whenever you make changes, they are applied to the
control that has focus.

A control that is selected or highlighted is described as having focus.

There are two main techniques used to give focus to a control. On the form, click the
desired control. On the other hand, you can select the desired control on the combo box
on the upper section of the Object Inspector. You can also select a control by clicking its
name in the Object TreeView.

To select a form, click an unoccupied area on the form. If the form is hidden, press F12 to
toggle between the form and the code. If your application has more than one form, to
display one of them, on the main menu, click View  Forms and select the desired form
from the list.

Practical Learning: Selecting Controls


1. To display one of the forms, on the main menu, click View  Forms…

30 © FunctionX, Inc.
Windows Events Borland C++ Builder

2. From the View Form dialog box, click Form1

Figure 7: The View Form Dialog Box

3. Click OK
4. To select one of the controls, click the memo box. Also notice the Name field in
the Object Inspector:

Figure 8: Viewing the selected control on the Object Inspector

5. To select another control, in the Object TreeView, click Edit3


6. Notice that, on the form, the Edit3 control receives focus.
7. To select another control, click the arrow on the upper section of the Object
Inspector and click Edit2

Figure 9: Selecting a control from the Object Inspector

8. Notice the new selected name in the Object Inspector.


9. On the form, click Edit1 to select it.

31 © FunctionX, Inc.
Windows Events Borland C++ Builder

10. While one of the controls, namely Edit1 is still selected, press the up, down, left,
and right arrow keys on the keyboard to select other controls on the form.
11. Click anywhere on the form and not on a control. Notice that the form is
selected. You can verify this by checking the name on the top section of the
Object Inspector.
12. On the form, click Memo1 to select it.
13. To dismiss the selected control, press Esc. Notice that the form is now selected.
14. To hide the form, press F12.
15. To display the form again, press F12.
16. To select two controls, on the form, click Edit2.
17. Press and hold Shift.
18. While you are still holding Shift, click Edit3 and click the ActionList button.
19. Release Shift. Notice that the controls have handles on their corners, indicating
that they are selected. The Object Inspector displays properties that are common
to the selected controls.
20. To make another selection, just under the lowest edit box on the form, click and
drag up and right as to draw a rectangle that would touch Edit2, Edit3, and
Memo1:

Fig 2.21
Drawing a
control

Starting Point

Figure 10: Drawing a control

21. Then release the mouse. Notice that the touched controls are selected.
22. Press Shift + F12 to display the View Form dialog box.
23. Press the down arrow key to select Form2 and press Enter. Notice that Form2
displays.

32 © FunctionX, Inc.
Windows Events Borland C++ Builder

2.3.3 Moving Controls


Any control on a form can be moved to a desired location either to accommodate other
controls or based on new demands.

To move a control, click and hold your mouse on it; then drag your mouse to the desired
location. To move a group of controls, first select them; then click one of the selected
constrols and drag to the desired location. If the controls are hosted by another control,
you can move all of them when moving the container.

There are two valuable dialog boxes available to move controls. To solve alignment
issues, access the Align dialog from the main menu by clicking Edit  Align… When
dealing with relative dimensions, call the Size dialog by clicking Edit  Size…

The Alignment Palette is a window that can be used to deal with both alignments and
control spacing. To access it, on the main menu, click View  Alignment Palette. To
find out what a button on that window is used for, position the mouse on a particular
button for a few seconds until a hint displays.

Practical Learning: Moving Controls


1. To move the form with regard to its position on the screen, click and hold its
title bar. Then drag left.
2. While you are still holding the mouse, drag right and release the mouse.
3. Here is another technique you can use. Make sure the form has focus; this means
its title bar is blue (or the system color of your computer as set in Control
Panel). Press Alt + Shift + Space (this is equivalent to clicking the system menu
of the form). Notice that a menu comes up.

4. Press m to select Move. Notice the shape of the mouse pointer .


5. Press the left arrow key 4 times and notice that the form is moving.
6. Press the right arrow key 6 times and press Enter. Notice the new position of the
form.
7. To move the Edit1 edit box on Form2, click and hold the mouse on Edit1; then
drag to the upper left section of the form and release the mouse. Notice that the
control has moved.
8. Click and hold your mouse on the panel.
9. Drag to the left section of the form to move the panel. Release the mouse.
10. Notice that the panel has moved with its “children”.
11. On the main menu, click View  Forms…
12. Double-click Form1.
13. Notice that the controls selected earlier are still highlighted. Otherwise, select
them (Edit2, Edit3, and Memo1).
14. Since some controls are selected, click and hold your mouse on one of the
selected controls; for example click and hold Memo1. Then drag to the upper
section of the form and release the mouse.

33 © FunctionX, Inc.
Windows Events Borland C++ Builder

15. To deselect the group, press Esc.


16. To use another technique of moving controls, click Edit2 to select it.
17. Press and hold Shift. Then click Edit1 and Edit3 and release the mouse.
18. Once you have selected those controls, on the main menu, click Edit  Align…
19. On the Alignment dialog box, in the Horizontal section, click the Right Sides
radio button:

Figure 11: The Alignment Dialog Box

20. Click OK.


21. On the form, right-click one of the selected controls, position your mouse on
Position and click Align…
22. On the Alignment dialog, on the Horizontal section, click Left Sides. On the
Vertical section, click the Space Equally radio button and click OK.
23. Press Esc to deselect the group and select their container.
24. On the form, move the Edit1control to the center section of the form. Move
Edit2 to the lower right section of the form. Move Edit3 to the top section of the
form.
25. Select Edit1, Edit2, and Edit3.
26. On the main menu, click Edit  Size…

34 © FunctionX, Inc.
Windows Events Borland C++ Builder

27. On the Size dialog box, in the Width section, click Shrink to Smallest:

Figure 12: The Size Dialog Box

28. Click OK
29. While the controls are still selected, on the main menu, click View  Alignment
Palette.
30. On the Align window, click Align Left Edges

Figure 13: The Align floating window

31. Notice all selected controls share the same left alignment.
32. Close the Alignment Palette.
33. To deselect, click anywhere on the form

2.3.4 Resizing Controls


Most controls, including the form, can be resized using indicative mouse pointers. To
resize a control, first select it. Except for the form, whenever a control is selected, there
are eight handles around it. To resize the control, position your mouse on one of the
handles. The mouse pointer will change, indicating in what direction you can move to
resize the control.

Handle Role
Moves the seized border in the North-West <-> South-East
direction
Shrinks or heightens the control
Moves the seized border in the North-East <-> South-West
direction
Narrows or enlarges the control

35 © FunctionX, Inc.
Windows Events Borland C++ Builder

Practical Learning: Resizing Controls


1. To resize the form, position your mouse on its right border until the mouse turns
into double horizontal arrow .
2. Click and drag left for one inch.
3. Release the mouse.

4. Position the mouse on the lower right corner


5. Click and drag in the upper right direction, to acceptable dimensions.
6. release the mouse.
7. To resize a control, on the form, click ActionList.
8. Position the mouse on its lower left corner until the mouse turns into a double
arrow.
9. Click and drag in the lower left direction and release the mouse.
10. Notice that the control’s dimensions did not change but the icon moved.
11. Click Memo1.
12. Position your mouse on its left border until the pointer turns into a double
horizontal line.
13. Click and drag to the left to enlarge it. Then release the mouse.
14. Click anywhere on the form to select it.

2.4 Introduction to Controls Properties


Objects have characteristics that monitor their presence, their position, and their
appearance on a form. These characteristics are called properties. A property is anything
that characterizes or describes an object. The properties include the name of the control,
its color, its dimensions, and many other features that would set a control apart from the
others. These are visual characteristics accessible every time the object is displaying.
Many objects can be configured either while you are designing your application or when
coding it. Some other properties can be changed only during one phase. Some properties
are shared by most controls and some others are used only by a few or one control.

2.4.1 Setting Properties


The properties of a control can be changed either at design time or at run time. You can
also manipulate these characteristics both at design and run times. You can even set some
properties at design time and some others at run time.

To change the properties of a control at design time, you will use the Object Inspector.
Each field on the Object Inspector has two sections: the property’s name and its field
valule. The box on the right side of each name represents the value of the property that
you can set for an object. There are various kinds of fields you will use to set the
properties. To know what particular kind a field is, click its name. But to set or change a
property, you use the box on the right side of the name.

36 © FunctionX, Inc.
Windows Events Borland C++ Builder

Empty fields: By default, these fields have nothing


in their properties. Most of these properties are dependent on other settings of your
program. For example, you can set a menu property for a form only after you have
created a menu.
To set the property on such a field, you can type in it or select from a list. If you type an
invalid value and press Enter, you would receive an “Invalid Property Value” error :

Fig 1.10
Error
Message Box

Text Fields: There are fields that expect you to type


a value. Most of these fields have a default value. To change the value of the property,
click the name of the property and press Enter. While some properties would allow
anything, such as the Caption, come other fields expect a specific type of text, such as a
numeric value. If you type an invalid value, you would receive an error.

Fig 1.11
An error from
typing an
invalid value.

You can click OK to dismiss the error dialog and type a new valid value.

Expandable Fields: Some fields have a + sign. This


indicates that the property has a set of sub-properties that actually belong to the same
property and are set together. To expand such a field, click its + sign and a – sign will
appear:

To collapse the field, click the – sign. Some of the set properties are created from an
enumerator. Since the field was created as a set, this allows the property to have more
than one value. For example, the BorderIcons property can have the minimize and the
maximum button. Some other fields that have a plus sign are actually complete classes or
a combination of classes.

37 © FunctionX, Inc.
Windows Events Borland C++ Builder

Boolean Fields: Some fields can have only a true or


false value. To change their setting, you can either select from the combo box or double-
click the property to toggle to the other value.

Action Fields: Some fields would require a list of items and need to be controlled by an
intermediary action. Such fields display an ellipsis button . When you click the button,
a dialog box would come up and you can set the value for the field. You can also double-
click the field value to call the dialog.

Selection Fields: To change the value of some of the


fields, you would use their combo box to display the available values. After clicking the
arrow, a list would display.

There are various types of selection fields. Some of them display just two items. To
change their value, you can just double-click the field. Some other fields have more than
two values in the field. To change them, you can click their arrow and select from the list;
you can also double-click until the desired value is selected. On some other properties,
you can double-click the field and a dialog would come up

2.4.2 Form Properties


At the most basic level, a form is a control like any other; it has properties that are shared
by other controls. As a container, a control has some unique characteristics that allow it
to configure the control(s) it is hosting.

Fig 1.12 Every control has a particular property as its default. This means that, when you visually
Error add the control to a form or container, its default property is selected in the Object
Message Box Inspector. If you start typing, that default property will receive your change. The default
property of the form is the caption. The caption of a form is the word or group of words
that display(s) on its title bar. Whenever you add a new form to your application, if you
start typing, the Caption field in the Object Inspector would receive the change.

At design time, you can only set the caption as text. At run time, you can control and
programmatically display anything on the caption of the form. To change the caption at
run time, you can use a function, a method, or an event. Just type “Caption = “ and the
sentence you want. For example, you can display today’s date on the caption as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::ChangingFormCaption()
{
Caption = "Today is " + Date();
}
//---------------------------------------------------------------------------

You can also indirectly control the caption. For example, after the user has typed his or
her name in an edit box, you can display it in the form’s caption as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::ChangingFormCaption()
{
Caption = Edit1->Text;
}
//---------------------------------------------------------------------------

38 © FunctionX, Inc.
Windows Events Borland C++ Builder

An important property of a control is its name. The name of a control allows you and the
compiler to relate to the control. To change the name of a control, when the control is
selected, on the Object Inspector, click the Name field to highlight it. Type a new name.
You should not try to change the name of a control at run time, unless you absolutely
know what you are doing. This is because the compiler needs to know the name of a
control all the time.

Except for the form, every window control of your application is hosted by another
control. The form, on the other hand is housed by the screen of your monitor. For this
reason, the positon of the form is relative to the screen. At design time, you can position
the form anywhere on your screen and when you run the application, the form would
appear following that position. This is based on the fact that the position of the form is
controlled by the TPosition enumerator. The default position of the form is recognized as
designed if you do not change the Position property.

The dimensions of a form are controlled by its Left, its Top, its Width, and its Height
properties. The measurement starts on the top-left corner of the window host where the
origin is set to 0,0. The Left property represents the length from the left border of the
screen to the left border of the form. In the same way, the Top property measures the
length from the top border of the screen to the top border of the form. As their names
indicates, the Width property represents the width of the form and the Height property is
the height of the form. These measurements are integer types:

Left

0,0

Top

Height

Width

To change the dimensions of the form at design time, click the name of the desired
property to highlight it and type a valid value. When you press Enter and/or move to
another field or property, the form will apply the new value.

To change a dimension at run time, in the function where you want to use it, type the
name of the property followed by = and followed by a valid value. For example, you can
change the width of a form named Form1 as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::ChangingFormWidth()
{

39 © FunctionX, Inc.
Windows Events Borland C++ Builder

Width = 248;
}
//---------------------------------------------------------------------------

If a form is hosting more than one visual control, you can control which control has focus
when the form launches. This is set using the ActiveControl property. To set the active
control, click the ActiveControl field to display its combo box. Click the arrow of the
combo box and select one.

The Align property is mostly used by controls other than the form. Therefore, I would
suggest you hardly use it for a form, although you can. The Align property allows you to
control how the form would be positioned relative to the screen when it starts.

The Anchors field controls how a control is positioned or dimensioned when its host
control is resized. You will hardly use this property with a form because the form usually
does not have a parent container: a form is already a container.

The BorderIcons property allows you to decide what system buttons the form would
display. By default, the form has the Minimize , the Maximize , and the Close
buttons. Optionally, if you are creating a dialog box, you can add a Help button. To
change the border icons, click the + on the property’s name to display the list. Since this
proerty is a set you can choose one or more of the sub-properties. To change a sub-
property, click it to show its combo box; you can change it by setting it to true or false, as
needed:

Fig 2.2
Setting the
system
buttons on a
form

The BorderStyle property is a good place to configure the appearance of the form.

By default, a form is designed to be resizable using


the bsSizeable value. In this case the user can
change its width and its height by dragging one of
its borders or corners.

40 © FunctionX, Inc.
Windows Events Borland C++ Builder

If you set the BorderStyle property to bsDialog, the


user will not be able to resize the dialog. This is the
default and the mostly used characteristics for a
dialog window. You should always use it if you
want the window to be a dialog box. A modal dialog
box is a dialog that the user must dismiss before
continuing with the application.

A BorderStyle set with bsSingle looks like one set


with the bsSizeable. The difference is that the user
cannot resize it.

A floating window is a form used to let the user move


it around while he or she is working on the main form
or dialog. This form is usually modeless, which
means the user does not have to close it to continue
working. If you want to create a floating modeless
window, you should set the form’s BorderStyle to
bsSizeToolWin. The window has a short titlebar and
it can be resized.

Like the sizable tool window, a form with


bsToolWindow has a short title bar and is also a
prime candidate for a floating window. Unlike the
form with bsSizeToolWin, the user cannot resize a
bsToolWindow form.

A Form whose BorderStyle is set to bsNone has


neither a title bar nor borders.

The WindowState property specifies how the form must appear when it opens. The
default value is wsNormal, which means that the window would display normally when
it launhes. If you want the form to be maximized when it is called, set this property to
wsMaximized. A form with wsMinimized WindowState would not appear on the screen
when it is called, but it would appear on the taskbar where the user can restore or
maximize it as desired.

41 © FunctionX, Inc.
Windows Events Borland C++ Builder

The Color property controls the background of a control. In this case, you can use it to
change the form’s color. When you click the Color name field, a combo box would
appear with a list of colors. You can then choose one color from the list. The list of colors
of the Color property is derived from the TColor enumerator:

enum TColor {clMin=-0x7fffffff-1, clMax=0x7fffffff};

Fig 2.3
Color
Property

If none of the colors suits you, double-click the field section, on the right column of
Color. A dialog box would come up; and you can use it to select or set a color:

To change the form’s background color at run-time assign a long integer to the Color
keyword. For example Color = 568698. If the number is not qualified, you would receive
a warning although the application would run fine. To avoid the warning, you should cast
the number as a TColor object. Here is an example:

Fig 2.7 //---------------------------------------------------------------------------


void __fastcall TForm1::BackgroundColor()
The View
{
Form Dialog
Color = TColor(764358);
}
//---------------------------------------------------------------------------

The user of your application will have the ability to resize the form when using your
application. If the form is not a classic dialog box, by default, the user can resize it to any
dimensions allowed by the screen resolution; the minimum is to have the system buttons
and just a tiny part of the caption. You can set the minimum height, the maximum height,

42 © FunctionX, Inc.
Windows Events Borland C++ Builder

the minimum width, and the maximum width allowed on the form when the user decides
to resize it. This property is controlled by the Constraints property. The Constraints
property is controlled by the TSizeConstraints class which is inherited from the
TPersistent class. Although it is a class, you should never declare it. The control that uses
a Constraints class will create and initialize an instance of the class. The MinWidth,
MinHeight, MaxWidth, and MaxHeight are integer values you can set using the
keyboard. To set the constraints of a control that has this property, click the + sign of the
Contraints name in the Object Inspector, click the field desired and type an integer
value. To programmatically control the constraints of a control, call the
TSizeConstraints::Property and type the desired value. In the following example, when
the user tries to resize the Form1 form, the minimum and maximum dimensions of the
form are already set and would not change:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
Form1->Constraints->MinHeight = 300;
Form1->Constraints->MinWidth = 500;
Form1->Constraints->MaxHeight = 400;
Form1->Constraints->MaxWidth = 565;
}
//---------------------------------------------------------------------------

Practical Learning: Setting a Form Properties


1. To start a new appication,on the main menu, click File  New Application. If
you are asked to save the project, click No.
2. To test the current application, press F9.

3. After previewing the form, click its Close button


4. On the Object Inspector, click Caption and type Introduction to Form Design
5. Click Name and type frmMain
6. Click the Color field to reveal its combo box. Click the arrow that points down
and select clBlue.

7. Click the Icon field. Notice that an ellipsis button appears .


8. Click the ellipsis button.
9. On the Picture Editor dialog, click the Load button.
10. Locate the folder where you installed your exercises and double-click Images.
11. Click Exo1 and notice the preview on the right section of the Load Picture
dialog:

Fig 2.5
The Load
Picture
Dialog

43 © FunctionX, Inc.
Windows Events Borland C++ Builder

12. Click Open.

Fig 2.6
The Picture
Editor Dialog

13. On the Picture Editor dialog, click OK


14. To test the current application, press F9
15. Resize the form to increase its width and its height.

16. After previewing the form, click its Close button


17. If the form has disappeared, press F12.
18. Drag the form to the upper right corner of the screen, using its title bar.
19. On the Object Inspector, change the Position field to poScreenCenter.
20. Click Width and type 380
21. Click Height and type 285
22. Click the + symbol on the Constraints field.
23. Set the MaxHeight to 320 and the MaxWidth to 412
24. Set the MinHeight to 260 and the MinWidth to 355
25. Double-click the clBlue selected in the Color field.

44 © FunctionX, Inc.
Windows Events Borland C++ Builder

26. On the Color dialog box, click the Define Custom Colors >> button.
27. To change the color, double-click the Red edit box and type 255
28. Press Tab and, in the Green edit box, type 236
29. Press Tab and, in the Blue edit box, type 217

Fig 2.4
The Color
Dialog

30. Click OK.


31. Notice the color value in the Color field as 0x00D9ECFF.
32. To test the current application, press F9
33. Using the form’s borders, resize the form and notice that it cannot reach some
dimensions.

34. After previewing the form, click its Close button


35. If the form disappears, press F12 to display it.

2.4.3 Form Navigation


Form navigation has to deal with not only the alignment of controls on your form but also
the logical process the user should follow when using your product. The Tab key on your
keyboard is the primary means users use to navigate from one control to another. The tab
order is the sequence of controls that the keyboard follows when the user presses the Tab
key. Usually, after creating a form, this navigation sequence does not follow the right
logic. You usually have to adjust that sequence. This is done from the Edit Tab Order
dialog box.

Practical Learning: Form Navigation


1. To start another project, on the main menu, click File  New  Other…
2. From the New Items dialog, make sure Application is selected and click OK.

3. From the Component Palette, click Edit and click on the form to add Edit1
4. Add other edit controls as Edit2, Edit3, and Edit4.

45 © FunctionX, Inc.
Windows Events Borland C++ Builder

5. From the Standard tab of the Component Palette, click Button to add a
button control to the form
6. Add one more button.
7. Add two more Edit controls as Edit5 and Edit6
8. Move and resize your controls and the form as follows:

Fig 2.14
Form Design

9. To test the form, press F9.


10. Notice that Edit1 is highlighted, meaning it has focus.
11. Press Tab and notice that when the second edit box receives focus, its content is
highlighted:

Fig 2.11
Tab Sequence

This Edit
Control has
focus

12. Press Tab a few times until Button1 is highlighted:

Fig 2.12
Form
Navigation

This Button
Control has
Focus

13. Press Tab a few times to review the sequence of navigation.

46 © FunctionX, Inc.
Windows Events Borland C++ Builder

14. Close the form.


15. To adjust the navigation sequence, right-click an empty area on the form and
flick Tab Order…
16. On the Edit Tab Order dialog, click Button1: TButton

17. Click the down pointing button twice.


18. Click Edit6: TEdit

19. Click the up pointing button .


20. Rearrange the list on the Edit Tab Order dialog as follows:

21. Click OK
22. To test the form, press F9.
23. On the form, Press Tab a few times and notice the new sequence of navigation.
24. Close the form.

2.5 Controls Events


An event is an action that occurs in the life of a control. The essence of Object Oriented
Programming (OOP) is to predict the necessary events and take action accordingly. When
an event occurs, it is said to have been “fired”. The control that sends the event is said to
“fire” the event.

There are two main categories of events that will occur in your application, those from
your user doing something and those controlled by the operating system.

A user initiates an event based on what your application presents. For example, if you
expect the user to click a button, then an event associated with clicking the button will

47 © FunctionX, Inc.
Windows Events Borland C++ Builder

fire. If the user is supposed to type, then the appropriate event will be fired when the user
types.

The computer itself, that is, the operating system, has its own events and controls them.
For example, when the computer starts, the operating system controls many events that
occur. When you start Borland C++ Builder, the computer fires events that control how
Bcb displays on your screen. The computer also controls the time on your computer; this
is very important.

Your job as a programmer is to anticipate what event could occur for a particular control
that is part of your application. Not all controls have or can fire events, and not all
controls can fire the same events; but many controls share events of the same category.
We will review controls and their associated events when we learn to design each
particular control.

The users of your program will mainly use the mouse and the keyboard to interact with
your application. These two objects are the primary sources of using events. Therefore,
you will mainly deal with events associated with either the mouse or the keyboard.
Whenever possible, you should also give users the option of using either the mouse or the
keyboard to perform the same action. Whenever possible and necessary, make sure the
user can use the mouse or the keyboard without encountering different behaviors for the
same intended purpose.

2.5.1 Mouse Events


The mouse is a piece of hardware equipped with two buttons (by default): the left and the
right mouse buttons. Each button has three main actions it can initiate. To use the mouse,
you click, mainly the left button. When you click, the mouse sends an event considered as
“the mouse down event”. Every event in C++ Builder starts its name with On. Therefore,
if an event occurs when the mouse is down, Borland C++ Builder would call it the
OnMouseDown event.

As soon as you release the mouse button, the mouse fires another event called the
OnMouseUp event.

Whenever you are moving your mouse on a form or a control, the mouse is firing another
event called the OnMouseMove event. This is useful when you want to detect what the
user is doing or where the mouse pointer is located.

Since the mouse has two buttons and the user can use either of them, the program locates
the mouse at all times using a coordinate system with its origin on the top left corner of
your monitor.

48 © FunctionX, Inc.
Windows Events Borland C++ Builder

Mouse top
position
Mouse left position

Y
The axes of the mouse location are directed to the right and down. The horizontal
location of the mouse is represented by X (going right) and the vertical location is
represented by Y (going down). The compiler is designed to recognize not only the left
and right but also the middle – if any – buttons of the mouse. This is done using the
TMouseButton structure that has the mbLeft, mbRight, and mbMiddle values that
represent each button..

There are two actions you will take with regards to the mouse. You can consider the
previous three mice events separate. To program these events, you will ask the compiler
to find out which button was clicked.

C++ Builder also recognizes the currently popular mice with wheels. Therefore, you can
also program the OnMouseWheel, the OnMouseWheelDown, and the
OnMouseWheelUp events.

When the OnMouseDown and the OnMouseUp events are combined, the compiler
simply considers that the mouse was clicked. In this case, a special common event called
the OnClick event is fired. Actually, the previous mouse events completely depend on
the mouse and they are highly used in programs that involve intense mouse movements
where the programmer needs to usually find out what mouse button is or was pressed.
Examples of these programs are drawing, word processing, etc.

When the mouse click occurs, to make programming a little easier, the compiler hands
responsibility to the control where the mouse was clicked. That is, the control that
initiated the event. Therefore, the OnClick event, one of the most regularly used events,
belongs to the control. Besides finding out which button was clicked, you will also be
concerned with what should happen when a particular control is clicked.

Many other events relative to the mouse can be customized or configured when they
occur on the control

49 © FunctionX, Inc.
Windows Events Borland C++ Builder

2.5.2 Keyboard Events


Although a piece of hardware highly used, the keyboard itself can claim only three
events.

When the user presses a key on the keyboard, the OnKeyDown event fires. When she
releases the key, the OnKeyUp event occurs. The OnKeyPress event occurs when the
user presses one key.

The keyborad events are useful when you need to find out which key was pressed on a
control. For example, you can perform different assignments of a form when the user
presses Enter or Tab and you can ask the application to ignore all the other keys. On the
other hand, you can write an application that would validate an action only if a certain
key or a combination of keys is pressed.

The names of the keys, as you will use them in your program, are listed in the winuser.h
file. Under no circumstance should you ever include that file in your application. Instead,
you can include the windows.h header file. To get an exaplanation of each key, in the
help file of Bcb, do a search on virtual key codes.

2.5.3 Other Events

Many events are shared among controls that anticipate the user to perform a similar
action. For example, to use most controls, the user is supposed to click; therefore, many
controls have an OnClick event. Some other events are appropriate for particular
controls.

When the content of an edit or a memo control changes, the OnChange event fires; this
is appropriate because it happens almost all the time and you should take appropriate
actions, such as dismissing a wrong data the user has provided.

2.5.4 Controlling and Programming Events


Although you are allowed to use any available event for a control, you should justify it to
yourself, “Why do you want to implement this particular event”? To proceed, you should
understand when and why an event occurs. On an edit box, the user can click, double-
click, triple click, type, drag, etc. Before deciding to control an event, you decide on the
importance of that event with regard to the control. Although the user can type and
change the content of an edit box, sometimes you will need to prevent the user from
typing until a dependent action on another control has occured. This means that you can
program an event on one control to act relative to another control or another event.
Therefore, you should know what events are available and how to access them.

An event is qualified as default because it is the most likely event used on a control. For
example, when thinking about a button, the first action that comes in mind is to click it.
Therefore, OnClick is the default event of a button.

Depending on how the control was created and configured, when a control has a set of
events, if you double-click it from the form, it would open the Code Editor with the
default event ready to receive code.

50 © FunctionX, Inc.
Windows Events Borland C++ Builder

2.5.5 The Structure of an Event


Although there are different ways you can implement an event, there are two main ways
you can initiate the coding of an event. If the control has a default event, if you double-
click it, the compiler would initiate the default event.

Another technique you can use is to click the Events


tab of the Object Inspector. This would display a list
of the events associated with the selected control.

The list is divided in two columns. The name of each


event is displayed on the left side. You can click the
name of an event to reveal a combo box. If a similar
event has already been written, you can click the
arrow of the combo box and select it from the combo
box:

Similar events are those that share a behavior.


Otherwise, to initiate an event double-click the field
on the right column of the name of the desired event.

When an event has been initiated, you would be transported to the Code Editor and the
cursor would be positioned in the event, ready to receive your instructions. To customize
an event, the compiler divides its structure in three sections:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
// Write code associated with the event here
}
//---------------------------------------------------------------------------

The coding of an event starts with its return value. Most events in C++ Builder return a
void. All events use the fastcall convention.

The return type is followed by the name of the parent class from where the event would
be fired. This is mainly the class that controls the form. By default, the name of the
starting form is Form1. The class that controls the form holds the same name following
Borland’s convention of class names. Therefore, the class that creates Form1 is called
Tform1. If you rename the form, such as frmMain, the compiler would update the name
of the class; in this case the class would be renamed TfrmMain. The above event would
be changed to:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)

51 © FunctionX, Inc.
Windows Events Borland C++ Builder

{
// Write code associated with the event here
}
//---------------------------------------------------------------------------

After the name of the class, the compiler rightly uses the class member access operator
(::) to call the event.

The name of an event is made of a combination of the control that “owns” the event and
the name of the event. For example, if a form fires the OnCreate event, the compiler
would name the event FormCreate. If a button called Button1 fires an OnClick event,
the compiler would call it Button1Click event.

Each event has at least one argument, the TObject *Sender. Some events use additional
arguments that we will review when coding such events.

2.5.6 Form Events


During its lifetime or functionality, a form fires events and receives changes as the user is
interacting with your application.

The default event of a form is the OnCreate. This event is fired as soon as a form
displays on the screen. This is the favorite place you would programmatically initialize
the form and some of your variables. For example, if you want the form to be maximized
at startup, you can ask the compiler to take care of that when the form launches, using the
OnCreate event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
WindowState = wsMaximized;
}
//---------------------------------------------------------------------------

The OnClick event occurs when the user clicks anywhere on the screen but outside of a
control.

//---------------------------------------------------------------------------
void __fastcall TForm1::FormClick(TObject *Sender)
{
if( Color == 0x05F9C617 )
Color = TColor(0x00D9ECFF);
else
Color = TColor(0x05F9C617);
}
//---------------------------------------------------------------------------

When the user double-clicks an unoccupied area on the form the DblClick event fires.

Practical Learning: Using the Form’s Events


1. To create a new application, on the main menu, click File  New 
Application.
2. On the Object Inspector, click Caption and type Rapid Application
Development

52 © FunctionX, Inc.
Windows Events Borland C++ Builder

3. Click Name and type frmMain


4. To add another form to your application, on the View toolbar, click the New
Form button
5. Click the Name field and change it to frmSecond
6. As the new form is still selected, double-click in its middle to initiate its
OnCreate event.
7. Implement the event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmSecond::FormCreate(TObject *Sender)
{
Width = 405;
Height = 350;
Caption = "I know you called me!";
}
//---------------------------------------------------------------------------
8. To display the main form, on the main menu, click View  Forms…

9. On the View Form dialog box, click frmMain and click OK.
10. To include the header of the other form, on the main menu, click File  Include
Unit Hdr…
11. From the list, Unit2 should be clicked already, otherwise click it

12. Click OK.

53 © FunctionX, Inc.
Windows Events Borland C++ Builder

13. On the Object Inspector, click the Events tab and double-click the event field of
the OnDblClick field.
14. Implement the event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormDblClick(TObject *Sender)
{
frmSecond->ShowModal();
}
//---------------------------------------------------------------------------
15. To test the program, press F9.
16. Move the form from its current position by dragging its title bar.
17. To call the second form, double-click in the middle of the form.
18. After viewing the form, close it. Also close the main form.
19. To add another form to your application, on the main menu, click File New 
Form.
20. Change the name of the new form to frmFloater
21. On the Object Inspector, click the OnCreate name and double-click the event
field.
22. Implement the event as follows:

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

#include <vcl.h>
#pragma hdrstop

#include "Unit3.h"
// Include the dependent header file
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmFloating *frmFloating;
//---------------------------------------------------------------------------
__fastcall TfrmFloating::TfrmFloating(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfrmFloating::FormCreate(TObject *Sender)
{
// The appearance should be that of a floating window
BorderStyle = bsToolWindow;
// Keep this floating always on top
FormStyle = fsStayOnTop;
// Change the form's background color
Color = TColor(RGB(202, 238, 255));
// Make sure this window aligns with the top-left
// corner of the calling form
Top = frmSecond->Top;
Left = frmSecond->Left;

54 © FunctionX, Inc.
Windows Events Borland C++ Builder

// Set the dimensions of the window


Height = 325;
Width = 124;
}
//---------------------------------------------------------------------------
23. We will call the floating window from the second form. On the View toolbar,
click the View Unit button .
24. On the View Unit dialog, click Unit2

25. Click OK
26. Press F12 to display the second form.
27. Press Alt + F11 to call the Use Unit dialog. Double-click Unit3.
28. On the Object Inspector, double-click the OnClick event.
29. Implement the event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmSecond::FormClick(TObject *Sender)
{
frmFloater->Visible = !frmFloater->Visible;
}
//---------------------------------------------------------------------------
30. To test the program, press F9
31. To display the second form, double-click the main form.
32. To display the floating form, click the second form. Notice that the floating
window appears.
33. Move the second form and try to position it on top of the floating window.
Notice that the floating window is always on top of the second window.
34. Click the second form again. Notice that the floating form reappears.
35. Click the second form again to display the floating window. Make sure the
floating window display.
36. Close the second window
37. Display the second form.

55 © FunctionX, Inc.
Windows Events Borland C++ Builder

38. On the Object Inspector, double-click the event field of OnClose.


39. Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmSecond::FormClose(TObject *Sender,
TCloseAction &Action)
{
if( frmFloater->Visible )
frmFloater->Close();
}
//---------------------------------------------------------------------------
40. Press F9 to test the program.
41. Display the second form.
42. Click the second form to display the floating window.
43. Close the second form. Notice that the floating window has been closed.
44. Close the main form.

2.6 Dynamic Forms


Besides a form visually, sometimes this will not be possible. You may have to create the
form dynamically. To create a form dynamically, declare a pointer to a TForm class.

2.6.1 Dynamic Local Forms


If you want to quickly use a form in a function or an even, you can create it easily. There
are two options you have. If you want to create a duplicate of the form you already have,
you can use it as the base class and simply create an instance of the form using the new
operator. When dynamically creating a form, you must provide a parent for the form. If
you are creating a duplicate of the form, set the parent as the this pointer. The parent is
provided to the constructor. For example, to create a duplicate form using a form’s
OnDblClick event, you can implement the event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm1* Former = new TForm1(this);
}
//---------------------------------------------------------------------------

The problem with a duplicate is that, unless you go through a big deal of code writing,
everytime you do anything on the form, the duplicate produces the same action. For
example, if you use the above code, everytime you double-click the form, a new
duplicate is created. Therefore, the second option you have on creating a local object is to
create a fresh form. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm* Former = new TForm(this);
}

56 © FunctionX, Inc.
Windows Events Borland C++ Builder

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

2.6.2 Dynamic Global Forms


The biggest problem with a locally created form is that it is available only in the event or
the function in which it is created. If you try to access it outside, you would receive an
error. If you want a form to be available to more than one event or function, you must
create it in a header file of an existing form. You could create the form as follows:

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TForm* Comet;
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

If you try running the application, you would receive a noisy warning that seems
harmless:

If you insist, you can click No and the program would compile and run fine. But, this
would be unprofessional and unpredictable. This is because you would have declared a
non-visually added control to your application. The solution is to make sure you declare
your dynamic object in one of the other sections. If you want the form to be available
outside of the parent form that “owns” the header file, you must declare it in the public
section. Otherwise, you should declare it in the private section:

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

#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
TForm* Comet; // A dynamically created form
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

57 © FunctionX, Inc.
Windows Events Borland C++ Builder

extern PACKAGE TForm1 *Form1;


//---------------------------------------------------------------------------
#endif

After declaring the form, since you cannot initialize a variable in the header file, you can
use the constructor of the host form to initialize the dynamic form. This is done by using
the new operator and initializing the TForm class with the this pointer, like this:

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

#include <vcl.h>
#pragma hdrstop

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

2.6.3 Customizing Dynamic Forms


Whatever technique you use to create your form, you can set its properties using code.
The most basic thing you should do is to display it using the TForm::ShowModal()
method. If the form was created locally, you must display it in the function or event
where it was created:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm* Former = new TForm(this);
Former->ShowModal();
}
//---------------------------------------------------------------------------

If the form was created globally, you can use almost any event to display it. The best way
to display such a form is through a button, which we will learn soon. Otherwise, to
display a glogally created form when the user double-clicks the main form, you can
write:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
Comet->ShowModal();
}
//---------------------------------------------------------------------------

After creating a form, such as Comet, you can programmatically set any of its properties
and use any of its methods.

58 © FunctionX, Inc.
Windows Events Borland C++ Builder

After creating and using a form, you should make sur the memory allocated to it is
regained. The Borland C++ Builder compiler can take care of cleaning your dynamic
controls when the application exists. Otherwise, you can delete it manually:

delete MyForm;

Furthermore, to avoid any memoly leak, you can reclaim the dynamically allocated
memory by assigning NULL to the deleted object:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
TForm1 *Cosmos = new TForm1(this);
Cosmos->ShowModal();
delete Cosmos;
Cosmos = NULL;
}
//---------------------------------------------------------------------------

Practical Learning: Using a Dynamic Form


1. To create a new application, on the Standard toolbar, click the New button.
2. On the New Items dialog, double-click Application.

2.7 Form’s Scroll Bars

A form’s scroll bar is a horizontal or vertical control used to navigate in two directions
along the form by clicking one of the arrows. A form is configured to automatically add
one or two scroll bars if needed; this happens when one or more of the hosted controls
goes “overboard”; instead of resizing itself, the form displays a scroll bar (or two if
necessary):

59 © FunctionX, Inc.
Windows Events Borland C++ Builder

For its functionality, a scroll bar is made of three parts:


1. a button arrow of each side of the form: Up or Down .
2. a horizontal or vertical bar
3. a scrolling region

There are three main ways to use a scroll bar. If you click one of the arrows, the content
of the form would slide in the opposite direction, revealing the previously hidden or
unavailable section of the form. You can also click the rectangular bar itself, hold the
mouse on it and drag. Another use of the scroll bar consists of clicking in the scrolling
region of the control.

2.7.1 The Form’s Scroll Bars Properties


Note The scroll bars of a form are derived from the TScrollingWinControl class. A form is
The AutoScroll property is configured to automatically display one or two scroll bars based on the value of the
set only on the control, TScrollingWinControl::AutoScroll property. When its Boolean value is set true, which
such as the form, that is the default, a form gets equipped with one or two scroll bars as needed. You can also
owns it and not on the set this property programmatically. For example, when the form opens or if the user
hosted controls. Each
control manages its own moves a control on the form, if you do not want the scroll bars to appear as part of the
scrolling properties, if form’s functionality, set the AutoScroll property to false. Here is an example:
available.
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
AutoScroll = False;
}
//---------------------------------------------------------------------------

If you dynamically create a form, its AutoScroll is set to true by default. If you do not
wish to ever display the scroll bars, specify it:

60 © FunctionX, Inc.
Windows Events Borland C++ Builder

The horizontal scroll bar of a form is configured using the HorzScrollBar property. The
vertical scroll bar of a form is controlled from the VertScrollBar property. To
manipulate any of these properties at design time, on the Object Inspector, click the + of
the desired properties to expand it:

Both the HorzScrollBar and the VertScrollBar properties are created from the
TControlScrollBar class.

2.7.2 The TControlScrollBar Class


The TControlScrollBar class is used to accommodate the form (or the ScrollBox control) with a scroll bar
object completely configured independently from the form but providing all the scrolling functionality that
the parent control needs.

For the scroll bar to display, its Visible property must be set to true, which is the default. If you do not
want to display one particular scroll bar, you can set this property to false. Although this setting seems to
apply the same property as the TScrollingWinControl::AutoScroll, the TControlScrollBar::Visible
property applies only to a specific scroll bar object. To change this property programmatically, you would
use code such as:

A scroll bar is configured to slide from one minimum value to a maximum. The minimum value is 0. The
maximum value is that of the ClientWidth property. This value is controlled by the Range property and is
set by default to 0. If you add a control that exceeds the right border of the form, a horizontal scroll bar is
added, then the compiler calculates the necessary value of the range based on the ClientWidth value of the
form and the usable (area that can be used) width of the far right control. This calculation results in a
Range long enough so the user can scroll and display the content of the form completely. If you want to
control this value, change the integer value of the Range field. If you set a value less than the
ClientWidth, the horizontal scroll bar would disappear and the user would not see hidden parts of the
exceeding control(s). You can also set this value so that only part of the exceeding control would appear.
As stated already, when you add a control that exceeds the right section of the form, the compiler sets the
range so enough room, but not more than enough, is available to display the whole control. By setting the
value of the Range to more than the “regular” value, you can display the form beyond the right border of

61 © FunctionX, Inc.
Windows Events Borland C++ Builder

the far right control. These rules apply in the same way to the Range property of the vertical scroll bar,
controlled by the VertScrollBar property, based on the form’s ClientHeight.

When a horizontal scroll bar appears, the rectangular bar is positioned on the far left side of the scroll bar.
If there is a vertical scroll bar, it would be on the top section of the control. The position of this bar is
controlled by the Position property which is an integer value. This property is set using an integer value
and is related to the Range value. When a form appears, by default, the Position is set to 0, which is the far
left for the horizontal and the top for the vertical scroll bars. As the user slides a scroll bar, the position of
the bar is: Position = Range – ClientWidth. At design time, you can set where the bar would be positioned
by setting the Position to a value less than Range – ClientWidth.

When the user clicks an arrow on a scroll bar, the control slides by one pixel in the opposite direction. This
value is controlled by the Increment property. If one pixel is not enough, you can set this value to your
liking.

The physical height of the horizontal scroll bar and the width of the vertical scroll bar are controlled by
their respecticve Size property. The side measurement of the arrow button on each side of the scroll bars is
controlled by the ButtonSize property.

For aesthetic reasons and others, there are three styles of scroll bars, controlled by the TScrollBarStyle
enumerator. The most common and default Style is ssRegular which results in raised border arrow buttons
and a raised bar. To get flat scroll bars, set the Style to ssFlat; this adds a “web” effect to the control. The
borders appear when the mouse is on top of an arrow button or the central bar. If you Style is set to
ssHotTrack, the arrow buttons or the bar reverses their color when the user positions the mouse on top.

As a visual control, a scroll bar can benefit from color that set it apart from the rest of the form. By default,
a scroll bar inherits the color of the form that hosts it. This is set from the ParentColor property. Since the
default color of a form is clBtnFace, this applies to the the scroll bar. To change this and assign a different
color to a scroll bar, change its Color property to any color you like. The new color would apply to the
scrolling region.

2.7.3 TControlScrollBar Methods


The TControlScrollBar class is not a Windows control. This means you will (almost) never have any reason
to create it. If or when a control (form or ScrollBox) needs it, the needing control will create it.

62 © FunctionX, Inc.
Windows Events Borland C++ Builder

Chapter 3:
Fundamental Controls

 Controls Design and Properties

 Changing Form and Controls Properties

 Forms

 Command Buttons

 Labels

 Text Boxes

 Introduction to Expressions
63 © FunctionX, Inc.
Windows Events Borland C++ Builder

3.1 Command Buttons


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 the mouse’s left button.

There are various kinds of buttons. The most common and regular is a rectangular object
that the user can easily recognize and use. In some 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.

From the programmer’s standpoint, a button needs a host; this could be a form, a toolbar,
or another container. Once you have decided where the button will reside, you can use
the drag n’ drop process of Borland C++ Builder to add it to your program

3.1.1 The Command Button


The most popular button used in Windows applications is a rectangular control that
displays a word or a short sentence that directs the user to access, dismiss, or initiate an
action or a suite of actions. In C++ Builder, this control is implemented using the Button
control from the Standard tab of the Component Palette. Therefore, to add a button to a
container, click the Button control and click on the container, which is usually a form.
Once you have added the control to your application, you can set its properties using the
Object Inspector.

3.1.2 Button Properties


From the user’s point of view, the only things important about a button are the message it
displays and the action it perform. Therefore, 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 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 dialog 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
usefull on a button whose 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, click the
word Caption and type the desired caption.

64 © FunctionX, Inc.
Windows Events Borland C++ Builder

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()
{
Button1->Caption = "Let Me Go!";
}
//---------------------------------------------------------------------------

To the programmer, one of the most important properties of any control is the Name.
This allows you and the compiler to know what control you are referring to when the
program is running. By default, the first button you add to a form is named Button1, the
second would be Button2. Since a program usually consists of many buttons, it would be
a good idea to rename your buttons and give them meaningful names. The name should
help you identify what the button is used for. To change the name of a control, on the
Object Inspector, click the word Name and type a valid C++ name. Refrain from trying
to change the name of any control with code.

When a form is hosting many controls, including buttons, it is a good


idea to set the control that has focus when the form opens. This is
done using the form’s ActiveControl property. By default, as we
know about the Tab Order, the order of controls on a container is
directed by the order of adding them to the container. Even if a
control was added last, and regardless of the Tab Order, you can set a
certain control to have focus when the form launches. To set the
ActiveControl, give focus to the form. On the Object Inspector, click
the ActiveControl field to reveal its combo box; click its combo box
and select a control from the list.

To set the active control programmatically, call the TForm::ActiveControl property


(actually, the ActiveControl property belongs to the TCustomForm control). Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::SetTheActiveControl()
{
ActiveControl = Button3;
}
//---------------------------------------------------------------------------

A very important property of a button is the Default property. The Default is a Boolean
property. If you set its value to true, this button will have a thick border; this means that
if the user presses Enter any time, the action associated with the button would be
executed. This is usually set on a dialog box with a button whose caption displays OK.

Another useful property that you should always set, or whenever possible, is the Cancel.
Using a Boolean variable, the Cancel property allows the user to press Esc to perform the
same action that would be used to dismiss a dialog box. This is important on a dialog box
if the button’s caption is Cancel or Close.

The position of the control is controlled by the Left and Top properties. The dimensions
of the control are set by the Width and Height properties.

65 © FunctionX, Inc.
Windows Events Borland C++ Builder

If the form or dialog that is hosting the button is not the first form
or dialog (in other words, if the form or dialog is accessed by a
call from another form or dialog), 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. This is a very useful and convenient way to
find out what button the user clicked, without going through a lot
of code. To use a button as a valid integral ModalResult, 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 and 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 happended? Where are you?";
}
}
//---------------------------------------------------------------------------

Depending on what you are trying to do, sometimes you will not want the user to see a
control until another action has occurred. To hide a control, use the Visible property. As a
Boolean value, the Visible property toggles the appearance and the disappearance of a
control. To set the visibility of a control, give focus to the control. On the Object
Inspector, you can click the arrow of the combo box or you can double-click the value of
the field until the desired value is set. To programmatically hide a control, use the
TControl::Visible property. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::HideTheControl()
{
Button1->Visible = False;
}
//---------------------------------------------------------------------------

Another useful feature of C++ Builder comes in toggling the appearance and the
disappearance of a control. The only thing you have to do with the Visible property is to
reverse its state. This will come very handy when using menus and toolbars, etc (imagine
how easy it is to hide or display a control or a menu item with one line of code, no
pointer, no dynamic creation or declaration of any class). The following example toggles
the appearance of a form by checking whether the control (in this case the seond form) is
displaying or not. If the control (the second form) is visible, it gets hidden and vice-versa:

66 © FunctionX, Inc.
Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::ToggleControlAppearance()
{
Form2->Visible = !Form2->Visible;
}
//---------------------------------------------------------------------------

Also a Boolean value, the Enabled property allows you to enable or disable a control.
When a control is enabled, it can perform and respond to all of its normal operations. A
disabled button cannot receive focus and most, if not all, of its properties and actions
cannot be performed or acted on. You can set and control the Enabled property the same
way you would do with the Visible property.

If you position a (visual) control on a form, if the control is positioned on the top left
section of the form, when the user resizes the form, the control’s position would appear
static, it would not move. This is a concern if the control is positioned on the right, the
bottom or the lower right section of the form. When the user resizes the form, the
button’s position would not be updated. Sometimes you will want the control to have the
same measurement with regard to the bottom, the right, and/or the lower right corner of
the form. This ability is controlled by the Anchors property. The anchoring of a control
to its parent or host container is controlled using a set property derived from the
TAnchors enumerator. By default, when you add a control to a form, it is “glued” to the
top left corner of its container. Since this property is a Set, you can the control’s position
with regards to its container’s right and bottom borders.

Practical Learning: Buttons

1. Create a new project with the starting form


2. From the Component Palette, on the Standard tab, click the Button control

.
3. Click on the form. Notice that a button has been drawn on the form.
4. To move the button, click and hold your mouse on it. Then drag to the desired
location, for example, move it to the upper left section of the form.
5. On the Standard tab of the Component Palette, double-click the Button control.
6. On the form, move the second button, Button2, and position it under Button1
7. On the form, click Button1 to select it.
8. On the Object Inspector, click Caption and type &Close

67 © FunctionX, Inc.
Windows Events Borland C++ Builder

9. Notice that its caption has changed. Also notice the Caption field in the Object
Inspector.
10. In the Object Inspector, click the Name field and type btnClose
11. On the form, click Button2 to select it.
12. Type btnQuit
13. Notice that this time, the name has changed because the Name field had focus.
14. On the Object Inspector, click the Caption field and type &Quit
15. To make this button dismiss its form when the Esc key is pressed, double-click
the false value of the Cancel field to change it to true.
16. Click anywhere on the form and change its dimensions to Height = 152 and
Width = 315.
17. To test the form, press F9.
18. After viewing the form, close it.

3.1.3 Button Events


The most regular action the user performs on a a button is to click it. Therefore, the
default event on a button is the OnClick. To initiate the OnClick event on a button,
double-click it.

One of the most regular actions you will assign to a button is the close its parent form
when the user clicks the button. There are different reasons you will want to close a
dialog. If the form or the dialog 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. When
studying message boxes, we will review other situations of dismissing a dialog box by
clicking a button.

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’s PostQuitMessage() function. This function takes one argument
which is an integer. The argument could be set to almost any integer value although it
should be WM_QUIT.

Practical Learning: Using Button Events


1. On the form, double-click the Close button. Notice that the Code Editor opens.
2. Press Tab and type:

Close();
3. Click the arrow of the combo box on the top section of the Object Inspector and
select btnQuit

68 © FunctionX, Inc.
Windows Events Borland C++ Builder

4. Click the Events tab.


5. Double-click the empty box on the right side of OnClick.
6. Notice the cursor on the Code Editor.
7. Press Tab and type:

Note
The PostQuitMessage()
PostQuitMessage(WM_QUIT);
function is part of the 8. To test the form, on the Debug toolbar, click the Run button.
Win32 library
9. Click the Close button. Notice that this action closes the form.
10. Click the Run button again to execute the program.
11. Press Esc. Notice that the form closes also and this takes you back to Bcb.
12. Change the PostQuitMessage as follows:

PostQuitMessage(0);
13. Execute the program to test it. Click the OK button to close the form.
14. Press F12 to display the form.
15. Double-click the Quit button to get to the Code Editor. Notice that you are taken
back to the Code Editor. Edit the PostQuitMessage() function as follows:

PostQuitMessage(WM_DESTROY);
16. To test the form press F9. After viewing the form, close it.
17. To add another form, on the View toolbar, click the New Form button.
18. While the new form is still displaying, on the Object Inspector, click the
Properties tab and set the following properties for the second form: BorderStyle
= bsDialog; Caption = Mission and Assignment; Height = 260; Width = 395
19. Press and hold Shift. On the Component Palette, click the Button control.
Release the Shift key.
20. Click on the form three times to add three buttons

69 © FunctionX, Inc.
Windows Events Borland C++ Builder

21. On the Component Palette, click the arrow button to dismiss the Button
control selection.
22. Arrange the three buttons on the form to make them visible.
23. Set the properties of the first button as follows: Caption = OK; Default = true;
ModalResult = mrOk
24. Set the properties of the second button as follows: Cancel = true; Caption =
Cancel; ModalResult = mrCancel;
25. Set the properties of the 3rd button as follows: Caption = Abort; ModalResult =
mrAbort.

26. On the Code Editor, click Unit1.cpp


27. To display the first form, press F12.
28. On the main menu, click File -> Include Unit Hdr…
29. From the Use Unit dialog box, make sure Form2 is selected and click OK
30. To add another button, from the Standard tab of the component Palette, click the
Button control.
31. Click on the form to add the button and move it to under the Quit button.
Change its caption to Form &2
32. Double-click the Form 2 button and implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Form2->ShowModal();
}
//---------------------------------------------------------------------------
33. Add another button to the form and enlarge it to cover most of the unoccupied
area on the form. Set the name of the new button to btnMessage and its caption
to Message

70 © FunctionX, Inc.
Windows Events Borland C++ Builder

34. While the new button is still selected, on the Object Inspector, click the field on
the right side of the Font property (it displays (TFont).
35. Set the characteristics to Font = Times New Roman, Font Style = Bold, and
Size=14. Click OK

36. Double-click the new large button and implement its OnClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnMessageClick(TObject *Sender)
{
if( Form2->ShowModal() == mrOk )
btnMessage->Caption = "I came back OK";
else if( Form2->ShowModal() == mrCancel )
btnMessage->Caption = "I was dismissed!!!";
else if( Form2->ShowModal() == mrAbort )
btnMessage->Caption = "Mission Impossible";
else
btnMessage->Caption = "What's Happening?";
}
//---------------------------------------------------------------------------
37. To test the project, click the Run button.
38. After testing the application, close it
39. To create a new project, on the main menu, click File  New…
40. Make sure Application is selected and click OK.
41. When asked to save the project, click No.
42. On the Object Inspector, click Caption and type Form and Buttons Interaction
43. Click Height and type 280
44. Click Width and type 380
45. From the Standard tab of the Component Palette, double-click Button.
46. On the Object Inspector, click Caption and type &Juventus
47. Click Name and type btnTeam
48. Click Left and type 16. Click Top and type 16
49. On the Component Palette, double-click Button

71 © FunctionX, Inc.
Windows Events Borland C++ Builder

50. On the Object Inspector, click the + of the Anchors properties. Set its
characteristics as follows: akLeft = false; akTop = false; akRight = true;
akBottom = true.
51. Click Caption and type &Sidney
52. Click Left and type 288
53. Click Name and type btnCity
54. Click Top and type 216
55. To test the project, press F9.
56. To resize the form, position the cursor on the lower-right corner then drag down
and right. Notice that the Sidney button is anchored to the bottom and right
borders of the form. Close the form
57. On the Component Palette, double-click Button.
58. Change its Caption to &Turtle, its Left value to 288, its Name to btnAnimal,
and its Top value to 16
59. On the Component Palette, double-click Button.
60. Set its Caption to &Hamburger, its Left value to 16, its name to btnFood, and
its Top value to 216
61. On the Component Palette, double-click Button
62. Change its Cancel field to true and its Caption to Close
63. Change its name to btnClose

64. On the form, double-click the Close button.


65. Press Tab and type:

Close();
66. Press F12 to display the form

72 © FunctionX, Inc.
Windows Events Borland C++ Builder

67. Double-click Juventus, press Tab and type:

BtnClose->Enabled = False;
68. To test the form, on the View toolbar, click the Run button.
69. Click Juventus. Notice that the Close button is disabled.
70. Click the Close button on the form. Notice that it is not working

71. To close the form, click its Windows Close button


72. To toggle enabling and disabling the Close button, change the OnClick event of
the btnTeam button with:

btnClose->Enabled = !btnClose->Enabled;
73. Press F12 to display the form
74. Double-click the Turtle button and implement its OnClick event as follows:

void __fastcall TForm1::btnAnimalClick(TObject *Sender)


{
if( btnTeam->Caption == "&Juventus" )
btnTeam->Caption = "&Naples";
else if( btnTeam->Caption == "&Naples" )
btnTeam->Caption = "&Juventus";
}
75. To test the form, press F12 and press F9.
76. Click Turtle button a few times and notice that the caption of the team button
toffles. Click the team (Juventus or Naples) button. Notice that the Close button
is disabled and you cannot click it. Click the team button again to enable the
Close button.
77. Make sure you close the form using the Close button in the middle of the form.
78. Press F12 to display the form and click an unoccupied area of the form.
79. Click the Events tab.
80. Double-click the box on the right side of the OnResize field.
81. In the implementation of the event, press Tab and type:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
btnAnimal->Left = Width - 92;
btnClose->Top = (ClientHeight - btnClose->Height) / 2;
btnClose->Left = (ClientWidth - btnClose->Width) / 2;
}
//---------------------------------------------------------------------------
82. Press F12 to display the for. To test the form, press F9.
83. Resize the form by enlarging or shrinking it. Notice how the turtle and the Close
buttons are anchored to the borders of the form.

73 © FunctionX, Inc.
Windows Events Borland C++ Builder

3.1.4 Button Methods


The Button cannot boast a lot 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 construtor used to dynamically create a
button. You might also use the destructor to delete the control after using it. Most of the
other methods used on a button are derived from member variables of the TButton class.

The TWinControl::SetFocus() allows you to give focus to a particular control on the


form.

Practical Learning: Using Button Methods

3.1.5 Dynamic Buttons


A dynamic button is one you create at runtime. This happens when you could not or
would not create a button at design time.

To create a dynamic button, use the TButton contructor. Declare a pointer to a TButton
object and use the new operator to assign the constructor. There are two important pieces
of information you need to provide. The instance of the object and the container of the
control.

If you decide to create a button locally, in a function or an event, declare an instance of


the control and specify its parent. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::CreateAButton()
{
TButton* Btn = new TButton(this);
Btn->Parent = this;
}
//---------------------------------------------------------------------------

The problem with a locally created object is that it is available only in the function or
event in which it is created. You cannot access it outside the function or event. The
alternative is to create the object globally in the header file of its host.

To create an object globally, in the private or the public section of the parent’s header
file, declare a pointer to the contructor:

private:
TButton* Foot;

In the constructor of the host, use the new operator to assign an instance of the object’s
contructor:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Foot = new TButton(this);
}
//---------------------------------------------------------------------------

74 © FunctionX, Inc.
Windows Events Borland C++ Builder

Once you have the object initialized, to display it, set its parent and the desired
properties:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Foot->Parent = Form1;
Foot->Caption = "I'm Running";
Foot->Left = 220;
Foot->Top = 205;
}
//---------------------------------------------------------------------------

3.2 Bevels
A bevel is a VCL control used to enhance the display of a form by adding a box, a frame
or a line. A bevel shares a lot of the other controls properties, this means that you can
modify them at design and/or run times.

3.2.1 Bevel Properties


To add a bevel object to your form, click it on the Additional tab of the Component
Palette and click on the form. In its uniqueness, although the bevel does not have much
functionality, some of its properties make it a valuable accessory for your form’s look.
By default, a bevel does not have a particular alignment on the form; it completely
depends on the developer. Unlike the TForm and TPanel controls, the bevel control is
not a container; therefore, although you can place controls inside a bevel, the bevel does
not control their position or alignment. In other words, the bevel does not “own” them.

The two most important properties of a bevel are its shape and its style. The Shape
property is a TBevelShape enumerator that controls how the bevel appears. You can set
the bevel to appear as a line, to show borders or to be empty. To set the shape of the
bevel, click it on the form to select it. On the Object Inspector, click Shape to reveal its
combo box and select from the list. To set the bevel’s shape programmatically, use code
such as this:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Bevel1->Shape = bsFrame;
}
//---------------------------------------------------------------------------

With the cursor positioned on the right side, press Ctrl + Space to displcy the valid values
and select from the list. The Style property is a TBevelStyle enumerator that specifies
whether the bevel will be lowered or raised with regard to the surface of its host
container.

Practical Learning: Adding a Bevel Control

75 © FunctionX, Inc.
Windows Events Borland C++ Builder

1. Create a new application with the starting form.


2. Set the dimensions of the form as follows: Height = 456, Width = 504. Set the
BorderStyle to bsDialog.
3. Click the + sign on the HorzScrollBar and VertScrollBar fields and set each of
their Visible properties to false.
4. On the Component Palette, click the Additional tab and double-click the Bevel
control.
5. Set the bevel properties as follows: Align = alNone, Height = 18, Left = 0,
Shape = bsBottomLine, bsLowered, Top = 184, Width = 490.
6. On the Component Palette, click the Standard tab. Double-click the Button.
7. Change the button’s properties as follows: Caption = &Details >>, Cursor =
crVSplit, Left = 408, Top = 160.
8. Also add a few visual controls on the top and the bottom sections of the form.
9. Double-click an unoccupied area on the form to initiate the form’s OnCreate
event. Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Height = 228;
Bevel1->Visible = False;
}
//---------------------------------------------------------------------------

10. Press F12 to display the form. Double-click the Details button to initiate its
OnClick event. Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if( Height == 228 )

76 © FunctionX, Inc.
Windows Events Borland C++ Builder

{
Height = 456;
Bevel1->Visible = True;
Button1->Caption = "&No Details";
}
else if( Height == 456 )
{
Height = 228;
Bevel1->Visible = False;
Button1->Caption = "&Details >>";
}
}
//---------------------------------------------------------------------------
11. To test the application, on the Debug toolbar, click the Run button.

3.2.2 Bevel Methods


The Bevel control has no other methods than the constructor and the destructor. All of its
methods are derived from its parent and ancestor classes.

You should never call the TBevel class, if you want to dynamically create a bevel,
declare a TBevel object. Using the new operator, assign it the bevel constructor
specifying the control component as the form on which the bevel will be positioned. You
must also specify the control parent of the bevel. You can dynamically create a bevel
inside of a function or another control’s event. In the following example, a bevel is
created in an OnClick event of a button called Button2:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TBevel* Bvl = new TBevel(Form1);
Bvl->Parent = this;
}
//---------------------------------------------------------------------------

If you create a bevel in a function, the control would not be available to other sections of
a program. If you want the control to be global, declare a TBevel object in the unit’s
header file in the private or the public sections:

private: // User declarations


TBevel *Beauty;

In the form’s constructor, initialize the control using the new operator and specifying the
component that would host the control:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Beauty = new TBevel(Form1);
}
//---------------------------------------------------------------------------

After creating the control, you can programmatically set its properties. If the control was
created locally, set these properties in the function or event:

77 © FunctionX, Inc.
Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TBevel* Bvl = new TBevel(Form1);
Bvl->Parent = this;

Bvl->Height = 115;
Bvl->Left = 8;
Bvl->Shape = bsFrame;
Bvl->Style = bsRaised;
Bvl->Top = 8;
Bvl->Width = 210;
}
//---------------------------------------------------------------------------

If you had created the control in the header file, you can use a function or event to
initialize the control:

//---------------------------------------------------------------------------
void __fastcall TForm1::ControlTheBevel()
{
Beauty->Parent = Form1;
Beauty->Left = 240;
Beauty->Width = 146;
Beauty->Top = 80;
Beauty->Height = 100;
Beauty->Style = bsRaised;
}
//---------------------------------------------------------------------------

To manipulate the control, you can use any event of the form. For example, the following
code sets the bevel’s anchors:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
Beauty->Anchors = TAnchors() << akRight << akBottom;
}
//---------------------------------------------------------------------------

3.3 The Panel Control


The panel control provides two valuable services for application design. First, like a
bevel, a panel allows you to design very good-looking forms by playing with colors and
other properties such as Align and Style. Unlike bevels, panels are not transparent;
therefore, their color can be changed to control their background display. Also, the panel
will be your second favorite container, besides the form. Unlike a bevel, a panel is a
complete control with properties, methods, and events.

3.3.1 The Panel and its Properties

78 © FunctionX, Inc.
Windows Events Borland C++ Builder

To add a panel to a form, click the Panel control from the Standard tab of the Component
Palette. Then click in the desired location on the form. Although you can create a panel to
be a container standing on its own, at design time, the only way you can use the control is
to add it to a form.

After adding a control to a container, you may want to “glue” it to one border or corner of
its host, as you would do with the Anchors property. Unlike anchoring a control, the
Align property allows you to fix a control to one border of its host:

By default, the Align property is set to


alNone. In this case, the control can assume
any position with regard to its host control

When the Align property is set to alLeft, the


control will be fixed to the left border of its
host.

A control whose Align property is set to


alTop can serve as a toolbar or a floatable
window on the top section of its host.

If the control has the Align property set to


alRight, the control would be anchored to the
right border of its container.

79 © FunctionX, Inc.
Windows Events Borland C++ Builder

A control can be used as a status bar that


always displays on the bottom section of the
form. In this case, its Align property would
be set to alBottom.

If a control’s Align property is set to


alClient, it would occupy the client area of
the container. If another control on the same
container already have one of the previous
alignments, except alNone, the control whose
Align property is set to alClient would
occupy only the remaining unoccupied area.

Most controls that use a caption allow you to control how such text would be aligned as a
paragraph. The Alignment property is a TAlignment enumerator that lets you align text
to the left (default), the center, or the right. If the control, such as a panel would not
display a caption, you can leave this property “as is”. To change the Alignment property,
click it on the Object Inspector to reveal its combo box. Click the arrow and select the
desired value: taLeft, taCenter, or taRight.

Three specific bevel properties allow you to customize the appearance of a panel. A panel
object is drawn with two borders: an inner and an outer borders. You can decide which
one or both would use the bvNone, bvLowered, bvRaised, or bvSpace. Using a
combination of these values on the BevelInner and BevelOuter fields, you can create
special effects for the apperance of a panel. The other property to take into consideration
is the BevelWidth value. This is an integer that controls the border value of a panel.
Playing with these three values can tremendously transform the appearance of a panel.

Another property that acts on a panel’s display is the BorderStyle; this controls the line
used to draw the contour of the panel.

A panel can be used as a button, in which case the user would click it to initiate an action.
A panel can also simply display a message to the user. In any case you want to display a
word or a group of words, you can use the Caption property to show it.

A property that is highly used on forms and panels is the Color. If you change the Color
property, the new color would cover the face of the panel:

80 © FunctionX, Inc.
Windows Events Borland C++ Builder

Figure 14: Using Panels

One of the most useful actions performed on a panel consists of involving it in drag and
drop operations. A panel can serve as the source or the destination on such an operation.

The DockSite property uses a Boolean value to indicate that the control, in this case the
panel, can serve as the host for a drag’n’drop operation. The DragKind property
specifies how the control participates in the drag’n’drop operation. If the control serves as
a docking host, set its DragKind property to dkDock. On the other hand, if the control
will itself be used when dragging, set its DragKind property to dkDrag. If a control is
“draggable”, use the DragMode property to specify how the dragging operation on the
control would be initiated. If you want the dragging operation to be possible when the
user clicks the control, set its DragMode property to dmAutomatic. Otherwise, some
controls, depending on the result you are trying to achieve, should be available for
dragging only depending on an intermediary action. In such a case, you can write your
program so that the dragging operation on a control would be available only after the
application or another event or control has called the TControl::BeginDrag() method. In
this case, set the DragMode property to dmManual.

3.4 Affiche
The form painted.
Practical Learning: Form Events
1. Double-click:

2. Press it.
3. .
4. Implement the FormClick event as follows:

81 © FunctionX, Inc.
Windows Events Borland C++ Builder

5. code to:

6. To test the form press F9.


7. Tab and type:

Color = TColor(RGB(X % 255, Y % 255, (X + Y) % 255));


8. To test type:

Color = TColor(RGB(420 - X, Y - 280, abs(X - Y) % 255));


9. To test.

Practical Learning: Displaying A Dependent Form


1. On the
2. Implement the event as follows:

3. To .
4. Implement it as follows:

5. Scroll up on the Code Editor and, under the #include "Unit1.h" line, add the
following:

6. To field.
7. Implement it as follows:

8. Double-click the box of the OnMouseMove event.


9. Implement it as follows:

Color = TColor(RGB(X, Y, abs(Y - X)));


10. To test the form, press F9.
11. it.
12. Close the first form.
Other Form’s Properties
1. Start files.
2. Click Save.
3. project.
4. .

82 © FunctionX, Inc.
Windows Events Borland C++ Builder

3.5 Exercises

83 © FunctionX, Inc.
Windows Events Borland C++ Builder

Chapter 4:
Introduction to Text Controls

84 © FunctionX, Inc.
Windows Events Borland C++ Builder

4.1 The Label Control


Borland C++ Builder ships with many string classes for most of the controls uses to
perform any necessary string manipulation. The AnsiString class is the most used of the
string classes. It controls the caption property of all controls that need to set or control
their caption. Before getting into the characteristics of these classes, we will study two of
the most fundamental controls used in C++ Builder.
A label is a control that serves as a guide to the user. It provides a static text that the user
cannot change but can read to get information about another control on the form. The
programmer can also use it to display simple information to the user. Most controls on
the form are not explicit at first glance and the user would not know what they are.
Therefore, you can assign a label to the control as a help to the user.

To add a label to a form, click it from the Standard tab of the Component Palette and
click on the form. You can also dynamically create a label.

A label is a child of the TCustomLabel class which itself is derived from the
TGraphicControl class.

4.1.1 Label Properties


The most used property of the label control is the caption, and the Caption is the label’s
default property. The caption controls what the user would see or read. To set a label’s
caption, after adding the control to a container, click Caption in the Object Inspector and
type the desired value.

When you type the caption of a label, C++ Builder helps its size itself so the caption can
be fit. If you edit the label, as you delete or add characters, the label resizes itself. If you
want to fix the size of the label regardless of its caption, set the Boolean property
AutoResize to false. By default, this property is set to false on most controls that use; but
on a label, it is set to true.

If you want to create a shadow effect using a label object, you can place one label on top
of another. Using the Transparent property, which is a Boolean value, you can make the
top label transparent.

Practical Learning: Labels Design


1. Start Borland C++ Builder if you did not yet. To start a new program, on the
main menu, click File  New  Application

2. To save the current project, on the Standard toolbar, click Save All
3. Loacte the C:\BcbExercises folder. Click the Create New Folder button to create
a folder.
4. Type Employment Application and press Enter twice to display the new folder
in the Save In combo box.
5. To rename the current unit, in the File Name box, replace the name with Main
and press Enter
6. Type Employment as the name of the project and press Enter.

85 © FunctionX, Inc.
Windows Events Borland C++ Builder

7. From the Standard tab of the Component Palette, click the Label control
8. Click on the form.
9. As the new label is still selected, on the Object Inspector, click Caption and type
Date &Hired:

10. To move the new label, click and drag it to the left section of the form. To
position it precisely, using the Object Inspector, set the label’s properties as
follows: Left = 16, Top = 96
11. To add another label, on the Standard tab, double-click the Label control
12. On the Object Inspector, click the Caption field and type &First Name:
13. Set its Left property to 16 and its Top to 120.
14. Add the following other labels:

15. To add another label, click the Label control and click on the top section of the
form.
16. On the Object Inspector, click the Caption field, type Employment Application
17. Click the gray box on the right side of the Font field. Notice the ellipsis button.
18. Click the ellipsis button to open the Font dialog.
19. Change the font to Times New Roman
20. In the Font Style combo box, click Bold.
21. In the Font Size combo box, select 24

86 © FunctionX, Inc.
Windows Events Borland C++ Builder

22. Click the arrow of the Color combo box and select Blue

Figure 15: The Font Dialog Box

23. Click OK
24. On the Object Inspector, click the Name field and type lblMainTitle
25. Double-click the box on the right side of the Transparent field. Instead of false,
it should now display true.
26. On the form, click the Employment Application label to select it.
27. On the main menu, click Edit  Copy.
28. Click an unoccupied area on the form to make sure nothing is selected.
29. On the main menu, click Edit  Paste.
30. As the new label is still selected, click the + on the Font field.
31. Under the Font field, click Color to reveal its combo box. Click the arrow of its
combo box and select clGray
32. Click the – on the Font field.
33. Click the Name field and type lblTitleShadow
34. Click the arrow on the top section of the Object Inspector and select
lblMainTitle

35. Click the Left field and type 16


36. Click the Top field and type 8
37. Click the arrow on the top section of the Object Inspector and select
lblTitleShadow
38. Click the Left field and type 19
39. Click the Top field and type 11

87 © FunctionX, Inc.
Windows Events Borland C++ Builder

40. Right-click on the group of those big labels. One of them will be selected. On
the context menu, click Send To Front. If the blue label does not come in front,
right-click again and click Bring To Back until the blue label is on top of the
white label:

Figure 16: Adding a shadow to a label

41. To add another label on the form, on the Component Palette, double-click the
Label control.
42. While the new label is still selected, click the Caption field and type
Tenley Associates

43. Click the Cursor field.


44. Click the arrow of the cursor field and field select crHandPoint
45. Click the + on the Font field to expand it.
46. Under the Font field, click the Color field and click its arrow.
47. Select clRed.
48. Click the Name field and click its combo box. Select Garamond.
49. Set the (Font) Size field to 10.
50. Click the + on the Style field to expand it.
51. Double-click the field on the right side of fsBold to change it to true
52. Double-click the field on the right side of fsUnderline to change it to true.
53. Click the – on the Font field to collapse
54. Click the Left field and type 416
55. Click the Top field and type 8
56. Add the following other labels:

Name Caption Font Size Left Top


lblCompAdr 4412 Conic Rd Suite 204D MS Serif 7 414 24
lblCompCity Silver Spring MD 20910 MS Serif 7 420 34
lblCompPhone (301) 309-0330 MS Serif 7 440 46
57. Click an unoccupied area on the form.
58. To add a horizontal line on the form, add a label and for its caption, type ____
(Shift + -) continuously until a horizontal line spans the form. Position that line
under the big blue label.

88 © FunctionX, Inc.
Windows Events Borland C++ Builder

59. To test the project, press F9:

Figure 17: Improving a form with labels

60. To save the project, on the Standard toolbar, click Save All.

4.1.2 Label Methods


The Label does not have any methods per se, only a constructor and a destructor. You
should never directly call either the TLabel constructor or the ~TLabel destructor. These
are only used if you want to dynamically create a label.

To dynamically create a label locally, in a function or an event, declare a TLabel object


and use the new operator, specify the component that owns the instance of the control. To
initiate the control, you must specify its container or parent:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TLabel* Lbl = new TLabel(Form1);
Lbl->Parent = Form1;
}
//---------------------------------------------------------------------------

To create a label object globally, declare a TLabel object in the private or the public
sections of the header file of the unit that owns it:

private: // User declarations


TLabel* Team;

In the constructor of the unit, use the new operator to specify the component that owns
the control;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Team = new TLabel(Form1);

89 © FunctionX, Inc.
Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

Once you have dynamically created a label, you can control it using functions or events:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TLabel* Lbl = new TLabel(Form1);
Lbl->Parent = Form1;
Lbl->Caption = "LaFace, Inc.";
Lbl->Left = 75;
Lbl->Top = 32;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
Team->Parent = this;
Team->Left = 120;
Team->Caption = "PSV Eindhoven";
Team->Top = 96;
}
//---------------------------------------------------------------------------

When your application exits, C++ takes care of cleaning all VCL objects that you had
dynamically created. If you want to perform this housekeeping yourself, delete the object
using the delete operator. It might also be a good idea to reclaim your memory to avoid
any memory leak. This is done by assigning the NULL constant to the dynamic object
previously used:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete Team;
Team = NULL;
}
//---------------------------------------------------------------------------

4.1.3 Label Events


The Label control has a few events that are part of its repertoire, although they are hardly
used. You can configure a label to behave like a (web) link using its OnClick event. For
example the Win32 ShellExecute() function can be used to perform an operation on a
file. The following OnClick event on a label would launch WordPad:

//---------------------------------------------------------------------------
void __fastcall TForm1::lblWordPadClick(TObject *Sender)
{
ShellExecute(NULL, NULL,
"C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe",
NULL, NULL, SW_SHOWNORMAL);
}
//---------------------------------------------------------------------------

90 © FunctionX, Inc.
Windows Events Borland C++ Builder

Practical Learning: Coding a Label Control


1. Click the (red) Tenley Associates label to select it.

2. On the Object Inspector, click the Events tab.

3. Double-click the box of the OnClick field.

4. Press tab and implement the label’s OnClick event as follows:

void __fastcall TfrmEmployment::Label3Click(TObject *Sender)


{
ShellExecute(NULL, "open", "http://www.functionx.com",
NULL, NULL, SW_MAXIMIZE);
}
1. To display the form, press F12. To test the program, press F9

4.2 Edit Boxes


An Edit box is a Windows control used to get or display text for the user’s interaction. At
its most regular use, an Edit box serves as a place to fill out and provide information.
Such a use is common on an employment application, login dialog boxes, etc.

Like most other controls, the role of an edit box is not obvious at first glance; that is why
it should be accompanied by a label that defines its purpose. From the user’s standpoint,
an edit box is named after the label closest to it. Such a label is usually on the left or the
top side of the edit box. From the programmer’s point of view, an edit box is a place
holder used for various things. For example, your can show or hide it as you see fit. You
can also use it only to display a text without allowing the user to change it.

To create an edit box, once again, Bcb provides a lot of choices. The most fundamental
edit box is designed with the Edit control of the Standard tab of the component palette.

4.2.1 Edit Box Properties


The most important edit box property for both the programmer and the user is the Text.
When you add an Edit control, C++ Builder initializes it with the name of the control,
this would be Edit1 for the first edit box, Edit2 for the second, etc. If you want the control
to display some text when the form launches, type the text in the Text property field.
Otherwise, if you want the edit box to be empty when it comes up for the first time,
delete the content of the Text field.

Another important property of the Edit control is the Name. It makes it easy for you to
identify the control and its events when writing code.

Although it does not belong to an Edit control, the FocusControl property of a Label
control provides a convenient way to specify which control is associated with the label.
For example, if a label has a caption of &Country and you want the user to press Alt + C
to access the Edit control positioned under or on the right side of the label, select the
name of such an Edit control in the FocusControl field of the Label control.

The CharCase property allows the content of an Edit control to apply a character case of
your choice. The CharCase property is controlled by the TEditCharCase enumerator.
By default, it is set to normal, which respects whatever character case is typed in an edit

91 © FunctionX, Inc.
Windows Events Borland C++ Builder

box. Otherwise, you can set it to ecUpperCase or ecLowerCase to set the edit box’
charactrers to uppercase or lowercase respectively.

When using a form, the user can press Tab to move from one control to another. By
default, when such a control receives focus from the user pressing Tab, the whole text in
an edit control is selected. This is controlled by the AutoSelect property. If you do not
want that, you can set the AutoSelect Boolean property to false.

The Color property allows you to control the background color of an Edit control.

The Hint property provides a quick local help to the user. It is text that would appear if
the user positions the mouse on a control for a few seconds. The best or most effective
way to set this property is to set the form’s ShowHint property to true. To set the text
hint for a control, once the control is selected at design time, type a word or a few words
in the Hint field.

Practical Learning: Edit Box Design

1. To add an Edit box, on the Standard tab of the Component Palette, click the Edit

control .
2. Click on the form.
3. To reposition the control, click and drag the Edit control to the right side of the
Date Hired label.
4. As the Edit control is still selected, on the Object Inspector, click the Name field
and type edtDateHired
5. Click the Text field and press Delete to empty its content.
6. Using the same process, add new labels and edit boxes as follows. The name of
an edit box starts with edt follows by the caption of the label omitting the
special characters:

7. Set the FocusControl property of each label to Edit control on its right.
8. To save the project, on the Standard toolbar, click Save All.
9. To test the form, press F9.

92 © FunctionX, Inc.
Windows Events Borland C++ Builder

10. Save the project.

4.2.2 Edit Control Methods and Events


The Edit control has a constructor and a destructor used to dynamically create an edit
control. The other methods are derived from the control’s direct parent which is the
TCustomEdit class. Other methods are derived from the ancestor classes.

The Edit control is equipped with many events. Some of these events are from its parent
class the TCustomEdit class and some others are from ancestor classes.

The OnEnter event occurs when the control receives focus. This happens when the user
clicks the edit box, after previously pressing Tab, to give focus to the control.

The OnChange event occurs as the user is typing text in the control. This happens as the
user is changing the content of an edit control; this sends a message that the content of
the edit box has changed or has been updated. You can use this event to check, live, what
the user is doing in the edit box. For example, if you create a dialog with a first and last
names edit boxes, you can use another edit box to display the full name. The controls
could be drawn as follows:

You can implement the OnChange event of the first name edit box as follows:

void __fastcall TfrmPersInfo::edtFirstNameChange(TObject *Sender)


{
edtFullName->Text = edtFirstName->Text + " " + edtLastName->Text;
}

When the second edit box is being edited, you can implement its OnChange event as
follows:

void __fastcall TfrmPersInfo::edtLastNameChange(TObject *Sender)


{
edtFullName->Text = edtFirstName->Text + " " + edtLastName->Text;
}

The OnExit event occurs when the control loses focus. In the case of an edit box, this
could happen if the control has focus and the user presses Tab; the edit box would lose
focus.

4.2.3 Keyboard Events: Another Review


Besides the Button control, probably the most interactive control on the form is the edit
box; it can receive or display information, it can exhibit its own behavior. The events we
will review here apply to all controls that have the keyboard events. Therefore, our

93 © FunctionX, Inc.
Windows Events Borland C++ Builder

demonstration will serve as a broad explanation of some events common to various


controls.

When a control receives focus, the OnEnter event fires. When a control loses focus, the
OnExit event fires. When the user presses a key, the OnKeyDown event fires. When the
user releases a key, the OnKeyUp event fires.

When implementing the keyboard events, you can also perform a particular operation
depending on the key that the user pressed. Each key has a virtual key code. You can find
the list of these keys in the winuser.h header file. You can shift focus when the user
presses Enter on an edit box using the following code:

void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)


{
if(Key == 13)
Edit2->SetFocus();
}

Practical Learning: Using the Keyboard Events


1. Create a new project with a starting form
2. Add four Edit controls in the order Edit1, Edit2,Edit3, and Edit4.
3. Add two Button controls Button1 and Button2 as follows:

4. Using the Text field on the Object Inspector, delete the content of each edit box.
5. Click Button1 to select it.
6. On the Object Inspector, click Caption and type &Reset
7. On the form, click Button2 and type E&xit.
8. Double-click the Exit button and implement its OnClick event as follows:

void __fastcall TForm1::Button2Click(TObject *Sender)


{
Close();
}
9. Press F12 to display the form.
10. Double-click the Reset button and implement its OnClick event as follows:

void __fastcall TForm1::Button1Click(TObject *Sender)


{

94 © FunctionX, Inc.
Windows Events Borland C++ Builder

Edit1->Text = "";
Edit2->Text = "";
Edit3->Text = "";
Edit4->Text = "";
}
11. To test the form, press F9
12. Type Something here and press Tab.
13. Type Another thing going on and press Tab.
14. Type Downsize and press Tab
15. Type Online outsourcing and press Enter.
16. Click Reset and notice that all buttons are empty.
17. Click Exit.
18. Press F12 to display the form.
19. Click the edit box on the top left section of the form.
20. On the Object Inspector, click the Events tab.
21. Double-click the box on the right side of OnKeyDown and implement it as
follows:

void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD &Key,


TShiftState Shift)
{
Edit2->Text = "I am not gonna be ignored.";
}
22. On the Object Inspector, double-click the box on the right side of OnKeyUp and
implement its event as follows:

void __fastcall TForm1::Edit1KeyUp(TObject *Sender, WORD &Key,


TShiftState Shift)
{
Edit4->Text = "Why? What did I do?";
}
23. To test the form, press F9
24. As the cursor in the first edit box, press and hold d
25. Notice the sentence that is displaying in the second edit box. Also notice that the
fourth edit box is empty.
26. Release d
27. Notice that the third edit box is displaying a sentence now. This demonstrates
the difference between the OnKeyDown and the OnKeyUp events.
28. Click Reset to empty the edit boxes.
29. Press F12 to display the form.
30. Click the second edit box (on the top right section of the form).

95 © FunctionX, Inc.
Windows Events Borland C++ Builder

31. On the Events tab, double-click the box on the right side of OnEnter and
implement its event as follows:

void __fastcall TForm1::Edit3Enter(TObject *Sender)


{
Edit3->Text = "I got focus!";
}
32. On the Object Inspector, double-click the box on the right side of OnExit and
implement it as follows:

void __fastcall TForm1::Edit3Exit(TObject *Sender)


{
Edit3->Text = "I lost it!";
}
33. To test the form, press F9.
34. Type Courses and press Tab
35. Press Tab again to give focus to the third edit box.
36. Notice the sentence it is displaying.
37. Press Tab twice to move the focus away and notice the change of the sentence.
38. Click the third edit box (lower left edit box) and notice the sentence in it.
39. Click the second edit box and notice how the third edit updates its sentence
when it gets or loses focus.
40. Click Exit
41. Press F12 to display the form.
42. Click Reset to select it.
43. On the Object Inspector, click Properties.
44. Change the Enabled property to false.
45. Double-click the first edit box (top left section of the form) and implement its
OnChange event as follows:

void __fastcall TForm1::Edit1Change(TObject *Sender)


{
if( Edit1->Text == "" )
Button1->Enabled = false;
else
Button1->Enabled = true;
}
46. To test the form, press F9
47. Notice that the Reset button is disabled.
48. Type grade and notice that the Reset button is enabled.
49. Press Backspace a few times to delete grade
50. Notice that as soon as the first edit is empty, the Reset button is disabled.
51. Click Exit.

96 © FunctionX, Inc.
Windows Events Borland C++ Builder

52. To empty the second exit box when the first is empty, change the previous code
as follows:

void __fastcall TForm1::Edit1Change(TObject *Sender)


{
if( Edit1->Text == "" )
{
Button1->Enabled = false;
Edit2->Text = "";
}
else
Button1->Enabled = true;
}
53. Test the form.

4.3 The MaskEdit Control


The MaskEdit is a special Edit control that provides more control over text entered or
displaying in an edit box. The biggest difference between the Edit and the MaskEdit
controls is the masking possibilities available on the latter.

To add a MaskEdit control to your form, from the Additional tab of the Component
Palette, click the MaskEdit button and click on the form.

4.3.1 MaskEdit Properties


The most important property of a MaskEdit control, which sets it apart from the
(traditional) Edit control, is its ability to control what the user can and cannot enter in the
text side. To configure this text, on the Object Inspector, click the EditMask field to
reveal its ellipsis button. You have two options. If you are familiar with the masking
properties of this control, you can type a value using the appropriate symbols. Otherwise
you should use an appropriate dialog box to guide you. You have two alternatives. You
can double-click the empty area of the EditMask field or you can click the ellipsis
button. This would call the Input Mask Editor dialog box

Once there, you have various alternatives. The easiest way is to select one of the
available formats in the Sample Masks list. Once you select a sample, its formatted mask
displays in the Input Mask edit box. If the format is satisfying, you can click OK.
Otherwise, you can add or delete symbols in the Input Mask edit box as you see fit.

If none of the samples matches your desire and you know the symbols used, you can type
your own. You can also check masks created for foreign languages to see if one of them

97 © FunctionX, Inc.
Windows Events Borland C++ Builder

would have the mask you need. To do this, click the Masks… button. This would call the
Open Mask File dialog box:

Click one file with a .dem extension and click OK. With the new mask in the Input
Mask Editor, examine the samples in the Sample Masks list and select one. You can
still customize any of the available masks.

The 3rd alternative is to create your own list of masks. To do this, follow the format used
to create a mask. This is:

Name | Sample | Mask

This line is made of three sections. The first and the second, then the second and the third
are separated by a beam. To see a sample file, using Notepad, locate the C:\Program
Files\Borland\Cbuilder6\Bin folder. After changing the Files of Type to All files, click
one of the files with .dem extensions:

Click Open:

98 © FunctionX, Inc.
Windows Events Borland C++ Builder

Create a new file following the example. Each mask is typed on its own line and press
Enter at the end of each mask. To save the file, locate the C:\Program
Files\Borland\Cbuilder5\Bin folder. In the Save dialog box, change the Save As Type to
All Files. Type a name in one-word followed by an extension .dem extension. To use
your list of masks, invoke the Input Mask Editor, click Masks… Locate the C:\Program
Files\Borland\Cbuilder5\Bin folder. Change the Files of Types to All files. Click the file
you created and click Open.

You can also set a mask programmatically using the symbols appropriate for the masks.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
// Mask for an 8 character file name + 3-character extension
// The first character is automatically converted to uppercase
// After the first character, the user can enter an alphabetical
// character or a digit to complete the 8 characters.
// The other 7 characters and the extensions are converted to lowercase
edtFileName->EditMask = ">L<aaaaaaa.<LLL;1;_";
}
//---------------------------------------------------------------------------

As a text-based control, the content of the MaskEdit control is represented by the Text
property, which is an AnsiString object. Following the EditMask you had set in the
Input Mask Editor editor, you can use a default text that would display when the control
opens. To set this text, on the Object inspector, click Text and type a value that abides by
the rules of the EditText field. At design time, C++ Builder will assist you and make
sure that the value you type is appropriate. At runtime also, the user will have to follow
the rules of the mask.

When a mask is configured for a MaskEdit control, the compiler reinforces the rule to
make sure the user would follow number and types of characters allowed in the edit box.
If you add a MaskEdit control but do not apply a mask to it, you can limit the number of
characters tha the user can enter in the box. The maximum number of characters allowed
is set using the MaxLength property. This property has any effect only if no mask is
applied to the control. At design time, type an integer value for the property. At runtime,
assign an appropriate value to the control.

The IsMasked Boolean property can be used to check whether a MaskEdit control has
been configured with a mask already.

99 © FunctionX, Inc.
Windows Events Borland C++ Builder

Practical Learning: Using the MaskEdit Control


1. Open the employment application we were working on.
2. Click the edit box on the right side of the Date Hired label and press Delete.
Also delete the edit boxes on the right sides of the MI, the Home Phone, the
Employee #, the ZIP, the Work Phone, and the Ext labels
3. On the Component Palette, click the Additional tab. Click the MaskEdit button

.
4. Click on the right side of the Date Hired label on the form.
5. On the Object Inspector, click the Name and type edtDateHired

6. Click EditMask field to display the ellipsis button . Click the ellipsis button.
On the Input Mask Editor dialog, click Date. In the Input Mask edit box, change
the two zeros to four zeros:

7. Click OK
8. As the MaskEdit control still has focus, on the Object Inspector, click the Text
field and press Delete. Click its ellipsis button. Set the text to 12/05/1996:

9. Click OK.
10. On the Component Palette, click the MaskEdit control and click on the right side
of the Home Phone label. On the Object Inspector, click the Text field and
delete the content of the field. Click the EditMask field and click the ellipsis
button. Click Phone and click OK.
11. On the form, click the new masked edit box of the Home Phone box. On the
main menu, click Edit -> Copy. On the main menu again, click Edit -> Paste.
Move the new paste edit box to the right side of the Work Phone label.
12. Add another MaskEdit control to the right side of the Employee # label. Click
the EditMask and type 00-000;1;_

100 © FunctionX, Inc.


Windows Events Borland C++ Builder

13. Add a MaskEdit control to the right side of the MI label. Set its EditMask to >L
and delete the content of the Text field.
14. Add a MaskEdit control on the right side of the ZIP label. Set its Text field to
00000 and set its EditMask to 99999
15. Add a MaskEdit control to the right side of the Ext label. Delete its Text field
and set its EditMask to #####;1;_

16. Complete the form as follows:

The external bevel around the edit boxes has a Lowered Style while the external
one has a Raised Style. The Close button resides on a Panel control. The
OnClick event of the Close button is implement with the Close(); line.
17. To test the application, on the Debug toolbar, click the Run button.
18. After viewing the form, close it.

4.3.2 MaskEdit Methods


On its own, the MaskEdit control has only two methods: the constructor and the
destructor. The TMaskEdit constructor is used to dynamically create a MaskEdit object.

101 © FunctionX, Inc.


Windows Events Borland C++ Builder

This requires an instance of a TMaskEdit class. Using the new operator, specify the
owner of the control. You must also specify the parent of the variable. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMaskEdit *Mascot = new TMaskEdit(Form1);
Mascot->Parent = Form1;
}
//---------------------------------------------------------------------------

A MaskEdit object created like this is just a classic Edit control. If you want to make a
true MaskEdit object, set its properties as needed, namely an EditMask and possibly a
Text properties. This time, not only will you have to work in a non-visual setting but you
should also make sure that the EditMask and the Text properties are synchronized.
Sometimes, this would involve trial-and-error.

4.3.3 MaskEdit Events


The main event of the MaskEdit control occurs when the content of the control has been
altered. The compiler takes care of validating the characters and synmbols while the user
is editing the edit box. When the user has finished and presses Enter or Tab to possibly
shift the focus to another control, a notification is sent to the operating system. If the
value entered in the control does not conform to the EditMask, an error is thrown and the
application stops responding. For this reason, you should use the MaskEdit control only
when appropriately needed; or you should write an event handler or function that would
deal with errors of this control.

4.4 The Memo Control


Like the Edit control, the Memo control is used to display or receive test. Unlike the Edit
control, the memo can be used to display multiple lines of text. Like the Editt control, the
Memo control is based on the TCustomEdit class. But there is an intermediary class
between the TCustomEdit and the TMemo; it is the TCustomMemo class.

To add a memo to a form or another container, from the Standard tab of the Component
Palette, click the Memo button and click on the desired position on the form.

4.4.1 Memo Properties


When creating a memo used as a basis for a text editor, use the appropriate size of the
control. Like any descendant of the TControl class, a Memo control is positioned by its
Left and Top measurements that are relative to the left and top borders of its container.
The dimensions of the Memo control are set using the Width and Height properties. By
default, the control is positioned where you drop it at design time. One of the most
fundamental properties is Align. This specifies how the memo will be aligned with regard
to its container. If the memo is used as the main area of a text editor application, you
should set its Align property to alClient.

As a text based control, the user mostly reads and/or enters text in the memo when
interacting with the control. At design time, you can set the text that world display when
the memo comes up. To enter this text, on the Object Inspector, click the Lines field to
reveal its ellipsis button. You can either double-click the field on the right side of Lines

102 © FunctionX, Inc.


Windows Events Borland C++ Builder

or click the ellipsis button. This would call the String List Editor dialog box. If you
want the control to be empty at startup, delete the content of the String List Editor and
click OK. Otherwise, type the desired text and click OK.

The user, on the other hand has the ability to type text to alter the content of the memo
box. This is possible only if the ReadOnly property is set to true, which is the default. If
you want to prevent the user from altering the text in the memo, set the ReadOnly
property to false. You can also do this programmatically:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->ReadOnly = True;
}
//---------------------------------------------------------------------------

The user cannot enter, delete, or cut the text but can select or copy it. The application,
which means your programming, can still change the content of the memo.

When a memo box opens, the compiler registers the content of the control. If the user has
the ability to change the text in the control and if the user changes it, the compiler flags
the content as Modified. This allows you to take actions. You can acknowledge this by
programmatically setting the Modified property to true. If another control or some other
action alters the content of the memo, you can make sure that this property reflects the
change. You can change this programmatically as follows;

//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
Memo1->Modified = True;
}
//---------------------------------------------------------------------------

Although the user can enter any number of characters into a memo box, you can set a
maximum number that would prevent the user from going over this number of characters.
At design time, you can set the maximum number of characters in the MaxLength field.
Programmatically, you can change it as follows;

//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
Memo1->MaxLength = 24;
}
//---------------------------------------------------------------------------

If the control will be used to enter text, the user can press Enter at the end of a line to
move to the next line. This ability is controlled by the Boolean WantReturns property.
By default, this property is set to true, which means the user can press Return (also called
Enter) when typing text. If you do not want to validate the Enter key in the Memo
control, set this property to false. To set it programmatically, assign the desired value to
the WantReturns property:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Memo1->WantReturns = False;
}

103 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

When the WantReturns property is set to false, if the user presses Enter while the memo
has focus, the Enter action would be transferred to the form as the parent. The form in
turn can find out what to do. For example, you can have configured the form to perform a
particular action when the Enter key is pressed. The typical example is by setting a
button’s default property to true. In this case, pressing Enter from the Memo control
would cause the action associated with the button. Even if the WantReturns of a memo
is set to false, the user can still press Ctrl + Enter to move to the next line.

In the same way, the user is accumstomed to pressing Tab to insert tab characters in the
text. By default, when the user presses Tab when interacting with your application, the
focus moves from one control to the next, following the TabOrder values of the form.
Even when using a memo to perform text editing, if the user presses Tab, the focus would
switch to another control or to the form. If you want a memo to receive focus when the
user presses the Tab key, set the WantTabs property from false (the default), to true.
Programmatically, you can do it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->WantTabs = True;
}
//---------------------------------------------------------------------------

When entering text in a Memo control, the characters start on the left side of the memo
and are subsequently added on the right side. The ability to align text is controlled by the
Alignment property. For a Memo control, the alignment is configured using the
TAlignment enumerator:

enum TAlignment { taLeftJustify, taRightJustify, taCenter };

By default, the text is aligned to the left. To align the content of the memo to the center
section of the control, set its Alignment property to taCenter. To align it with regard to
the right side of the memo, set its Alignment to taRightJustify. You can also configure
this with code as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Alignment = taRightJustify;
}
//---------------------------------------------------------------------------

As the user enters text in a memo box, the compiler considers that a paragraph starts from
the user typing a character until he or she presses Enter. Therefore, a paragrph could be
an empty space, a character, a word, a line of text, a whole page or an entire book.
Depending on the width of the Memo control, the text is incrementally added to the right
side of each previous character. If the caret gets to the right border of the control, the text
continues to the next line, although it is still considered as one paragraph. To start a new
paragraph, the user has to press Enter. The ability for the text to continue on the next line
when the caret encounters the right border of the memo is controlled by the WordWrap
property whose default Boolean value is set to true. If you do not want text to wrap to the
subsequent line, set the WordWrap property to false. You can also set it
programmatically as follows:

104 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->WordWrap = False;
}
//---------------------------------------------------------------------------

The Memo control is typically used to perform text editing and can therefore contain
many lines of text. Sometimes the user needs to scroll up, down, left, and right to read
different sections of the control. The memo scrollbars are set using the TScrollStyle
enumerator:

enum TScrollStyle { ssNone, ssHorizontal, ssVertical, ssBoth };

To apply the scrollbars on a memo, use the ScrollBars property on the Object Inspector.
By default, a newly added Memo control does not have scrollbars although the user can
still scroll vertically in the text. This is because its ScrollBars property is set to ssNone.
To display the vertical scrollbar, set this property’s value to ssVertical. A horizontal
scrollbar would display if this property has a value of ssHorizontal. If you need both
scrollbars, set this property to ssBoth. You can also set the scrollbars programmatically
as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
Memo1->ScrollBars = ssBoth;
}
//---------------------------------------------------------------------------

4.4.2 Memo Methods


The Memo control is equipped with a constructor and a destructor. The constructor is
mostly used to dynamically create a memo box. To do this, declare a TMemo object
using the new operator to specify the owner of the control. You must also specify the
parent of the variable.

If you want to generate a memo needed only by an event or a function, create it locally.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMemo *Notes = new TMemo(Form1);
Notes->Parent = Form1;
}
//---------------------------------------------------------------------------

Such a memo would not be accessible outside of the function or event in which it is
created. If you want to make the memo available to other functions or events, in the
header file of the control that would host it, declare a TMemo variable in the private or
public section:

private:
TMemo * Comments; // User declarations

105 © FunctionX, Inc.


Windows Events Borland C++ Builder

Use the new operator to specify the owner of this control. This should be done in the first
event or function that would need to know about the dynamically crerated control.
Therefore, you should usually do this in the form’s constructor:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Comments = new TMemo(Form1);
}
//---------------------------------------------------------------------------

To display the memo, use the event or function that would initiate it. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnShowCommentsClick(TObject *Sender)
{
Comments->Parent = Form1;
}
//---------------------------------------------------------------------------

If you had created the memo locally, set any of the properties as necessary. You can
change just the default values or configure any that would affect the behavior of the
control. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnNotesClick(TObject *Sender)
{
TMemo *Notes = new TMemo(Form1);
Notes->Parent = Form1;

Notes->Left = 350;
Notes->Top = 20;
Notes->Height = 120;
Notes->Width = 320;
}
//---------------------------------------------------------------------------

If you created the memo globally, you can access it anywhere and change its properties
where appropriate:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnShowCommentsClick(TObject *Sender)
{
Comments->Parent = Form1;
Comments->Align = alLeft;
Comments->Width = 420;
Comments->Font->Color = clWindowText;
// A button called btnBackground was added to change
// or togglethe background color of the memo
btnBackground->Enabled = True;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnBackgroundClick(TObject *Sender)
{
if(Comments->Color == clWindow)
{
Comments->Color = clBackground;

106 © FunctionX, Inc.


Windows Events Borland C++ Builder

Comments->Font->Color = clWhite;
}
else
{
Comments->Color = clWindow;
Comments->Font->Color = clWindowText;
}
}
//---------------------------------------------------------------------------

In order to use a memo, or any windowed control, the control must receive focus. This
could be done by the user clicking it. In the case of a memo box, the user usually gives it
focus by clicking inside of it or pressing Tab that could lead to the memo.
Programmatically, you can give focus to a control using the TWinControl::SetFocus()
method. Its syntax is:

void __fastcall TWinControl::SetFocus(void);

This method does not perform any other action than to give focus to the appropriate
control. It is typically used in response to an action that should hand the window focus to
the needed control. For example, after changing the font of a memo, in order to continue
text editing, the control would naturally need to regain focus. To give focus to a memo,
you could write code such as:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnShowCommentsClick(TObject *Sender)
{
Comments->Parent = Form1;
Comments->Align = alLeft;
Comments->Width = 420;
Comments->Font->Color = clWindowText;
Comments->SetFocus();
// A button called btnBackground was added to change
// or togglethe background color of the memo
btnBackground->Enabled = True;
}
//---------------------------------------------------------------------------

The content of a memo box can have one of two states, either it is empty or it contains
something. If you want it empty, use the Clear() method. This would delete the whole
content of the control:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnClearMemoClick(TObject *Sender)
{
Memo1->Clear();
}
//---------------------------------------------------------------------------

One of the actions the user performs on a memo’s text is to select it. To select a portion
of text, the user would drag from one end of the text to the desired end. Alternatively, you
can allow the user to select the whole content of a text-based control using the SelectAll()
method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnSelectAllClick(TObject *Sender)
{

107 © FunctionX, Inc.


Windows Events Borland C++ Builder

Memo1->SelectAll();
}
//---------------------------------------------------------------------------

If the user or another control or action had selected text on the memo, you can delete the
selection using the ClearSelection() method. This method first finds if some text is
selected. If so, the selected text would be discarded. If nothing is selected, the method
would not do anything. To delete a selected text, you can write:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnClearSelectionClick(TObject *Sender)
{
Memo1->ClearSelection();
}
//---------------------------------------------------------------------------

4.4.3 Memo Events


As a control, the only event that the Memo control can claim on its owns is the
OnChange event. This occurs when the user changes the content of the control. This
event is useful if you want to display a notification that the text is not what it was when
the form opened. For example, combined with the Modified property, you can change the
caption of the form:

//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1Change(TObject *Sender)
{
Caption = "* Untitled.txt";
}
//---------------------------------------------------------------------------

When the application focus moves from one to another control or the application itself to
a control, the OnEnter event is fired. When the control looses focus, an OnExit event is
fired.

108 © FunctionX, Inc.


Windows Events Borland C++ Builder

Chapter 5:
A Study of VCL Strings

109 © FunctionX, Inc.


Windows Events Borland C++ Builder

5.1 Constructing Strings


String operations in C++ Builder are mainly performed using AnsiString. The
AnsiString class is not derived from TObject; therefore, it enjoys a good level of
independence and flexibility from the application or the control that wants to use it.

Many controls use AnsiString properties. All controls that use a caption (forms, panels,
labels, etc) have their Caption property set as an AnsiString. Many other controls such as
the edit box use the AnsiString class as the basis of their text. Based on these two facts,
you have already used and implemented AnsiString objects. In some other scenarios you
will need to declare and possibly initialize a string before using it.

5.1.1 Declaring a String


To declare a string, use the AnsiString word followed by a valid C++ name. Here is an
example:

AnsiString Country;

Since the AnsiString is a class with its own constructor, you can also declare its variable
with empty parenthese, which would be calling the class’ construtor. Here is an example:

AnsiString City();

5.1.2 Initializing a String


There are two main ways you can initialize an AnsiString variable. After declaring it, you
can assign the desired value to the variable using the assignment operator. Here is an
example:

Note AnsiString Country;


The AnsiString class was Country = “Madagascar”;
redefined as String in the
VCL documentation You can also initialize the string variable when declaring it, again, using the assignment
(actually, you can find its
typedef redefinition in the operator and providing the desired value. Here is an example:
sysmac.h header file).
Therefore, instead of AnsiString Province("British Columbia");
AnsiString, you can use
the word String wherever
you would use the Once you have defined the string you can use it as you see fit. You can use it to change a
AnsiString word. control’s caption:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Country;
Country = "Madagascar";
Panel1->Caption = Country;
}
//---------------------------------------------------------------------------

You can also use it to fill out an edit control:

110 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString City = "Antananrivo";
Edit1->Text = City;
}
//---------------------------------------------------------------------------

5.2 General Purpose String Functions


These are functions performed on strings regardless of any other consideration. For
example, before performing any operation on a string, sometimes you will first need to
find out whether the string contains something or it is empty. Eventually, you will decide
what to do if the string is empty.

5.2.1 Checking Whether a String is Empty


There are two main ways you can check whether the content of a text-based control is
empty. To find out whether a control is empty, you can just use the AnsiString
“==”overloaded operator. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Original = Edit1->Text;
if(Original == "")
Edit2->Text = "Why is Edit1 empty?";
}
//---------------------------------------------------------------------------

The AnsiString class provides its own function used to check whether a string is empty.
Its syntax is:

bool __fastcall IsEmpty() const;

This function can be used to check whether a text-based control contains nothing but it
cannot empty a text control. The following example shows two ways of using the
AnsiString::IsEmpty() method:

//---------------------------------------------------------------------
void __fastcall TOKBottomDlg::OKBtnClick(TObject *Sender)
{
String UserName = edtUserName->Text;
if( UserName.IsEmpty() )
Panel1->Caption = "Please provide a User Name";
if( edtPassword1->Text == "" )
Panel1->Caption = "You need to type a password";
if( edtPassword2->Text.IsEmpty() )
Panel1->Caption = "Your account is not complete";
edtUserName->SetFocus();
}
//---------------------------------------------------------------------------

111 © FunctionX, Inc.


Windows Events Borland C++ Builder

5.2.2 Trimming a String Left


Trimming a string is an operation that gets rid of leading or ending spaces in a string.

To remove any (empty) space on the left side of a string, you can use the
AnsiString::TrimLeft() method. Its syntax is:

AnsiString __fastcall TrimLeft() const;

If the original string has space on its left, this function would remove it and return a string
that is like the original without the leading space. If the original does not have any
leading space, the function would return the same string:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit2->Text = Edit1->Text.TrimLeft();
}
//---------------------------------------------------------------------------

Another function used to perform the same operation is the TrimLeft(). Its syntax is:

AnsiString _fastcall TrimLeft(const AnsiString S);

As opposed to the AnsiString::TrimLeft() method, the (global) TrimLeft() function


takes one argument which is the string that needs to be left trimmed. The function returns
a new string that is the same as the original omitting the leading space (if any exists):

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit2->Text = TrimLeft(Edit1->Text);
}
//---------------------------------------------------------------------------

5.2.3 Trimming a String Right


To remove any space on the right side of a string, you can use the
AnsiString::TrimRight() method. Its syntax is:

AnsiString __fastcall TrimRight() const;

If the original string has space on its right, this function would remove it and return the
same string without any trailing space. Otherwise, the original string would be returned:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit2->Text = Edit1->Text.TrimRight();
}
//---------------------------------------------------------------------------

Another function used to perform the same operation is the TrimRight(). Its syntax is:

AnsiString _fastcall TrimRight(const AnsiString S);

112 © FunctionX, Inc.


Windows Events Borland C++ Builder

The (global) TrimRight () function requires one argument as the string that needs to be
trimmed. The function returns the original string without the trailing space:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit2->Text = TrimRight(Edit1->Text);
}
//---------------------------------------------------------------------------

5.2.4 Trimming a String on Both Sides


Other functions allow you to combine the last two operations into one. You can use the
AnsiString::Trim() method to remove spaces on both sides of a string. Its syntax is:

AnsiString __fastcall Trim() const;

Here is an example of using this method:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit2->Text = Edit1->Text.Trim();
}
//---------------------------------------------------------------------------

Alternatively, you can use the global Trim() function to perform the same operation. Its
syntax is:

AnsiString _fastcall Trim (const AnsiString S);

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit2->Text = Trim(Edit1->Text);
}
//---------------------------------------------------------------------------

5.3 Fundamental String Conversions


Text that the user types in a program, such as in an edit box is considered a string. This is
because the compiler cannot assume what kind of value the user or the client of an Edit
control would supply. For this reason, after a value has been provided to a control that
uses the AnsiString as the basis of its content, if you want to perform any mathematical
operation on the string you must convert the string to a valid data type.

113 © FunctionX, Inc.


Windows Events Borland C++ Builder

5.3.1 Converting Regular Data Types to AnsiString


The AnsiString provides a lot of constructors that allow you to create a string of any kind.
For example you can use it to declare:
• a character:

AnsiString Symbol = 'H';

• an interger

AnsiString Int = 120;

• a long integer

AnsiString Longer = -73495745;

• a floating-point value:

AnsiString WeeklyEarnings = 675.15;

• a double-precision number:

AnsiString WeeklyEarnings = 675.15;


AnsiString Silver = 2.15e28;

• a string

AnsiString GirlFriend = "Micheline Phoon";

Any of these variables can be declared using their equivalent constructors:

AnsiString Symbol('H');
AnsiString Int(120);
AnsiString GirlFriend("Micheline Phoon");
AnsiString WeeklyEarnings(675.15);
AnsiString Longer(-73495745);
AnsiString Silver(2.15e28);

Based on the configurations of the AnsiString constructors, you can convert any value
and make it available to a control that uses an AnsiString property. For example, you can
convert and display:
• a character:

char Sign = 'q';


Edit1->Text = AnsiString(Sign);

• an interger

Integer Number = 808;


Caption->Text = AnsiString(Number);

• a long integer

long Value = 497783L;


Panel1->Caption = AnsiString(Value);

114 © FunctionX, Inc.


Windows Events Borland C++ Builder

• a floating-point value:

Float Distance = 1205.62;


Label1->Caption = AnsiString(Distance);

• a double-precision number:

Double YearlyIncome = 24588;


Edit1->Text = AnsiString(YearlyIncome);

• a string

AnsiString Food = "Peanut Butter";


Button2->Caption = AnsiString(Food);

5.3.2 AnsiString and C-Strings


The AnsiString class is configured to recognize null-terminated strings of the classic C
string functions. The AnsiString class has a constructor that can convert a null-terminated
C string to AnsiString. Thanks to this constructor, the AnsiString(const char* Source),
you can declare a C string and use it as you see fit:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char Status[] = "Employee Status";
Caption = Status;
char *FullName = "Antoine Williams";
Edit1->Text = FullName;
}
//---------------------------------------------------------------------------

Based on this constructor, you can declare a C string, manipulate its value and use it in
your application.

To convert an AnsiString to a null-terminated string, use the AnsiString::c_str() method.


The syntax of this function is:

char* __fastcall c_str() const;

This function is very valuable because it can help you perform various types of string
operations. Sometimes you will need to perform an operation that seems trivial but there
woule not be an AnsiString method that can accommodate your needs.

5.3.3 Requesting an AnsiString From the User


The AnsiString class does not allow you to request its variables or display its values on
the DOS prompt. Alternatively, you can use C functions, such as gets() and puts(), as
intermediary for this operation. This allows you to write a Console application that can
still use AnsiString strings. Here is an example:

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

115 © FunctionX, Inc.


Windows Events Borland C++ Builder

#include <iostream.h>
#include <vcl.h>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{
char Cont[20];
AnsiString Country;

cout << "Enter a country: ";


gets(Cont);
cout << "\n";

Country = Cont; // Assign the AnsiString to the char


puts(Cont); // Display like this
puts(Country.c_str()); // or like this

cout << "\nPress any key to continue...";


getchar();
return 0;
}
//---------------------------------------------------------------------------

5.4 Changing Strings Cases


There are various techniques you can use to convert a string from lowercase to uppercase
and vice-versa. These methods are useful for string comparison and when writing
password algorithms.

An alphabetical character is recognized as being in lowercase if it is one of the following


characters: a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z. On the other
hand, a character qualifies as uppercase if it is one of A, B, C, D, E, F, G, H, I, J, K, L,
M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z. All the other symbols are ignored even if on
the keyboard you would press Shift to type them.

5.4.1 Converting from Lowercase to Uppercase


To convert a lowercase character or string to uppercase, you can use the
AnsiString::UpperCase() function. Its syntax is:

AnsiString __fastcall UpperCase() const;

This function considers an AnsiString variable and examines each one of its characters. If
a character is an alphabetic character in lowercase, it would be converted to uppercase. If
the character is either an alphabetical character in uppercase or it is not an alphabetic
character, it would be kept “as is”. This method also considers the Regional Settings of
the computer being used.

If you want to convert a single character to uppercase, after initializing or getting, call
this method. Here is an example:

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

116 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall TForm1::Button1Click(TObject *Sender)


{
String S = 's';
Edit1->Text = S.UpperCase();
}
//---------------------------------------------------------------------------

You can use this same method to convert a string to uppercase as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String S1 = "James N. Fame!";
String S2 = S1.UpperCase();
Edit1->Text = S2;
}
//---------------------------------------------------------------------------

This would produce:

Besides the the AnsiString method, you can use the UpperCase() function to convert a
character or string to uppercase. Its syntax is:

AnsiString __fastcall UpperCase(const AnsiString S);

This function uses the same algorithm as the AnsiString::UpperCase() method. Here is
an example of using it:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String S1 = "James N. Fame!";
String S2 = UpperCase(S1);
Edit2->Text = S2;
}
//---------------------------------------------------------------------------

The AnsiUpperCase() function uses the same syntax as the UpperCase() function and
applies the same algorithm as the AnsiString::UpperCase() method. Unlike the
UpperCase() function, the AnsiUpperCase() function considers the Regional Settings of
the computer being used. Look at how these two functions convert the same French
string:

//------------------------------------------------------- //-------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject void __fastcall TForm1::Button1Click(TObject
*Sender) *Sender)
{ {
String S1 = "La maison? Ça a été brûlée!"; String S1 = "La maison? Ça a été brûlée!";

117 © FunctionX, Inc.


Windows Events Borland C++ Builder

String S2 = AnsiUpperCase(S1); String S2 = AnsiUpperCase(S1);


Edit2->Text = S2; Edit2->Text = S2;
} }
//------------------------------------------------------- //-------------------------------------------------------

5.4.2 Converting from Uppercase to Lowercase


You can use the AnsiString::LowerCase() method to convert an uppercase character or
string to lowercase. Its syntax is:

AnsiString __fastcall LowerCase() const;

Using the Regional Settings, this function examines each character of the provided
AnsiString variable. If a character is an alphabetic character in uppercase, it would be
converted to lowercase. The case of all the other characters would be ignored.

If you want to convert a single character to uppercase, after initializing or getting, call
this method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
String String1 = "[Borland C++ Builder]";
edtConvert->Text = String1.LowerCase();
}
//---------------------------------------------------------------------------

You can also use the LowerCase() function to convert a character or string to lowercase.
Its syntax is:

AnsiString __fastcall LowerCase(const AnsiString S);

This function uses the same algorithm as the AnsiString::UpperCase() method. Here is
an example of using it:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
String String1 = "[Borland C++ Builder]";
edtConvert->Text = LowerCase(String1);
}
//---------------------------------------------------------------------------

If the local settings you are using or distributing your program to are a factor, you should
use the AnsiLowerCase() function. It processes the string in the same way as the
AnsiString::UpperCase() method but uses the same syntax as the UpperCase()
function:

118 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
String S1 = "La version Française de Borland C++ Builder est là. "
"Elle est arrivée!";
edtConvert->Text = AnsiLowerCase(S1);
}
//---------------------------------------------------------------------------

5.5 Adding and Appending Strings

5.5.1 Using the + Operator


To add one AnsiString object to another, you use the addition operator (it was overloaded
to respond appropriately). The operation would produce a new string that combines the
first and the second string. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit3->Text = Edit1->Text + Edit2->Text;
}
//---------------------------------------------------------------------------

You can then use the addition operation to add as many strings as you see fit.

Practical Learning: Using the Addition Operator to Add Strings


1. Create a new project with the starting form.
2. Add three Edit controls named edtFirstName, edtLastName, and edtFullName
respectively. Add the labels that identify the edit boxes.
3. Set the ReadOnly property of the edtFullName control to true.
4. Add a panel to the lower section of the form. Add a bevel around the labels and
edit boxes. Set the bevel’s Shape to bsFrame and its Style to bsRaised:

119 © FunctionX, Inc.


Windows Events Borland C++ Builder

5. Double-click the edtFirstName control to launch its Onchange event. Implement


it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtFirstNameChange(TObject *Sender)
{
edtFullName->Text = edtFirstName->Text + " " +
edtLastName->Text;
}
//---------------------------------------------------------------------------
6. Also implement the OnChange event of the edtLastName as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtLastNameChange(TObject *Sender)
{
edtFullName->Text = edtFirstName->Text + " " +
edtLastName->Text;
}
//---------------------------------------------------------------------------
7. Double-click the panel object to initiate its OnClick event. Implement its
OnClick event with Close();
8. To test the application, on the Debug toolbar, click the Run button.

5.5.2 Appending Strings


Appending two strings consists of adding one string to another string. This operation
usually involves two strings: a destination and a source strings.

To append two strings, besides the the addition operator “+”, you can use the
AppendStr() function. Its syntax is:

void __fastcall AppendStr(AnsiString &Destination, const AnsiString Source);

This function takes two arguments as strings. The source is added to the destination. The
function returns the destination already changed by the operation. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Destination = "Paul ";

120 © FunctionX, Inc.


Windows Events Borland C++ Builder

AnsiString Source = "Lombard";


AppendStr(Destination, Source);
Edit1->Text = Destination;
}
//---------------------------------------------------------------------------

5.6 Strings and their Length


There are various methods you can use to get or control the length of a string.

5.6.1 Getting the Length of a String


To find the length of a string, if the string is from the C string class, you can first convert
it using the AnsiString::c_str() function, then use the strlen() function to get its length:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char* S = Edit1->Text.c_str();
Edit2->Text = strlen(S);
}
//---------------------------------------------------------------------------

To get the length of an AnsiString variable, use the AnsiString::Length() method. Its
syntax is:

int __fastcall Length() const;

This function returns the length of the string as an integer. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString S = Edit1->Text;
Edit2->Text = S.Length();
}
//---------------------------------------------------------------------------

5.6.2 Controlling the Length of a String


The AnsiString class allows you to impose the number of characters of a string. It uses
the following method:

AnsiString& __fastcall SetLength(int NewLength);

This method takes one argument which is the length you want the AnsiString variable to
have. If the NewLength argument is less than the length of the string, the resulting string
would be the first NewLength characters of the original string. If the NewLength
argument is less than the length of the string, the original would be preserved and
assigned to the resulting string:

121 © FunctionX, Inc.


Windows Events Borland C++ Builder

//--------------------------------------------------- //---------------------------------------------------
void __fastcall void __fastcall
TForm1::Button1Click(TObject *Sender) TForm1::Button1Click(TObject *Sender)
{ {
AnsiString S = Edit1->Text; AnsiString S = Edit1->Text;
Edit2->Text = S.SetLength(7); Edit2->Text = S.SetLength(4);
} }
//--------------------------------------------------- //---------------------------------------------------

5.7 Strings Comparison Functions


You can perform comparison of two strings. This allows you to find out which one of
two strings is longer or whether both strings are equal.

When comparing two strings, the compiler sometimes checks lowercase and uppercase
characters. Depending on the function you are using, you can ask the compiler to
consider the case of the characters; this is referred to as case-sensitivity. Some of the
functions, when performing their comparison on Dates or currency values, would refer to
the Regional Settings of your computer as set in the Control Panel.

5.7.1 Checking the Same Text


The SameText() function is used to compare two strings. Its syntax is:

bool __fastcall SameText(const AnsiString String1, const AnsiString String2);

The function requires two AnsiString variables and compares them. The comparison is
performed without case-sensitivy. If the strings are the same, the result is true (the integer
equivalent is 1); otherwise the comparison yields false (0).

You can use the SameText() function on a validation dialog like this one:

122 © FunctionX, Inc.


Windows Events Borland C++ Builder

Then you can implement the OnClick() event of the OK button as follows:

//---------------------------------------------------------------------
void __fastcall TOKBottomDlg::OKBtnClick(TObject *Sender)
{
String Password1 = edtPassword1->Text;
String Password2 = edtPassword2->Text;
Boolean Result = SameText(Password1, Password2);

if(Result == False)
{
Panel1->Caption = "Your passwords do not match!";
edtPassword1->SetFocus();
}
else
{
Panel1->Caption = "Your account has been setup.";
Close();
}
}
//---------------------------------------------------------------------------

5.7.2 String Comparison With Case-Sensitivity


The AnsiString::AnsiCompare() method is used to compare two strings with regard to
case sensitivity. This function, when performed on dates and currency values, considers
the Regional Settings of your computer. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString String1 = Edit1->Text;
AnsiString String2 = Edit2->Text;

if(String1.AnsiCompare(String2) < 0)
Edit3->Text = "True";
else if(String1.AnsiCompare(String2) > 0)
Edit3->Text = "False";
else

123 © FunctionX, Inc.


Windows Events Borland C++ Builder

Edit3->Text = "Equal";
}
//---------------------------------------------------------------------------

Besides the AnsiString::AnsiCompare() method, you can use the AnsiCompareStr()


function to compare strings. Like the AnsiString::AnsiCompare() method, this method
takes into consideration the Windows Regional Setings. Its syntax is:

int __fastcall AnsiCompare(const AnsiString& OtherString) const;

The function considers its own string and compares it to the string argument it takes. This
function returns:
1. a negative value if your string is less than the OtherString
2. a positive value if your string is greater than the OtherString
3. 0 if both strings are the same

To compare strings, you can also use the CompareStr() function. Unlike the
AnsiString::AnsiCompare() method, this function does not care about the Windows
Regional Settings. The syntax of this function is:

int __fastcall CompareStr(const AnsiString First, const AnsiString Second);

The function takes two string arguments and examines their characters incrementally.
After the comparison, the function returns:
4. a negative value if the First string is less than the Second
5. a positive value if the First string is greater tham the Second
6. 0 if both strings are the same

5.7.3 String Comparison With Case-Insensitivity


The AnsiString::AnsiCompareIC() method performs a comparison of two strings,
considering the Regional Settings. Unlike the AnsiString::AnsiCompare() method, this
function does not care about case-sensitivity.

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString String1 = Edit1->Text;
AnsiString String2 = Edit2->Text;

if(String1.AnsiCompareIC(String2) < 0)
Edit3->Text = "True";
else if(String1.AnsiCompareIC(String2) > 0)
Edit3->Text = "False";

124 © FunctionX, Inc.


Windows Events Borland C++ Builder

else
Edit3->Text = "Equal";
}
//---------------------------------------------------------------------------

Alternatively, you can use the CompareText() function to compare strings. Unlike the
AnsiString::AnsiCompareIC() method, this function does not care about the Windows
Regional Settings. The syntax of this function is:

int __fastcall CompareText(const AnsiString First, const AnsiString Second);

The function takes two string arguments and examines their characters incrementally.
After the comparison, the function returns:
1. a negative value if the First string is less than the Second
2. a positive value if the First string is greater tham the Second
3. 0 if both strings are the same

5.8 Strings Boolean Comparisons


The AnsiString and the sysutils library provide techniques of comparing strings. The
functions we have used to perform comparisons returned integral values at the end of
their comparisons. Sometimes, when performing specific algorithms, such as comparing
passwords, performing mathematical calculations, performing spell checks in text
documents, etc, you will only need to know whether two strings are equal. This type of
comparison renders a Boolean value of true or false. Both libraries tend to handle any sort
of comparison.

5.8.1 Getting the Same String


When you have two strings and would like to find out whether both are equal, you have a
lot alternatives. Using the AnsiString class, to find out whether two strings are equal, you
can use the (overloaded) == operator. If both strings are equal, the conditional
comparison would return true.

You can also use the AnsiSameStr() function. Its syntax is:

bool __fastcall AnsiSameStr(const AnsiString First, const AnsiString Second);

The function takes the Windows Regional Settings into consideration when comparing
the First and the Second strings with case-sensitivity. If both strings are the same, the
function return true. If they are not the same, the result is false. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnSendClick(TObject *Sender)
{
String EMail1 = edtEMail1->Text;
String EMail2 = edtEMail2->Text;

if(AnsiSameStr(EMail1, EMail2))
{
frmCongratulations->ShowModal();
Close();
}

125 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

Alternatively, to compare two strings, you can use the AnsiSameText() function. Both
functions use the same syntax. Like the AnsiSameStr() function, the AnsiSameText()
considers the Regional Settings. Unlike the AnsiSameStr() function, the AnsiSameText()
function does not consider the case of the characters in the strings.

If the strings you want to compare label captions, such as those you see on a form, it
would be cumbersome to write a comparison function that would examine them. This is
because the captions on a form usually have an ampersand used to underline one of their
characters. Examples include First Name, Address, City, Full Name or Department.
Fortunately, Borland provides the AnsiSameCaption() function. Its syntax is:

bool __fastcall AnsiSameCaption(const AnsiString First, const AnsiString Second);

This function takes two captions and compares them considering the Regional Settings .
Regardless of where the ampersand is positioned, the other characters of the captions
would be examined. If tboth captions are the same, the function would return true. In the
following example, two captions are set as First Name and First Name respectively. A
regular comparison would find them different, but the AnsiSameCaption() function
finds that both strings are the same:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
lblCaption1->Caption = "&First Name";
lblCaption2->Caption = "First &Name";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareCaptionsClick(TObject *Sender)
{
String Caption1 = lblCaption1->Caption;
String Caption2 = lblCaption2->Caption;

if(AnsiSameCaption(Caption1, Caption2))
Panel1->Caption = "Same captions";
else
Panel1->Caption = "Completely Different";
}
//---------------------------------------------------------------------------

5.8.2 AnsiString Boolean Operators


The == operator is configured to compare two strings. The strings are typed on both sides
of the operator. If both are the same, the comparison would return a true value:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Edit1->Text == Edit2->Text)
Panel1->Caption = "Same Text";
else
Panel1->Caption = "Different Stuff";
}
//---------------------------------------------------------------------------

126 © FunctionX, Inc.


Windows Events Borland C++ Builder

On the other hand the != operator checks whether two strings are not the same:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Edit1->Text != Edit2->Text)
Panel1->Caption = "The strings are different";
else
Panel1->Caption = "The same thing everywhere";
}
//---------------------------------------------------------------------------

We learned different techniques of comparing strings and finding out whether one was
greater than the other. Using Boolean operators, you can find out solely if one string is
greater or less than another.

The < operator is used to find out whether one string is less than another. The strings are
written on both sides of the operator, like this: S1 < S2. If the left string is less than the
right string, the comparison returns true:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String S1 = Edit1->Text;
String S2 = Edit2->Text;
if(S1 < S2)
Panel1->Caption = "The first is less than the second strings";
else
Panel1->Caption = "I don't understand this!";
}
//---------------------------------------------------------------------------

The <= operator is used to find out whether one string is less than or equal to another.

5.8.3 Operations on Strings


The + operator is used to add two strings:

The = operator is used to assign one string to another;

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String S1 = Edit1->Text;
String S2 = S1;
Edit2->Text = S2;
}
//---------------------------------------------------------------------------

127 © FunctionX, Inc.


Windows Events Borland C++ Builder

5.8.4 AnsiString Individual Characters


There are many operations you can perform on individual characters of an AnsiString
variable. These include checking for a character, finding the position of a character, or
deleting a character or characters.

5.8.5 Last Character of a String


To find the last character of a string, use the AnsiString::AnsiLastChar() method. Its
syntax is:

char* __fastcall AnsiLastChar() const;

You can use this method to find out the last character of a given string. In the following
example, the last character of the string in the Edit1 edit box displays in the Edit2 edit
box when the user clicks the Button1 control:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String S = Edit1->Text;
Edit2->Text = S.AnsiLastChar();
}
//---------------------------------------------------------------------------

If the AnsiString is used on a console application, you can use this same method to find
the last character of an AnsiString variable:

cout << “\nThe last character of the first name is “;


puts(FirstName.AnsiStringChar());

5.8.6 Deleting Characters


Sometimes you will want to get rid of a character in a string. This is done using the
AnsiString::Delete() method. The syntax is:

AnsiString& __fastcall Delete(int Index, int Count);

This function takes two integer arguments. The first argument specifies the position
where the compiler would start considering the deletion. The second argument specifies
the number of characters that should be deleted from the AnsiString variable.

If you declare an AnsiString variable called Country. You can use Country.Delete(14, 11)
to delete 11 characters starting at the 14th character:

AnsiString Country("United States of America");


AnsiString After;

puts(Country.c_str());
After = Country.Delete(14, 11);
puts(After.c_str());

128 © FunctionX, Inc.


Windows Events Borland C++ Builder

5.9 String Quotations


In the strict of string routines, a quote is a character or symbol used to delimite a string. It
sets the beginning and end of a string. In the English language, a quote is represented
with the double-quote symbol “. The VCL is equipped with functions used to insert or
remove quotes from a string.

5.9.1 The AnsiQuotedStr Function


The AnsiQuotedStr method is used to “convert” a string into a quoted string. Its syntax
is;

AnsiString __fastcall AnsiQuotedStr(const AnsiString Source, char Quote);

This function takes one string, the Source argument, and returns it added the Quote
characters on both sides of the string. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtQuotedExit(TObject *Sender)
{
char *BookTitle = edtQuoted->Text.c_str();
char Quote = '"';

AnsiString Quoted = AnsiQuotedStr(BookTitle, Quote);


edtBookTitle->Text = Quoted;
}
//---------------------------------------------------------------------------

5.9.2 Adding a Single Quote to a String


The QuotedStr() function is used to add a single-quote on both sides of a string. Its
syntax is:

AnsiString __fastcall QuotedStr(const AnsiString S);

129 © FunctionX, Inc.


Windows Events Borland C++ Builder

This function takes one string and returns it after adding a single-quote on both sides.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtQuotedExit(TObject *Sender)
{
char *BookTitle = edtQuoted->Text.c_str();

AnsiString Quoted = QuotedStr(BookTitle);


edtBookTitle->Text = Quoted;
}
//---------------------------------------------------------------------------

5.9.3 Removing the Quotes on a String


When a string is provided with quotes and you want to remove the quotes, use the
AnsiExtractQuotedStr() function. Its syntax is:

AnsiString __fastcall AnsiExtractQuotedStr(char * &Source, char Quote);

This function takes two arguments. The Source parameter is a null-terminated string that
is returned as an AnsiString value. When using the function, you must specify what
character or symbol is used as Quote. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtQuotedExit(TObject *Sender)
{
char *BookTitle = edtQuoted->Text.c_str();
char Quote = '"';

AnsiString RemoveQuotes = AnsiExtractQuotedStr(BookTitle, Quote);


edtBookTitle->Text = RemoveQuotes;
}
//---------------------------------------------------------------------------

5.10 Working With Substrings


A substring is a string that is included in another string. C++ and C++ Builder allow you
to find a substring in an original string, to get the position of a substring in a string, etc.

5.10.1 Getting a Substring


With a string, you can create a new string retrieved from the original using the
AnsiString::SubString() method. Its syntax is:

130 © FunctionX, Inc.


Windows Events Borland C++ Builder

AnsiString __fastcall SubString(int StartPosition, int HowManyChars) const;

This function takes two arguments as integers. From the original string, the first argument
specifies the position of the character where the new string would start. The second
argument specifies the number of characters that would be considered when creating the
new string. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Original = Edit1->Text;
AnsiString SubOne = Original.SubString(9, 4);
Edit2->Text = SubOne;
}
//---------------------------------------------------------------------------

5.10.2 The Position of a Substring


The AnsiString allows you to analyze a string and find out whether it contains a certain
substring. If it does, you can find out the integer position of the substring, using the
AnsiString::Pos() method (in many cases, you can also use the AnsiString::AnsiPos()
method). Its syntax is:

int __fastcall Pos(const AnsiString& SubString) const;

5.10.3 Console and AnsiString Objects


It is not possible to display an AnsiString object at the DOS prompt. Instead, you can use
C or C++ functions as intermediary:

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

#include <vcl.h>
#include <stdio.h>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{
AnsiString FirstName("Suzanne");
AnsiString LastName("ZOO");
AnsiString FullName = FirstName + " " + LastName;

puts(FirstName.c_str());
puts(LastName.c_str());
puts(FullName.c_str());

puts("\nPress any key to continue...");


getchar();

return 0;
}

131 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

5.10.4 Finding and Replacing a character or Substring


When performing your algorithms or other specific types of operations on strings, you
may want to find out whether a certaing character or group of characters has been
provided in a string. If so, you might want to replace it with a different character or with a
new substring. This operation is handled by the StringReplace() function. Its syntax is:

AnsiString __fastcall StringReplace(const AnsiString Original, const AnsiString


LookFor, const AnsiString ReplaceWith, TReplaceFlags FlagToUse);

The StringReplace() function will look for the LookFor character or substring in the
Original string. If it finds it, then it will replace the LookFor character or subtring with
the ReplaceWith character or substring. You control how this operation is performed by
using the FlagToUse argument. The values you can use are to replace all occurrences of
LookFor with ReplaceWith; the flag used would be rfReplaceAll. You can also ask the
compiler not to take the character(s) case into consideration, which is done with
rfIgnoreCase. Once the TReplaceFlags argument is a set, you can use one or both of the
flags. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit1->Text =
StringReplace(Edit1->Text, " ", "",
TReplaceFlags() << rfReplaceAll);
}
//---------------------------------------------------------------------------

132 © FunctionX, Inc.


Windows Events Borland C++ Builder

Chapter 6:
Applications Accessories

133 © FunctionX, Inc.


Windows Events Borland C++ Builder

6.1 WinHelp Anatomy


WinHelp was the primary help system used on applications at the time Microsoft
Windows 3.X was on desktop and office computers. Its popularity could have come from
its relative ease of use and Microsoft making it free. This system has stayed strong
despite the arrival of Microsoft HtmlHelp.

The most classic mode of WinHelp consists of a directory or table of contents that leads
to the topics that consistitute the body of the help system. WinHelp has other customized
variations such as a better looking but less commonly used Windows Explorer-like
interface with a table of contents on the left frame and the associated topics on the right
frame.

The WinHelp has almost disappeared from Microsoft products. In fact, one of the most
significance differences between Microsoft Office 97 and Microsoft Office 2000 and
later is the absence of WinHelp (but not completely). Almost the whole help system on
the new office family is built on HtmlHelp. But as you will see, there are many areas
where Microsoft did not have much choice, because of the limitations of HtmlHelp
(especially on context sensitive help issues).

The main reason I would encourage you to learn both systems is because each has its own
limitations that the other can complete.

6.1.1 WinHelp Description

134 © FunctionX, Inc.


Windows Events Borland C++ Builder

The primary WinHelp window is vertical rectangular dialog box made of a title bar, a tab
section and three buttons at the bottom.

The title bar allows you to move the window around the screen. It is also equipped with
two buttons. The question mark button allows you to get help while using the WinHelp
dialog box. The Close button allows you to exit from the application.

On the bottom section of the windows, the left button changes its caption depending on a
particular situation on the tabs above. The Print button allows you to print something.
You can exit any time by clicking Cancel or pressing Esc.

When you open an instance of a Winhelp document, you will likely first face the
directory of Help Topics, which is represented by the Contents property page. The
Contents tab displays the chapters or issues in a tree format. Each of these chapters is
called a topic and is represented by an icon that resembles a closed book . To view the
content of a book, you have two options. You can click a topic to highlight it, then click
the Open button; you can also double-click the topic. When a topic is opened, its icon
changes from a closed book to an open one . Depending on how the issue was
configured, some topics have sub-topics. Therefore, when you open a topic, you will see
one of two icons. If a book has only chapters, each displays with an icon that has a
question mark: . If a book consists of other books, it would display other closed-book
icons. Only the question-mark icons enclose readable chapters. To open a readable topic,
you can click it to highlight it, then click the Display button; you can also double-click it.

While the Contents tab provides library of books in a tree format, the Index tab presents a
list of words in a dictionary format. To select a word, you can scroll in the list, once you
find the desired word, you can click it and click Display; or you can double-click it. To
find the explanation of a word, you can also start typing it. As you type, WinHelp will try
to match it with a word. If you do not completely type a word, the closest match would be
highlighted, you can just press Enter to display its explanation. If you type a word that
does not exist in the Index and press Enter, you would receive an error. This means
WinHelp can address only the words that are part of its index.

The Find tab allows you to compile a list of words. Once again, its list are organized like
an dictionary and you can use it to find the explanation of a topic. The Find property page
(usually) encloses the same words as the Index and adds more (depending on how the
Help file was created.

6.1.2 Creating The Source File


The help file intended for a WinHelp file is all in one text document. The whole process
is done is various steps. To create the source document, create all of the files components
in one document, with each on its own section separate from the next. Once the topics
have been created, make a list of these topics because you will create an additional
documentation for each of them. For this process, we will use Microsoft Word.

If you work for a medium to big business, it is likely that you will be writing the help file
of an application you did not create. In a small business or for your own assignments, you
will usually be writing the help file of your own application. In one or the other scenario,
you should be fairly familiar with the application.

You do not have to create your whole help document in a row. You can start by creating
a document. The best way is to simply start make your notes, sometimes by

135 © FunctionX, Inc.


Windows Events Borland C++ Builder

brainstorming (the technique of writing “down” anything that comes in your mind) ideas
as related to the application. Organize your ideas in paragraphs, as many as you want. For
example, if you are writing a help file intended to guide employees when filling out a
time sheet, think of how they should interact with the application. When creating the help
file(s), you should have the aplplication with you; in fact, you should have used it a few
times. After making your notes and writing your ideas, organize and refine them by
sections of interest. Plan how the items of interest are related. Start dividing the document
in separate sections such as chapters. Each of these sections will be called a topic. A
section in this context could be made of one or various paragraphs.

After creating the main document (remember, you can continue adding words and
sections as necessary), save the document as a Rich Text Format. To do this, in Microsoft
Word, on the main menu, click File  Save As… (the shortcut is F12). On the Save As
dialog box, locate the folder you want to use. It does not have to be the same folder in
which the application was created. You can even create a new folder for the help file.
Then click the arrow of the Save as Type combo box and select Rich Text Format. In the
File Name box, set the name to your liking. Click Save.

6.1.3 Creating Page Breaks


After planning the content of the file and creating it, make sure that each topic can be
identified as belonging to its entity. To create this help file, you will separate each section
as if it belonged to its own page. This separation is performed by setting a page break at
the end of a section.

In Microsoft Word, there are two main ways you can create a page break in a document:
using the main menu, or creating the break manually. To create a page break using the
main menu, click Insert  Break… From the Break dialog box, click the Page Break
radio button and click OK. To manually create a page break, click the break position and
press Ctrl + Enter. Meanwhile, in Microsoft Word, it is usually a good idea to display
non-printing characters while creating a help file. This is done by clicking the Show/Hide

button .

136 © FunctionX, Inc.


Windows Events Borland C++ Builder

There will be two main types of links in your help files. A linked topic will allow the user
to jump from one topic or section to another. Another type of topic will display a pop-up
window when the user clicks it. Here is an example:

Each one of these topics must have its own Topic ID. The first category of topics consists
of those we have reviewed so far. To create the others, each one must be on its own page,
as if it were a book’s complete chapter.

Practical Learning: Creating Topic Sections


1.

6.1.4 Topics Titles


Since a topic represents a complete item of the help file, when actually creating the help
file, you will need to specify a recognizable title for each topic. First, you should start
each topic with a title heading: a word or group of words on top of the first paragraph of
the section.

The title of a topic is created as a footnot using the $ tag. To do this, click on the left
section of the title header. Then on the main menu, click Inser  Footnote… In the
Footnot and Endnote dialog box,click the edit box in the Numbering section, type $ and
click OK.

A topic’s title can be a letter from a to z (in uppercase or lowercase), a word, or group of
words of up to 255 characters. You should type it in one word (although different words
are allowed), no space (although spaces are allowed), and in uppercase (although it does
not matter). An example would be INTRO

Practical Learning: Creating Topics Titles

6.1.5 Creating Topic ID


A Topic ID is a word or group of words used to identify a topic of the help file. A Topic
ID is made of a character, a word or group of words that start with a character and can
consist of up to 255 characters including letters and numbers. Although spaces are
allowed, you should avoid any space on a Topic ID and do not start the identifier with a
number. You must not use the following characters: # = + @ * % !. Additionally, avoid
any fancy symbols; use only letters and numbers.

137 © FunctionX, Inc.


Windows Events Borland C++ Builder

You must create a Topic ID for each topic that will need a link, whether the link will
allow to jump to another part of the help file or it will popup a (local) message. For the
help files created for our application, make a Topic ID in one word that starts with IDH_

6.1.6 Topics Keywords


Keywords serve various purposes. They are the basis for an Index section of the help file.
They also allow users to perform various types of searches. An index keyword could be a
word of interest on a topic although it could also not be included at all in the section. To
create keywords for each topic, make a list of words that could be used during a search
and that would help

Keywords used for indexing are created from the footnote using the A flag. To do this, in
Microsoft Word, click on the left of a topic header. On the main menu, click Insert 
Footnote… In the Footnote and Endnote dialog box, in the edit box of the Numbering
section, type A and press Enter.

Type various or each. This is done using the A footnote.

138 © FunctionX, Inc.


Windows Events Borland C++ Builder

Chapter 7: Dialog Boxes

139 © FunctionX, Inc.


Windows Events Borland C++ Builder

7.1 C++ Dialog Boxes

A dialog box is a window container used as a platform for user interaction with the
computer. By itself, a dialog box means nothing; the controls it hosts accomplish the role
of dialog between the user and the machine.

A priori, a dialog has the following characteristics:


1. It is equipped with the Windows 95 Close button . As the only system button, this
button allows the user to dismiss the dialog and ignore whatever the user would have
done on the dialog. Usually, this button would be configured as if the user had
clicked Cancel or pressed Esc.
2. It cannot be minimized, maximized, or restored. A dialog box does not have any
other system button but Close.
3. It is modal. The user is usually not allowed to continue any other operation until he
or she has finished dealing with the dialog box.
4. It provides a way for the user to close or dismiss the dialog. Most dialog boxes have
the OK and the Cancel button, although this depends on the application developer.
When the dialog has the OK and the Cancel button, the OK button is configured to
behave as if the user had pressed Enter. In that case, whatever the user had done
would be acknowledged and transferred to the subsequent dialog, window, or
application. Pressing Esc applies the same behavior as if the user had clicked Cancel.

7.1.1 Creating a Dialog Box


To create a dialog box, the only thing you have to do is set the BorderStyle of a form to
bsDialog. An extra feature that Bcb provides is the ModalResult property. This property
autonomously and without any code can control the behavior of the closing dialog
depending on the button that was clicked.

If the user is supposed to change some settings on the dialog that would affect the
subsequent application, provide at least two buttons: OK and Cancel. Configure the OK
button so that after the user has used the dialog, whatever change was made would be
validated. Therefore, set the Default property of the OK button to true so that after the
user has made changes, he or she can press Enter. Configure the Cancel button so that if
the user changes his or her mind after making changes, he or she can click Cancel or
press Esc, dismissing the dialog and discharging any change.

As you know already, when Bcb starts, it opens with a starting form. To make that form a
dialog box, simply change its BorderStyle property to bsDialog. All you have to do is
configure the dialog to behave as you see fit.

To make your development experience even faster, C++ Builder ships with a lot of dialog
boxes ready for use. These dialog boxes are equipped with an OK and a Cancel butons.
These dialogs are available on the Dialogs property page of the New Items dialog box.

Practical Learning: Creating a Dialog Box


1. Start Borland C++ Builder if you did not yet. On the main menu, click File 
New…

140 © FunctionX, Inc.


Windows Events Borland C++ Builder

2. On the New Itrems dialog box, click the Dialogs tab. Click Standard Dialog
(Vertical):

3. Click OK.
4. Press F12 to access the Code Editor. Click Unit1.cpp to display its code.
5. Once Unit1.cpp is displaying, right-click in the Code Editor and click Close
Page. You will be asked whether you want to Save the changes of the Unit1
unit:

6. Click No.
7. To test the dialog box, on the main menu, click Run  Run.
8. After viewing the form, close it.

7.2 Windows Common Dialogs

Borland C++ Builder ships with a set of ready-made objects referred to as Windows
Common Dialogs. Indeed, these dialogs are part of the operating system and are equipped
with all the necessary operations pertinent to their functionality.

141 © FunctionX, Inc.


Windows Events Borland C++ Builder

To use a standard Windows dialog, from the Dialogs tab of the Component Palette, click
the desired dialog’s button and click anywhere on the form. The position of the control on
the form has no importance because it is only a representative; it will not appear when the
form is running. Once the desired dialog’s icon is on the form, place a button that will be
used to call the dialog. A dialog is called using the DialogName->Execute() method. You
can find out what button the user clicked when closing the dialog, and act accordingly.

To add a Windows common dialog to your application, you will select it from the
Dialogs page of the Component Palette.

7.2.1 The Color Dialog Box

The Color dialog box is used by various controls to change their background color. It can
also be used to control any type of color as part of the application. When the dialog
displays, at any time the user can get a larger preview of the selected color on the
Color|Solid box. The user can change the color in four different areas. The top left section
displays a list of 48 predefined colors. If the desired color is not in that section, the user
can click and drag the mouse in the colored palette. The user can also drag the right bar
that displays a range based on the color of the palette; the user can scroll up and down by
dragging the arrow. For more precision, the user can type the Red, Green and Blue value;
each uses a integral value that ranges from 1 to 255.

To add a Color dialog box to your application, click the ColorDialog button on the
Component Palette and click anywhere on the form.

The most important and most obvious property of the Color dialog is the selected color
once the user has made a choice. When the user opens the dialog you can set the default
color on the Object Inspector using the Color property. You can also set this color
programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::FormCreate(TObject *Sender)
{
ColorDialog1->Color = clRed;
}
//---------------------------------------------------------------------------

142 © FunctionX, Inc.


Windows Events Borland C++ Builder

When the user has finished using the Color dialog box and clicked OK, you can find out
what color was selected by using the TColorDialog::Color property.

The regula size of the dialog is half of the picture above. By default, this normal size is
also the one the user sees when the dialog opens. You can control the regular or full size
of the dialog using the Options property. At design time, to manipulate the options, on the
Object Inspector, click the + on the Options field to expand. Since the options are
controlled by the TColorDialogOption set, you can specify as many as you want:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::FormCreate(TObject *Sender)
{
ColorDialog1->Color = clRed;
ColorDialog1->Options << TColorDialogOption() << cdFullOpen << cdAnyColor;
}
//---------------------------------------------------------------------------

If you want to supply the user with a set of colors of your choice, you can do this using a
list of custome colors. To create this list, click the CustomColor field to reveal its ellipsis
button, then click that button to display the String List Editor dialog box. You can specify
up to 16 colors. The colors are named ColorA, ColorB, ColorC, and so on up to ColorP.
To create the list, type the ordinal name and assign it an integer number. Here is an
example:

The most important method of the Color dialog is the Execute() function. This method
occurs when the user clicks OK or presses Enter after selecting a color. You can use it to
get the selected color and use it as you see fit. The following example displays a Color
dialog when the user clicks a button on the form. When the user clicks OK on the Color
dialog, the selected color is applied to the background of the form:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ColorDialog1->Execute();
Color = ColorDialog1->Color;
}
//---------------------------------------------------------------------------

143 © FunctionX, Inc.


Windows Events Borland C++ Builder

The most efficient approach is to make sure that the dialog was opened and closed
successfully, then retrieve the color if the user clicked OK to close the dialog. This is
done through a conditional call, as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(ColorDialog1->Execute())
Color = ColorDialog1->Color;
}
//---------------------------------------------------------------------------

The TColorDialog constructor is used to dynamically create an instance of the


TColorDialog control at runtime in case you cannot design it. To do this, declare a
TColorDialog class in an event or function as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCreateColorClick(TObject *Sender)
{
TColorDialog* Dlg = new TColorDialog(this);
}
//---------------------------------------------------------------------------

After creating it, you can use it as a regular control. For example, you can change the
color of an Edit control on the form as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCreateColorClick(TObject *Sender)
{
TColorDialog* Dlg = new TColorDialog(this);

if(Dlg->Execute())
edtFullName->Color = Dlg->Color;
}
//---------------------------------------------------------------------------

To make a dynamically created Color dialog available to more than one event or
function, declare an instance of the TColorDialog class in the private or public sections of
the header file of a form or the unit that would use it:

//---------------------------------------------------------------------------
#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
TColorDialog *ChangeIt;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

144 © FunctionX, Inc.


Windows Events Borland C++ Builder

extern PACKAGE TForm1 *Form1;


//---------------------------------------------------------------------------
#endif

In the constructor, use the new operator to specify the control that would own the
dynamic object:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ChangeIt = new TColorDialog(Form1);
}
//---------------------------------------------------------------------------

When creating the object, you can specify the desired properties as you wish. Once the
object has been created, you can call it wherever you want in the object in which it is
created:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ChangeIt = new TColorDialog(Form1);
ChangeIt->Options << TColorDialogOption() << cdFullOpen << cdSolidColor;
ChangeIt->CustomColors->Add("ColorA=999662");
ChangeIt->CustomColors->Add("ColorE=668684");
ChangeIt->CustomColors->Add("ColorF=4457945");
ChangeIt->CustomColors->Add("ColorC=582558");
ChangeIt->CustomColors->Add("ColorB=2551286");
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Panel1Click(TObject *Sender)


{
if(ChangeIt->Execute())
Panel1->Color = ChangeIt->Color;
}
//---------------------------------------------------------------------------

7.3 Accessory Dialogs

The Visual Component Library ships with other dialog boxes useful for tasks that would
require a lot of work, such as letting the user browse the hard drive.

7.3.1 The Folder Browser

145 © FunctionX, Inc.


Windows Events Borland C++ Builder

The VCL library provides a convenient dialog box used to browser one of the drives of
the user’s computer to locate a folder. This dialog is invoqued using the SelectDirectory()
function. Its syntax is:

bool __fastcall SelectDirectory(const AnsiString Caption, const WideString Root,


AnsiString &Directory);

This function takes three arguments and returns two values. The Caption argument
displays under the title bar but above the tree view of the dialog box. The Root is a string
that represents the name of the root drive. The Directory string is the default path folder.
This function returns a Boolean value upon exiting. Here is an example of using the
SelectDiretory() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDirectoryClick(TObject *Sender)
{
AnsiString Caption = "Select a Directory";
const WideString Root = "C:\"";
AnsiString Directory = "C:\\Program Files";
SelectDirectory(Caption, Root, Directory);
}
//---------------------------------------------------------------------------

When the dialog box opens, it displays two buttons OK and Cancel. The OK button is
disabled because no directory would have been selected. To use the Browse For Folder
dialog box, the user clicks the + signs to expand a folder, and the – (if any) sign to
collapse a floder. Once the user locates the desired folder, he or she must click it to
highlight it, which enables the OK button.

After using the Browse For Folder dialog box, if the user clicks Cancel or presses Esc,
whatever change was made would be dismissed and the function would return false. If
the user clicks OK or presses Enter, the function would return the full path of the folder
the user has selected. This path is the returned Directory argument. You can use a
conditional statement to find out what button the user would have clicked then use the
returned Directory string as you see fit. Here is an example:

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

146 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall TForm1::btnDirectoryClick(TObject *Sender)


{
AnsiString Caption = "Select a Directory";
const WideString Root = "C:\"";
AnsiString Directory = "C:\\Program Files";

if(SelectDirectory(Caption, Root, Directory) == True)


edtInstallation->Text = Directory;
}
//---------------------------------------------------------------------------

7.3.2 The Directory Selector

An overloaded version of the SelectDirectory() function allows displaying a different


type of folder selector. The syntax of this function is:

bool __fastcall SelectDirectory(AnsiString &Directory, TSelectDirOpts Options, int


HelpCtx);

Lik the other SelectDirectory() function, this version returns two values: a Boolean and a
string. Once again, the Directory argument is required, although it is used as a sample
that the user can change. Since the root drive is not a directory, you cannot set its value as
“C:”, “C:\””, “A:”, “A:\”” or the likes. The Directory must be a valid path of an existing
folder. When the dialog displays, the string of the Directory is selected, which enables the
OK and the Cancel buttons. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
AnsiString Directory = "F:\\Corel\\WordPerfect Office 2002\\Graphics";
SelectDirectory(Directory,
TSelectDirOpts(),
0);
}
//---------------------------------------------------------------------------

On the computer I am using, the function produced:

147 © FunctionX, Inc.


Windows Events Borland C++ Builder

Notice the absence of a Directory Name edit box.

Once again, the user can change the displaying folder. This time, to proceed, the user
would double-click a folder in the Directories tree view to expand the folder. Once the
user has located the desired folder, he must click it to highlight it. After selecting a folder,
the user would click OK In this case the function returns true and the path of the folder.
Two options not available on the first CreateDirectory() version can be used here. If you
want to display the Directory Name edit box, set the TSelectDirOpts set to at least:

TSelectDirOpts() << sdAllowCreate

If the user wants to use a directory that does not exist, if the directory can be created, add
the sdPerformCreate option to the set as follows:

TSelectDirOpts() << sdAllowCreate << sdPerformCreate;

If the user types a directory that does not exist, it would be created transparently. If you
want the user to confirm that she wants to create a new folder, add the sdPrompt option to
the set. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
AnsiString Directory = "C:\\Program Files\\Borland\\Delphi4\\Projects";
SelectDirectory(Directory,
TSelectDirOpts() << sdAllowCreate << sdPerformCreate << sdPrompt,
0);
}
//---------------------------------------------------------------------------
The last option allows you to specify a help file to provide context sensitive help to the
user. To use it, associate an integer that is mapped to the appropriate identifier in the help
file. Once you set this argument and the application has a help file, a Help button would
appear on the dialog box. Here is an example of using the help argument:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
AnsiString Directory = "C:\\Program Files\\Borland\\Delphi4\\Projects";
const int HelpMe = 12;

SelectDirectory(Directory,

148 © FunctionX, Inc.


Windows Events Borland C++ Builder

TSelectDirOpts() << sdAllowCreate << sdPerformCreate << sdPrompt,


HelpMe);
}
//---------------------------------------------------------------------------

7.4 Message Boxes

A message box is a relatively small dialog box used to display a message and provide one
or more buttons. A message box is used to provide information to the user or to request a
decision (from the user). By clicking one of the buttons, the user makes a decision and
the program continues.

Message boxes are created from built-in functions from Borland and the Win32 library;
these functions shipped with the compiler.

Practical Learning: Preparing the Message Boxes Application


1. Create a new project with its starting form.
2. Change its caption to Message Boxes Configurations
3. From the Standard tab of the Component Palette, click the Edit control and click on
the form.
4. Change the name of the edit control to edtMessage and delete the content of its
Text field.

7.4.1 The ShowMessage Function

The ShowMessage() function provides the most fundamental of Borland’s applications.


This function takes one string argument and does not return any value. It is used to
display a message to the user who acknowledges it by clicking the OK button. The syntax
of the ShowMessage() function is

void __fastcall ShowMessage(const AnsiString Message);

A message box created with the ShowMessage() function uses the name of the project as
its caption. The message to display is a string that can be provided by the developer. Here
is an example:

void __fastcall TForm1::btnShowMsgClick(TObject *Sender)


{
ShowMessage("Welcome to the Sellers Bank.");
}

149 © FunctionX, Inc.


Windows Events Borland C++ Builder

The string can also derive from another control such as the content of an edit box, a
memo, or any text control. Here is an example:

void __fastcall TForm1::btnMsgFromEditClick(TObject *Sender)


{
ShowMessage(edtMessage->Text);
}

The string can also be a combination of other strings:

void __fastcall TForm1::Button1Click(TObject *Sender)


{
ShowMessage("The name " + AnsiString("\"")
+ edtMessage->Text + AnsiString("\"")
+ " is not in our records.");
}

Practical Learning: Using the ShowMessage() Function


1. From the Standard tab of the Component Palette, click Button and click on the
form.
2. Change the caption of the new button to Show &Msg and change its name to
btnShowMsg

3. Double-click the Show Msg button to access its Click event.


4. Press Tab and implement it as follows:

void __fastcall TForm1::btnShowMsgClick(TObject *Sender)


{
ShowMessage("Please fill out your Time Sheet before leaving.");
}
5. To test the program, press F9
6. Click the Show Msg button:

7. Click OK and close the form.


8. To save the project, on the main menu, click File  Save All
9. Locate the folder where the exercises are installed.
10. Click the Create New folder button. Type Message Boxes and press Enter
twice to display the new folder in the Save In combo box.
11. Click Save to save the Unit.
12. Type Messages to replace the name of the project and press Enter.

150 © FunctionX, Inc.


Windows Events Borland C++ Builder

13. To display the message on more than one line, change the event as follows:

void __fastcall TForm1::btnShowMsgClick(TObject *Sender)


{
ShowMessage("Please fill out your Time Sheet before leaving.\n"
"Make sure you sign and send it to Human Resources");
}
14. Test the form to verify the new caption of the message box:

15. And return to Bcb

7.4.2 The MessageBox Function

The MessageBox() function is derived from Win32. Its syntax is:

int __fastcall MessageBox(const char * Text, const char * Caption, int Flags);

Caption

Message

Flags

The MessageBox() function takes three arguments. The first argument, Message, is a
null-terminated string representing the message that the user would read. The Text string
could be a static sentence. It could be constructed from another control. Or it could be a
combination of different strings appended using C/C++ string functions and operations.

You can create a simple message box similar to one implemented using the
ShowMessage() function to display a simple message with an OK button. In this case,
you would provide only the Message argument. Set the other two arguments as NULL.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Application->MessageBox(
"This operation can only be performed by an administrator.",
NULL, NULL);

151 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

The second argument, also a string, is the caption that would display on the title bar of
the dialog box. You can also set it when creating the message box or you can build it
from what would be available at runtime. If you do not have a caption, you can set the
value of this argument as NULL. In that case the title bar would display Error. Therefore,
to create a less boring message box, provide the Caption argument. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Application->MessageBox("Make sure the music is playing.",
"CD PLayer Instructions", NULL);
}
//---------------------------------------------------------------------------

The third argument specifies the flags that would display on the dialog box: one or more
buttons and an optional picture. You can create a simple message box with OK as the
only button. In that case, set the third argument as MB_OK. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Application->MessageBox("Make sure the music is playing.",
"CD PLayer Instructions", MB_OK);
}
//---------------------------------------------------------------------------

To display more than one button, use a constant integer that represents a group of the
available buttons. Here are the constants and their buttons:

Constant Integer Buttons


MB_OK

MB_OKCANCEL

MB_ABORTRETRYIGNORE

MB_YESNOCANCEL

MB_YESNO

MB_RETRYCANCEL

MB_CANCELTRYCONTINUE

MB_HELP

For example, to create a message box that displays the Yes and No buttons, you could
write:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

152 © FunctionX, Inc.


Windows Events Borland C++ Builder

Application->MessageBox("Do you hear any music now or any sound at all?",


"CD Player Instructions", MB_YESNO);
}
//---------------------------------------------------------------------------

If you provide the MB_HELP as the only button, the message box would display with an
OK and a Help buttons.

The enhance your dialog and accentuate your message, you can display an icon using one
of the Win32 defined integer constants. Although you can use any icon with any button,
you should be tactful and make sure that the appearance is in accordance with the
message. The values and icons are:

Value Icon Suited when


MB_ICONEXCLAMATION, Warning the user of an action performed on
MB_ICONWARNING the application.
MB_ICONINFORMATION, Informing the user of a non-critical
MB_ICONASTERISK situation.
MB_ICONQUESTION Asking a question that expects a Yes or No,
or a Yes, No, or Cancel answer
MB_ICONSTOP, A critical situation or error has occurred.
MB_ICONERROR, This icon is appropriate when informing the
MB_ICONHAND user of a termination or deniability of an
action

The icons are used in conjunction with the buttons constant. To combine these two flags,
use the bitwise OR operator “|”. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Application->MessageBox("Do you hear any music now or any sound at all?",
"CD Player Instructions", MB_YESNOCANCEL | MB_ICONQUESTION);
}
//---------------------------------------------------------------------------

When a message box is configured to display more than one button, the operating system
is set to decide which button is the default. The default button has a thick border that sets
it apart from the other button(s). If the user presses Enter, the message box would behave
as if the user had clicked the default button. Fortunately, if the message box has more
than one button, you can decide what button would be the default. To specify the default
button, use one of the following constants:

If the message box has more than one


Value button, the default button would be
MB_DEFBUTTON1 The first button
MB_DEFBUTTON2 The second button
MB_DEFBUTTON3 The third button
MB_DEFBUTTON4 The fourth button

To specify the default button, use the bitwise OR operator to combine the constant
integer of the desired default button with the buttons constant and the icon. Here is an
example:

153 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Application->MessageBox("Do you hear any music now or any sound at all?",
"CD Player Instructions",
MB_YESNOCANCEL | MB_ICONQUESTION | MB_DEFBUTTON2);
}
//---------------------------------------------------------------------------

Since the combination of these buttons is using the OR bitwise operator to construct the
Flags argument, it does not make a difference which constant appears first:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Application->MessageBox("Do you hear any music now or any sound at all?",
"CD Player Instructions",
MB_YESNOCANCEL | MB_DEFBUTTON3 | MB_ICONQUESTION);
}
//---------------------------------------------------------------------------

After reading the message displaying on the dialog box, the user would click one of the
buttons and the dialog would be closed. Each one of the buttons has a constant integer
number that is assigned and recognized by the compiler. You can use this number to find
out what button the user had clicked. This means the MessageBox() function returns an
integer value as in the following table:

The MessageBox() returns If the user clicks


IDOK OK
IDCANCEL Cancel or presses Esc
IDABORT Abort
IDRETRY Retry
IDIGNORE Ignore
IDNO No
IDYES Yes
IDCONTINUE Continue
IDTRYAGAIN Try Again

Therefore, you can use one of these integers to act depending on the button clicked:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (Application->MessageBox(
"Do you hear any music now or any sound at all?",
"CD Player Instructions",
MB_YESNOCANCEL | MB_ICONQUESTION) == IDNO)
Panel1->Caption = "We will stop these tests now. Let the machine rest!";
}
//---------------------------------------------------------------------------

Practical Learning: Using the MessageBox() function


1. On the Component Palette, click Button and click on the form.

154 © FunctionX, Inc.


Windows Events Borland C++ Builder

2. Change the Caption of the new button to Simple &1 and its name to
btnSimpleMsg

3. Double-click the Simple 1 button to access its click event.


4. Press Tab and type:

Application->MessageBox("This operation can only be performed by an


administrator.", NULL, NULL);
5. To test the form, press F9.
6. Click the Simple 1 button to view the message box. Notice that the message box
has an OK button and a caption of Error:

7. Click OK and close the form.


8. Press F12 to display the form
9. Add another button to the form.
10. Change its caption to Simple &2 and its name to btnSimple2
11. Double-click the Simple 2 button.
12. Press Tab and type:

Application->MessageBox("Make sure the music is playing.",


"CD PLayer Instructions", MB_OK);
13. Test the form and return to Bcb
14. Add another button to the form.
15. Change its caption to &Question and its name to btnQuestion
16. Double-click the Question button.
17. Press Tab and type:

Application->MessageBox("Do you hear any music now or any sound at all?",


"CD Player Instructions",
MB_YESNOCANCEL | MB_ICONQUESTION);
18. Test the form:

155 © FunctionX, Inc.


Windows Events Borland C++ Builder

19. Return to Bcb


20. Add another button to the form
21. Change its caption to &Default and its name to btnDefault
22. Double-click the Default button and implement its event as follows:

void __fastcall TForm1::btnDefaultClick(TObject *Sender)


{
Application->MessageBox("The file you are trying to copy is being "
"used by someone else.\n"
"Would you like to try later? If you click\n"
"Yes: You will be reminded when the file is ready.\n"
"No: Copy the file anyway. You will get only the source file\n"
"Cancel: Cancel the operation.",
"Copying Files",
MB_YESNOCANCEL | MB_ICONQUESTION | MB_DEFBUTTON2);
}
23. Test the form:

24. Return to Bcb

7.4.3 The MessageDlg Function

The MessageDlg() function is Borland’s enhanced message box and it provides a good
alternative to the Win32’s MessageBox() function.

The syntax of the MessageDlg() function is:

int __fastcall MessageDlg(const AnsiString Message, TMsgDlgType IconType,


TMsgDlgButtons Buttons, int HelpContext);

The first argument, Message, is the message addressed to the user. It can be a simple
static sentence, a paragraph or any combination of strings.

156 © FunctionX, Inc.


Windows Events Borland C++ Builder

The IconType is an icon used to enhance the dialog box. The icon is set using a constant
integer as follows:

Value Icon
mtWarning

mtError

mtInformation

mtConfirmation
mtCustom None

The Buttons argument is used to specify the type(s) of button(s) to display on the dialog
box. The buttons are defined using the TMsgDlgButtons set as follows:

Value Button Value Button


mbYes mbRetry
mbNo mbIgnore
mbOK mbAll
mbCancel mbNoToAll
mbAbort mbYesToAll
mbHelp

The last argument is used if there is a help file available, in which case you would specify
the particular index related to this message box. This message box uses the name of the
project as its caption.

Practical Learning: Using the MessageDlg Function


1. Add a button to the form.
2. Change its caption to Msg Di&alog 1 and its name to btnMsgDialog1
3. Double-click the Msg Dlg 1 button.
4. Press Tab and type:

MessageDlg("All songs on the CD have been copied. Now it will be ejected.",


mtInformation, TMsgDlgButtons() << mbOK, 0);
5. Test the form
6. Add a button to the form.
7. Change its caption to Msg Dia&log 2 and its name to btnMsgDlg2
8. Double-click the Msg Dialog2 button and implement it as follows:

void __fastcall TForm1::btnMsgDlg2Click(TObject *Sender)


{
MessageDlg("The file " + AnsiString("\"") + edtMessage->Text

157 © FunctionX, Inc.


Windows Events Borland C++ Builder

+ AnsiString("\"") + " that you are trying to upload "


"already exists on the server.\n"
"If you continue, you will replace the recent versions "
"of the files on the server.\n"
"Would you like to upload anyway?",
mtConfirmation,
TMsgDlgButtons() << mbNoToAll << mbNo
<< mbYes << mbYesToAll, 0);
}
9. To test the form, press F9.
10. In the Message edit box, type canonderby.asp
11. Click the Msg Dialog 2 button:

12. Return to Bcb

7.4.4 The MessageDlgPos Function


The MessageDlgPos() function provides extra possibilities to the programmer. It behaves
exactly like the MessageDlg() function. To create a message box based on this function,
use the syntax:

int __fastcall MessageDlgPos(const AnsiString Msg, TMsgDlgType DlgType,


TMsgDlgButtons Buttons, int HelpCtx, int X, int Y);

Besides the same arguments as the MessageDlg() function, The MessageDlgPos()


function allows you to specify the coordinates used to display the dialog box. The X
argument is an integer value that specifies the distance between the left border of the
screen and the left border of the dialog box. The Y argument represents the height from
the top border of the screen to the top border of the dialog box. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MessageDlgPos("The right side of the main form displays "
"a \"Read-Only\" list of currently registered students.\n"
"This only includes students with good records.",
mtInformation,
TMsgDlgButtons() << mbRetry << mbIgnore,
0, 20, 120);
}
//---------------------------------------------------------------------------

158 © FunctionX, Inc.


Windows Events Borland C++ Builder

7.4.5 The CreateMessageDialog


If you have a prototype message box that you are planning to use over and over again in
your application, you create it at once, implement it, then use in different locations in
your application. Such a common message box is created using the
CreateMessageDialog() function. The CreateMessageDialog() function does not allow
you to create a new message box. It provides a technique of creating a central dialog box
that combines the arguments and flags of the other message boxes. The syntax of the
CreateMessageDialog() function is:

Forms::TForm* __fastcall CreateMessageDialog(const AnsiString Msg,


TMsgDlgType IconType, TMsgDlgButtons ButtonType);

This function takes three arguments similar to those of the MessageDlg() function. You
construct it by specifying the string message, the icon type, and the button type. To create
this dialog box, assign its construction to a dynamic form. To do this, you could create a
local form in a function or event, but since a local dynamic control in accessible only in
the event or function in which it is created, this would deceive the purpose of using the
CreateMessageDialog() function. Therefore, declare an instance of the Tform class in
the private or public sections of the unit or form that would use the message box:

//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TPanel *Panel1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall Panel1Click(TObject *Sender);
private: // User declarations
TForm* Mine;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Next, use the new operator to specify the owner of the form:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Mine = new TForm(this);

159 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

To create the custom message box, assign the return value of the
CreateMessageDialog() function by creating it. The message box can be as simple as a
single string, an icon, and a button:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Mine = new TForm(this);
Mine = CreateMessageDialog("Custom Dialog Box",
mtWarning, TMsgDlgButtons() << mbYes);
}
//---------------------------------------------------------------------------

The message could also comport any of the available icons combined with any common
buttons:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Mine = new TForm(this);
Mine = CreateMessageDialog("Is this the best song or what?",
mtInformation,
TMsgDlgButtons() << mbYes << mbAbort << mbCancel << mbNo);
}
//---------------------------------------------------------------------------

With the message box created, you can call it from any section or control that needs it in
your application:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Mine = new TForm(this);
Mine = CreateMessageDialog("Is this the best song or what?",
mtInformation,
TMsgDlgButtons() << mbYes << mbAbort << mbCancel << mbNo);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Mine->ShowModal();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)

160 © FunctionX, Inc.


Windows Events Borland C++ Builder

{
Mine->ShowModal();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
Mine->ShowModal();
}
//---------------------------------------------------------------------------

7.4.6 The Input Dialog Box


The InputBox() allows you to display a message box that would request a piece of
information from the user. The message box is equipped with an edit box and two
buttons. The edit box accepts a string from the user. The user can type anything but it is
up to you to use the content of that edit box as your program needs it. When the user
clicks OK, the Input Box returns the content of its edit box. If the user clicks Cancel or
presses Esc, the content of its edit box is dismissed.

The syntax of the InputBox() function is

AnsiString __fastcall InputBox(const AnsiString Caption, const AnsiString Prompt,


const AnsiString Default);

The Caption argument specifies the string that would display on the title bar of the dialog
box. The Prompt is a sentence that would display to the user as to what to type in the
provided edit box. The Default argument is a suggested value you can display in the edit
box to guide the user as the type of value expected. If you do not want to specify a default
value, you can set its string value to empty. Here is example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnInputClick(TObject *Sender)
{
InputBox("Temperature Conversion",
“Type the temperature in Celsius:", "");
}
//---------------------------------------------------------------------------

Although the Default argument is a string, you can initialize it to any value the
AnsiString class can interpret using one of its constructors. This means the default value
can be a character, a floating number or an integer:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnInputClick(TObject *Sender)
{
InputBox("Temperature Conversion",

161 © FunctionX, Inc.


Windows Events Borland C++ Builder

“Type the temperature in Celsius:", 102);


}
//---------------------------------------------------------------------------

If you specify the Default argument and the user clicks OK without changing the content
of the edit box, the compiler would consider the default value as valid.

After using the dialog box, the user would click OK, press Enter, click Cancel, or press
Esc. If the user clicks OK or presses Enter, the function returns the value that the user
would have typed in the edit box. This allows you to write a conditional statement that
would consider the new value returned by clicking OK on the InputBox dialog:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnInputClick(TObject *Sender)
{
Edit1->Text = InputBox("Distance and Measurement",
"Enter the distance in kilometer:", 0.00);
}
//---------------------------------------------------------------------------

If the user clicks Cancel or presses Esc, whatever the edit box was displaying would be
ignored. But the function would still return the default value.

If the returned value is intended for mathematical, date, or time calculations, you should
convert it accordingly.

Practical Learning: Using the InputBox Dialog


1. Add a button to the form.
2. Change its caption to Input &Box and its name to btnInputBox
3. Double-click the Input Box button.
4. Press Enter and type

InputBox("Student Registration",
"Type the Student's Gender", "");
5. Press F9 to test the form. Click the Input Box button. Notice that the content of
its edit box is empty.
6. Close the Input Box and the form.
7. To provide a default value to the user, change the content of the previous
function as follows:

InputBox("Student Registration",
"Type the Student's Gender", "Male");
8. Test the form and click the Input Box button
9. To use the content of another control, such as an edit box, as the default value,
change the above code as follows:

InputBox("Music Collection",
"Enter the category of music to register",
edtMessage->Text);
10. To test the form, press F9.

162 © FunctionX, Inc.


Windows Events Borland C++ Builder

11. Type Salsa in the Message edit box.


12. Click the Input Box button and notice that its default value is what you typed in
the edit box:

13. Type Irish Folks and click OK


14. Close the form.
15. To use and apply the result of an Input Box to another control, for example to
paste it into an edit box, change the above code as follows:

edtMessage->Text = InputBox("Employees Records",


"Employee's Department", "Human Resources");
16. To test the form, press F9
17. Click the Input Box button
18. Type Accounting and press Enter.
19. Notice that Accounting displays in the Message edit box.

7.4.7 The InputQuery Request


Like the InputBox() function, the InputQuery() function is used to display a prompting
dialog box to the user. The syntax of this function is:

bool __fastcall InputQuery(const AnsiString Caption, const AnsiString Prompt,


AnsiString &Value);

This takes three strings. The Caption argument is a string that displays on the title bar of
the dialog box. The Prompt argument is the sentence that indicates to the user what to
type in the edit box. Like the InputBox() function, the Value argument provides a default
and sample value to the user. Like the InputBox() function, the user can type a new value.
Here is an example of using the InputQuery() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnQueryClick(TObject *Sender)
{
InputQuery("Exiting Application",
" Are you sure you want to exist (y=Yes/n=No)?", 'n');

163 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

Unlike the InputBox() function that returns a string, the InputQuery() function returns
two values. By its declaration, this function returns a Boolean value of true or false. If the
user clicks OK or presses Enter after using the dialog box, the function returns true. If the
user presses Esc or clicks Cancel, the function returns false.

If the user clicks OK (or presses Enter), like the InputBox() function, whether the user
had changed the value of the edit box or not, the content of the edit box, provided as the
Value argument, would be returned. Because Value is passed by reference, the function
can return two values. Unlike the InputBox() function, if the user clicks Cancel (or
presses Esc) after dealing with the dialog box, the value of the Value argument would be
ignore.

You can validate the returned value of Value by writing a conditional statement that
examines whether the user had clicked OK or Cancel. In the following example, when the
user clicks the Input button, the compiler finds out if the user had clicked OK; in which
case it would display the returned value of the Value argument in an Edit control of the
form:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnQueryClick(TObject *Sender)
{
AnsiString Answer = 'Y';
if(InputQuery("Exiting Application",
"Are you sure you want to exist (Y=Yes/Y=No)?", Answer) == True)
edtExiting->Text = Answer;
}
//---------------------------------------------------------------------------

164 © FunctionX, Inc.


Windows Events Borland C++ Builder

Chapter 8:
The Math Libraries

165 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.1 The Math Libraries


The controls on your applications will receive strings of various kinds either supplied by
the user or gotten from other controls. Some of the values on these controls will be
involved in mathematical operations. The C++ language provides a reach set of functions
to help you quickly perform different types of caculations. The functions range from
arithmetic to geometry, from trigonometry to algebra, etc. To compensate for the areas
where C++ does not expand, instead of writing your own functions, Borland C++ Builder
ships with various functions that, besides geometry and algebra, deal with finance,
statistics, random number generation, etc.

By default, the content of a text control, such as an edit box, is a string, which is an array
of characters. If you want the value or content of such a control to participate in a
mathematical operation, you must first convert such a value to a valid data type and
proceed from there.

8.1.1 Converting a String to an Integer: ToInt()


If you want to use the content of a text control to an integer, you can use the
AnsiString::ToInt() method. Its syntax is:

int __fastcall ToInt() const;

This function converts an AnsiString variable to a valid integer. In the following


example, the contents of two edit boxes are converted to integers and a subtraction is
performed;

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Number1 = Edit1->Text.ToInt();
int Number2 = Edit2->Text.ToInt();
int Subtract = Number1 - Number2;

Edit3->Text = Subtract;
}
//---------------------------------------------------------------------------

If the control whose string needs to be converted is displaying an invalid integer, the
program would crash by throwing an error. The AnsiString provides a viable alternative.
The AnsiString::ToIntDef() allows you to supply a default value if the conversion fails.
Here is an example that uses it:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Value1 = Edit1->Text.ToIntDef(0);
int Value2 = Edit2->Text.ToIntDef(1);
int Remainder = Value1 % Value2;
Edit3->Text = Remainder;
}
//---------------------------------------------------------------------------

166 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.1.2 Converting a String to an Integer: StrToInt()


Another function used to convert a string is the StrToInt() function. Its syntax is:

int __fastcall StrToInt(const AnsiString S);

This function takes as an argument, the string that you are trying to convert. In the
following example, the strings of two edit boxes are converted to integers and an addition
is performed on their values:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Number1 = StrToInt(Edit1->Text);
int Number2 = StrToInt(Edit2->Text);
int Addition = Number1 + Number2;
Edit3->Text = Addition;
}
//---------------------------------------------------------------------------

8.1.3 Converting an Integer to String


To convert an integer to an AnsiString, you can use the IntToStr() function. Its syntax is

AnsiString __fastcall IntToStr(int Value);


or
AnsiString __fastcall IntToStr(__int64 Value);

This function takes an integer as the argument and returns a string.

8.1.4 Converting a String to a Float-Point Number


To convert the content of a control to floating number, use the AnsiString::ToDouble()
method. Its syntax is:

double __fastcall ToDouble() const;

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double Value1 = Edit1->Text.ToDouble();
double Value2 = Edit2->Text.ToDouble();
double Value3 = Value1 + Value2;
Edit3->Text = Value3;
}
//---------------------------------------------------------------------------

Another function used to convert a string to a floating-point value is the StrToFloat()


function whose syntax is:

Extended __fastcall StrToFloat(const AnsiString S);

167 © FunctionX, Inc.


Windows Events Borland C++ Builder

This function takes one argument which is the string to convert. The function returns a
long double-precision value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double Value1 = StrToFloat(Edit1->Text);
double Value2 = StrToFloat(Edit2->Text);
double Value3 = Value1 + Value2;
Edit3->Text = Value3;
}
//---------------------------------------------------------------------------

8.1.5 Formatting a Float to Display Decimals


The AnsiString class is equipped with a method used to format a floating-point number
and specify the number of decimal places. Actually, the AnsiString::sprintf() function
imitates the C string system of displaying strings, integers, and floating variables. In
mathematical operations, you can use it to control how to display a decimal number. The
syntax of the method is:

AnsiString& __cdecl sprintf(const char* format, ...);

Following the C system of passing arguments, this function can at least display a string.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Edit2->Text = Edit2->Text.sprintf("The best movie of the year");
}
//---------------------------------------------------------------------------

On the other hand, you can use this function to format a floating-point number. In the
following example, the values of the dimensions of a sphere are calculated and display in
appropriate edit boxes:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
double Radius, Diameter, Circumference, Area, Volume;

Radius = edtRadius->Text.ToDouble();
Diameter = Radius * 2;
Circumference = Radius * 2 * M_PI;
Area = Radius * Radius * M_PI;
Volume = Radius * Radius * Radius * 4.00 * M_PI / 3;

edtDiameter->Text = Diameter;
edtCircumference->Text = Circumference;
edtArea->Text = Area;
edtVolume->Text = Volume;
}
//---------------------------------------------------------------------------

168 © FunctionX, Inc.


Windows Events Borland C++ Builder

When the same values are configured using the AnsiString::sprintf() method, the
diameter and the circumference can be set to display two decimal values while the area
and the volume display three, as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
double Radius, Diameter, Circumference, Area, Volume;

Radius = edtRadius->Text.ToDouble();
Diameter = Radius * 2;
Circumference = Radius * 2 * M_PI;
Area = Radius * Radius * M_PI;
Volume = Radius * Radius * Radius * 4.00 * M_PI / 3;

edtDiameter->Text = edtDiameter->Text.sprintf("%.2f", Diameter);


edtCircumference->Text = edtCircumference->Text.sprintf("%.2f", Circumference);
edtArea->Text = edtArea->Text.sprintf("%.3f", Area);
edtVolume->Text = edtVolume->Text.sprintf("%.3f", Volume);
}
//---------------------------------------------------------------------------

8.2 Arithmetic Functions

8.2.1 Absolute Values

8.2.1.1 The abs Function


The decimal numeric system counts from minus infinity to infinity. This means that
numbers are usually negative or positive, depending on their position from 0, which is
considered as neutral.

In some operations, the number considered will need to be only positive even if it is
provided in a negative format. The absolute value of a number x is x if the number is
(already) positive. If the number is negative, its absolute value is its positive equivalent.
For example, the absolute value of 12 is 12, while the absolute value of –12 is 12.

169 © FunctionX, Inc.


Windows Events Borland C++ Builder

To get the absolute value of a number, you can use one of the C/C++ abs() functions. Its
syntax is:

int abs(int x);

This function takes an integer as the argument and returns its absolute value equivalent.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAbsoluteClick(TObject *Sender)
{
int Number = edtNumber->Text.ToInt();
edtResult->Text = abs(Number);
}
//---------------------------------------------------------------------------

8.2.1.2 The labs Function


If you want to find the absolute value of a number that is larger than the regular integer,
you can use the labs() function. Its syntax is:

long labs(long int x);

This function takes a long integer as argument and returns its equivalent absolute value:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnLongAbsoluteClick(TObject *Sender)
{
int Longer = StrToInt(edtNumber->Text);
edtResult->Text = labs(Longer);
}
//---------------------------------------------------------------------------

8.2.2 The Ceiling of Numbers


Consider a floating number such as 12.155. As you can see, this number is between
integer 12 and integer 13.

13

12.155

12
On the other hand, consider a number such as –24.06. As this number is negative, it is
between –24 and –25, with –24 being greater.

In arithmetics, the ceiling of a number is the closest integer that is greater or higher than
the number considered. In the first case, the ceiling of 12.155 is 13 because 13 is the
closest interger greater than or equal to 12.155. The ceiling of –24.06 is –24.

8.2.2.1 The ceil() Function


In C++, the function used to obtain the ceiling of a number uses the following syntax:

170 © FunctionX, Inc.


Windows Events Borland C++ Builder

double ceil(double Value);

The function takes one argument, which is the floating number to be evaluated, and the
function returns a double-precision number that is the integer that is greater than or equal
to Value. Here is an example:

//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
double Value1 = 155.55;
double Value2 = -24.06;

cout << "The ceiling of " << Value1 << " is " << ceil(Value1) << endl;
cout << "The ceiling of " << Value2 << " is " << ceil(Value2) << endl;

cout << "\nPress any key to continue...";


getchar();
return 0;
}
//---------------------------------------------------------------------------

This would produce:

The ceiling of -24.06 is -24

Press any key to continue...

8.2.2.2 The Ceil() Function


In C++ Builder, the function used to get the ceiling of a number is:

int __fastcall Ceil(Extended Value);

The Ceil() function takes an argument that represents a long double value. The function
returns the greater or equal integer of Value. To use the Ceil() function, include the
math.hpp header to your program. Here is an example:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{
Extended Value1 = 312.44;
Extended Value2 = -4002.35;

cout << "The ceiling of " << Value1 << " is" << Ceil(Value1) << endl;
cout << "The ceiling of " << Value2 << " is" << Ceil(Value2);

171 © FunctionX, Inc.


Windows Events Borland C++ Builder

cout << "\n\nPress any key to continue...";


getchar();
return 0;
}
//---------------------------------------------------------------------------

This would produce:

The ceiling of 312.44 is 313


The ceiling of -4002.35 is -4002

Press any key to continue...

8.2.3 The floor and the Floor Functions


Consider two floating numbers such as 128.44 and -36.72. The number 128.44 is between
128 and 129 with 128 being the lower. The number –36.72 is between –37 and –36 with
–37 being the lower. The lowest but closest integer value of a number is referred to as its
floor. For example, the floor of 128.44 is 128. The floor of –36.72 is –37.

8.2.3.1 The floor() Function


In C++, to obtain the floor of a number, use the following function:

double floor(double Value);

The floor() function takes the considered value as the argument and returns the integer
that is less than or equal to Value. Here is an example:

double Value1 = 1540.25;


double Value2 = -360.04;

cout << "The floor of " << Value1 << " is " << floor(Value1) << endl;
cout << "The floor of " << Value2 << " is " << floor(Value2) << endl;

This would produce:

The floor of 1540.25 is 1540


The floor of -360.04 is -361

Press any key to continue...

8.2.3.2 The Floor() Function


When using C++ Builder, you can use the Floor() function to find the floor of a number.
The syntax of the function is:

int __fastcall Floor(Extended Value);

The Value argument of the function represents the number that is being considered. The
function returns the integer that is less than or equal to Value. Here is an example:

Extended Value1 = 312.44;


Extended Value2 = -4002.35;

172 © FunctionX, Inc.


Windows Events Borland C++ Builder

cout << "The floor of " << Value1 << " is " << Floor(Value1) << endl;
cout << "The floor of " << Value2 << " is " << Floor(Value2) << endl;

This would produce:

The floor of 312.44 is 312


The floor of -4002.35 is -4003

Press any key to continue...

8.2.4 The frexp(), the frexpl(), and the Frexp() Functions

8.2.4.1 The frexp() and the frexpl() Functions


double frexp(double Number, int *Exp);
long double frexpl(long double Number, int *Exp);

The C++ frexp() and frexpl() functions are used to get the mantissa and the exponent
portions of a floating-point number. Each of these functions takes two arguments. The
Number argument represents the value that will be examined. For the frexp() function,
this value is a double-precision number. If the number is larger, then use the frexpl()
version whose argument is a long double. The Exp argument is passed as a pointer to an
integer. This allows the function to return a second value.

After execution, the function returns the mantissa such that:

Mantissa = frexp(Number, Exp);

The result returned, Mantissa, is a double (frexp) or a long double (frexpl) number in the
range 0.5 (included) to 1 (excluded). The Exp argument, passed as a pointer, is returned
as

Number = Mantissa * 2Exp

For the following example, a form is equipped with three Edit controls named
edtNumber, edtMantissa, and edtExponent. It also has a Button control named
btnCalculate with the Default property set to true. The user must type a number in the
Number edit box and press Enter. Then the OnClick event of the button executes to
perform the frexp() function which leads to displaying the results in the appropriate edit
boxes :

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
double Mant, Number = edtNumber->Text.ToDouble();
int Exp;

Mant = frexp(Number, &Exp);


edtMantissa->Text = Mant;
edtExponent->Text = Exp;
}
//---------------------------------------------------------------------------

173 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.2.4.2 The Frexp() Function


void __fastcall Frexp(Extended Number, Extended &Mantissa, int &Exp);

The Frexp() function is the VCL’s version of the frexp() function. This function takes
three arguments. The number to be examined is the Number argument passed as a lond
double. The number to be returned, also a long double, is the Matissa argument, also
passed by reference. The Exp argument, also passed as a reference is returned as the
exponent value. The numbers are dealt with according to the formula:

Number = Mantissa * 2Exp

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Extended Number, Mant;
int Exp;

Number = StrToFloat(Edit1->Text);
Frexp(Number, Mant, Exp);

Edit2->Text = FloatToStr(Mant);
Edit3->Text = Exp;
}
//---------------------------------------------------------------------------

8.2.5 The Power Functions

8.2.5.1 The C++ pow() Functions

double pow(double Source, double Raise);


long double powl(long double Source, long double Raise);

The pow() function is used to calculate the value of one number or expression raised to
the power of another number. This follows the formula: ReturnValue = xy

The pow() function takes two required arguments. The first argument, x, is used as the
base number to be evaluated. The second argument, y, also called the exponent, will raise
x to this value. The powl() function performs the same calculation on long double
numbers and returns a long double.

174 © FunctionX, Inc.


Windows Events Borland C++ Builder

In the following example, a form is equipped with a Button control and an Edit control.
When the user clicks the button, the constant 205.38 is raised to the power of 4.12. The
result displays in the edit box:

//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
const double Source = 205.38;
const double Exp = 4.12;
double Result = pow(Source, Exp);

Edit1->Text = Result;
}
//---------------------------------------------------------------------------

8.2.5.2 The IntPower() function

Extended __fastcall IntPower(Extended Base, int Exponent);

The VCL’s IntPower() function is used to raise a number, Base, to the integral Exponent
power. The first argument of this function, Base, can be an integer, a float, a double-
precision number or a long double. The Exponent argument is the factor about which the
Base number will be raised.

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Extended Number, Base;
int Exp;

Base = StrToFloat(Edit1->Text);
Exp = StrToInt(Edit2->Text);
Number = IntPower(Base, Exp);

Edit3->Text = FloatToStr(Number);
}
//---------------------------------------------------------------------------

8.2.5.3 The Power() Function

Extended __fastcall Power(Extended Base, Extended Exponent);

175 © FunctionX, Inc.


Windows Events Borland C++ Builder

The Power() function takes a number (any number, including integers, floating, double
or long double-precision numbers) as the Base argument and raises it to the power of the
Exponent argument, which also can be any number (int, float, double, long double).

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Source = 205;
float Exp = 5.25;
double Result = Power(Source, Exp);

Edit1->Text = Result;
}
//---------------------------------------------------------------------------

8.2.6 The Exponential


double exp(double x);

The exp() function calculates the exponential value of a number. The argument, a double-
precision value, represents the number to be evaluated.

If the value of x is less than -708.395996093 (approximately), the result is reset to 0 and
qualifies as underflow. If the value of the argument x is greater than 709.78222656
(approximately), the result is INF and qualified as overflow:

//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
cout << "\nThe exponential of " << 709.78222656
<< " is " << exp(709.78222656);

cout << "\n\nPress any key to continue...";


getchar();
return 0;
}
//---------------------------------------------------------------------------

Therefore, the value of the argument should be between these two extremes. For a larger
number, use the expl() function:

long double expl(long double x);

As opposed to an 8-byte value, this version of the function takes a 10-byte variable,
calculates its exponent, and returns a long double.

8.2.7 The Ldexp functions

8.2.7.1 The ldexp Function

double ldexp(double x, int y);

176 © FunctionX, Inc.


Windows Events Borland C++ Builder

long double ldexpl(long double x, int y);

The C/C++ ldexp() function takes the mantissa and the exponent numbers and returns a
floating number. The function uses the formula:

Result = x * 2y

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double x, Result;
int y;

x = StrToFloat(Edit1->Text);
y = StrToInt(Edit2->Text);
Result = ldexp(x, y);

Edit3->Text = FloatToStr(Result);
}
//---------------------------------------------------------------------------

The ldexp() function works on double-precision numbers while the ldexpl() uses long
doubles.

8.2.7.1 The Ldexp() Function

Extended __fastcall Ldexp(Extended X, int P);

The VCL’s Ldexp() function is used to calculate a number that is derived from a known
mantissa and an exponent numbers. To perform this calculation, the function uses the
formula:

Result = X * 2P

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
float Source = 450.04;
float Exp = 10.25;
double Result = Ldexp(Source, Exp);

Edit1->Text = Result;
}
//---------------------------------------------------------------------------

8.2.8 LnXP1
The LnXP1() function is used to calculate the natural logarithm of a number that is being
incremented to 1. The syntax of this function is

Extended __fastcall LnXP1(Extended X);

177 © FunctionX, Inc.


Windows Events Borland C++ Builder

When executing, this function takes one argument, X, adds 1 to X, and then calculates the
natural logarithm, also called the Napierian logarithm, of the new number. The formula
used is Result = ln(X+1). Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Extended X, Result;

X = StrToFloat(Edit1->Text);
Result = LnXP1(X);
Edit2->Text = FloatToStr(Result);
}
//---------------------------------------------------------------------------

8.2.9 Log10
The Log10() function calculates the base 10 logarithm of a number. The syntax of this
function is:

Extended __fastcall Log10(Extended X);

The number to be evaluated is passed as the argument X. The function returns the
logarithm on base 10 using the formula:

y = log10x which is equivalent to x = 10y

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Extended X, Result;

X = StrToFloat(Edit1->Text);
Result = Log10(X);
Edit2->Text = FloatToStr(Result);
}
//---------------------------------------------------------------------------

8.2.10 Log2
The Log2() function is used to calculate the logarithm of a number on base 2. The syntax
of the function is:

Extended __fastcall Log2(Extended X);

The variable whose logarithmic value will be calculated is passed as argument X to the
function. The function uses the formula:

Y = log2x. This is the same as x = 2y

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

178 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall TForm1::Button1Click(TObject *Sender)


{
Extended X, Result;

X = StrToFloat(Edit1->Text);
Result = Log2(X);
Edit2->Text = FloatToStr(Result);
}
//---------------------------------------------------------------------------

8.2.11 LogN
The LogN() function is used to calculate the logarithmic value of a number to the desired
base. Its syntax is:

Extended __fastcall LogN(Extended Base, Extended Number);

This function takes two arguments. The second, Number, is the variable whose value will
be evaluated. The first argument, Base, is used as the base of the logarithm. The formula
used by this function is:

y = logbx which is the same as x = by

For the LogN() function, this formula would be:

LogN(Base, Number) = NumberBase;

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Extended Base, Number, Result;

Base = StrToFloat(Edit1->Text);
Number = StrToFloat(Edit2->Text);
Result = LogN(Base, Number);

Edit3->Text = FloatToStr(Result);
}
//---------------------------------------------------------------------------

8.2.12 The Square Root


There are two forms of calculating the square root of a Real positive number. When using
any of these functions, make sure you include the math.h header file to your project.

The sqrt() function is used to calculate the square root of a double-precision number. Its
syntax is:

double sqrt(double x);

This function takes one argument as a positive floating number. After the calcultion, the
function returns the square root of x:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)

179 © FunctionX, Inc.


Windows Events Borland C++ Builder

{
double Number = Edit1->Text.ToDouble();
double Result = sqrt(Number);

Edit2->Text = Result;
}
//---------------------------------------------------------------------------

For a large or larger number, you can use the sqrtl() function. Its syntax is:

long double sqrtl(long double x);

This second form takes a long double number as a variable and returns a long double
number as the square root of x.

After the calculation, if a function succeed, it would return the square root. If it fails, it
would throw an error.

Practical Learning: Calculating the Result(s) of a Quadratic Equation


1. Start a new project with the default form. Position five Edit controls and a
button on the form. Design the form as follows:

2. Change the names of the Edit controls as follows: edtA, edtB, edtC, edtRoot1,
edtRoot2. Change the name of the main button to btnProcess and its caption to
Process.
3. Double-click the Process button and implement it as follows:
//---------------------------------------------------------------------------
void __fastcall TForm1::btnProcessClick(TObject *Sender)
{
double A, B, C;

A = edtA->Text.ToDouble();
B = edtB->Text.ToDouble();
C = edtC->Text.ToDouble();

if( A == 0 )

180 © FunctionX, Inc.


Windows Events Borland C++ Builder

return;
double A2 = 2 * A;

double D = (B * B) - (4 * A * C);
double Delta = sqrt(D);
double Root1 = (-B - Delta) / A2;
double Root2 = (-B + Delta) / A2;

edtRoot1->Text = Root1;
edtRoot2->Text = Root2;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

4. To test the program, on the main menu, click Run  Run. Test the program with
A = 1, B = -6, and C = 9.
5. Return to Bcb

8.3 Business Functions


An asset is an object of value. It could be a person, a car, a piece of jewelry, a
refrigerator. Anything that has a value is an asset. In the accounting world, an asset is a
piece of/or property whose life span can be projected, estimated, or evaluated. As days,
months or years go by, the value of such an asset degrade.

When an item is acquired for the first time as “brand new”, the value of the asset is
referred to as its Cost. The declining value of an asset is referred to as its Depreciation.
At one time, the item will completely lose its worth or productive value. Nevertheless,
the value that an asset has after it has lost all its value is referred to its Salvage Salue. At
any time, between the purchase value and the salvage value, accountants estimate the
value of an item based on various factors including its original value, its lifetime, its
usefulness (how the item is being used), etc.

8.3.1 DoubleDecliningBalance
The Double Declining Balance is a method used to calculate the depreciating value of an
asset. The function used to perform this calculation is the DoubleDecliningBalance() and
its syntax is:

Extended __fastcall DoubleDecliningBalance(Extended Cost, Extended Salvage, int


Life, int Period);

The first argument, Cost, represents the initial value of the item. The Salvage argument is
the estimated value of the asset when it will have lost all its productive value. The Cost
and the Salvage values must be given in their monetary values. The value of Life is the
length of the lifetime of the item; this could be the number of months for a car or the
number of years for a house for example. The Period is a factor for which the

181 © FunctionX, Inc.


Windows Events Borland C++ Builder

depreciation is calculated. For the Double Declining Balance, this Period argument is
usually 2.

In the following example, a form is equipped with five Edit controls named edtCost,
edtSalvage, edtLife, edtPeriod, and edtDepreciation. After entering the necessay values
and pressing Enter, the OnClick event of the Calculate button retrieves the values and
calls the DoubleDecliningBalnace() function to calculate the Depreciation and display it
the appropriate edit box:

//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.hpp>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Cost = StrToFloat(edtCost->Text);
Extended Salvage = StrToFloat(edtSalvage->Text);
Integer Life = StrToInt(edtLife->Text);
Integer Period = StrToInt(edtPeriod->Text);
Extended Depreciation = DoubleDecliningBalance(Cost, Salvage, Life, Period);

edtDepreciation->Text = FloatToStr(Depreciation);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

182 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.3.2 SLNDepreciation
The VCL provides another method used to calculate the depreciation of an item. This
time, the depreciation is considered on one period of the life of the item. The function
used, SLNDepreciation, is:

Extended __fastcall SLNDepreciation(const Extended Cost, const Extended Salvage,


int Life);

The Cost argument is the original amount paid for an item (refrigerator, mechanics
toolbox, high-volume printer, etc). The Life represents the period during which the asset
is (or was) useful; it is usually measured in years. The Salvage, also called the scrap
value, is the value that the item will have (or is having) at the end of Life.

To perform this operation, the VCL uses the following formula:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Depreciation, Cost, Salvage;
int Life;

Cost = StrToFloat(edtCost->Text);
Salvage = StrToFloat(edtSalvage->Text);
Life = StrToInt(edtLife->Text);
Depreciation = SLNDepreciation(Cost, Salvage, Life);

edtDepreciation->Text = FloatToStrF(Depreciation, ffCurrency, 8, 2);


}
//---------------------------------------------------------------------------

8.3.3 SYDDepreciation
The Sum-Of-The-Years’-Digits provides another method for calculating the depreciation
of an item.

Imagine that a restaurant bought a commercial refrigerator (“cold chamber”) for $18,000
and wants to estimate its depreciation after 5 years using the Sum-Of-Years’-Digits

183 © FunctionX, Inc.


Windows Events Borland C++ Builder

method. Each year is assigned a number, also called a tag, using a consecutive count; this
means that the first year is appended 1, the second is 2, etc. This way, the depreciation is
not uniformly applied to all years.

Year => 1, 2, 3, 4, and 5.

The total count is made for these tags. For our refrigerator example, this would be

Sum = 1 + 2 + 3 + 4 + 5 = 15

Each year is divided by this Sum, also called the sum of years, used as the common
denominator:

This is equivalent to 1. As you can see, the first year would have the lowest divident
(1/15 ≈ 0.0067) and the last year would have the highest (5/15 ≈ 0.33).

To calculate the depreciation for each year, the fractions (1/15 + 2/15 + 3/15 + 4/15 +
5/15) are reversed so that the depreciation of the first year is calculated based on the last
fraction (the last year divided by the common denominator). Then the new fraction for
each year is multiplied by the original price of the asset. This would produce:

Year Fraction * Amount = Depreciation


1 5/15 * $18,000.00 = $6,000.00
2 4/15 * $18,000.00 = $4,800.00
3 3/15 * $18,000.00 = $3,600.00
4 2/15 * $18,000.00 = $2,400.00
5 1/15 * $18,000.00 = $1,200.00
Total Depreciation = $18,000.00

The VCL function used to calculate the depreciation of an asset using the sum of the
years is called SYDDepreciation and its syntax is:

Extended __fastcall SYDDepreciation(constExtended Cost, const Extended Salvage,


int Life, int Period);

The Cost argument is the original value of the item; in our example, this would be
$18,000. The Salvage is the value the asset would have (or has) at the end of its useful
life. The Life is the number of years of the asset would have a useful life. The Period is
the particular period or rank of a Life portion; for example, if the Life of the depreciation
is set to 5 (years), the Period could be any number between 1 and 5. If set to 1, the
depreciation would be calculated for the first year. If the Period is set to 4, the
depreciation would calculated for the 4th year. You can also set the Period to a value
higher than Life. For example, if Life is set to 5 but you pass 8 for the Period, the
depreciation would be calculated for the 8th year. If the asset is worthless in the 8th year,
the depreciation would be 0.

Here is an example:

184 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended DeprecYear1, DeprecYearN, Cost, Salvage;
int Life;

Cost = StrToFloat(edtCost->Text);
Salvage = StrToFloat(edtSalvage->Text);
Life = StrToInt(edtLife->Text);
DeprecYear1 = SYDDepreciation(Cost, Salvage, Life, 1);
DeprecYearN = SYDDepreciation(Cost, Salvage, Life, Life);

edtYear1->Text = FloatToStrF(DeprecYear1, ffCurrency, 8, 2);


edtYearN->Text = FloatToStrF(DeprecYearN, ffCurrency, 8, 2);
}
//---------------------------------------------------------------------------

8.4 Finance Functions


The Visual Component Library provides a series of function destined to perform various
types of financially related operations. These functions use common factors depending on
the value that is being calculated. Many of these functions deal with investments or loan
financing.

The Present Value is the current value of an investment or a loan. For a savings account,
a customer could pledge to make a set amount of deposit on a bank account every month.
The initial value that the customer deposits or has in the account is the PresentValue as
referenced in the VCL functions. The sign of the variable, when passed to a function,
depends on the position of the customer. If the customer is making deposits, this value
must be negative. If the customer is receiving money (lottery installment, family
inheritance, etc), this value should be positive.

The Number Of Periods is the number of periods that make up a full cycle of a loan or
an investment. This period could be the number of months of a year, which is 12; but it
could be another length. This variable is passed as NPeriods. Suppose a customer is
getting a car loan that would be financed in 5 years. This is equivalent to 5 * 12 = 60
months. In the same way, a cash loan can stretch from 0 to 18 months, a carpenter truck
loan can have a life financing of 40 months, and a condominium can be financed for 15

185 © FunctionX, Inc.


Windows Events Borland C++ Builder

years of 12 months plus an additional 8 months; this is equivalent to (15 * 12) + 8 = 188
months.

The Interest Rate argument is a fixed percent value applied during the life of the loan or
the investment. The rate does not change during the length of the NPeriods. For deposits
made in a savings account, because their payments are made monthly, the rate is divided
by the number of periods (the NPeriods) of a year, which is 12. If an investment has an
interest rate set at 14.50%, the Rate would be 14.50/12 = 1.208. Because the Rate is a
percentage value, its actual value must be divided by 100 before passing it to the
function. For a loan of 14.50 interest rate, this would be 14.50/12 = 1.208/100 = 0.012.

The Payment is the amount the customer will be paying. For a savings account where a
customer has pledged to pay a certain amount in order to save a set (goal) amount, this
would be the amount the customer would pay every month. If the customer is making
payments (car loan, mortgage, deposits to a savings account), this value must be negative.
If the customer is receiving money (lottery installment or annuity, family inheritance,
etc), this value must be positive.

The Payment Time specifies whether the payment is made at the beginning or the end of
the period. For a monthly payment, this could be the beginning or end of every month.
The PaymentTime uses one of the values of the TPaymentTime enumerator. When
passing this variable, select one of the members of the enumerator:

enum TPaymentTime { ptEndOfPeriod, ptStartOfPeriod };

8.4.1 The Future Value of an Investment


The FutureValue() function is used to calculate the future value of an investment. The
syntax of this function is:

Extended __fastcall FutureValue(Extended Rate, int NPeriods, Extended Payment,


Extended PresentValue, TPaymentTime PaymentTime);

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, Payment, TheRate;
int Period;

186 © FunctionX, Inc.


Windows Events Borland C++ Builder

Present = StrToFloat(edtPresent->Text);
Payment = StrToFloat(edtPayment->Text);
Period = StrToInt(edtPeriod->Text);
TheRate = StrToFloat(edtRate->Text) / 12;
double Rate = TheRate /100;
Future = FutureValue(Rate, Period, Payment, Present, ptEndOfPeriod);

edtFuture->Text = FloatToStrF(Future, ffCurrency, 8, 2);


}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

8.4.2 The Number of Periods of an Investment


The NumberOfPeriods() function calculates the number of periodic payments of an
investment. Its syntax is:

Extended __fastcall PeriodPayment(constExtended Rate, int Period, int NPeriods,


const Extended PresentValue, const Extended FutureValue, TPaymentTime
PaymentTime);

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, TheRate, Payments, NPeriod;

Present = StrToFloat(edtLoan->Text);
Future = StrToFloat(edtFuture->Text);
Payments = StrToFloat(edtPayments->Text);
TheRate = StrToFloat(edtRate->Text) / 12;

double Rate = TheRate / 100;


// Apply the function
NPeriod = NumberOfPeriods(Rate, -Payments, -Present,

187 © FunctionX, Inc.


Windows Events Borland C++ Builder

Future, ptStartOfPeriod);
// Since the number of periods is really an integer, find its ceiling
Extended Actual = Ceil(NPeriod);
// Display the number of periods
edtNPeriods->Text = FloatToStr(Actual);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
PostQuitMessage(0);
}
//---------------------------------------------------------------------------

8.4.3 Making an Investment or Paying a Loan


The Payment() function is used to calculate the regular payment of an investment. Its
syntax is:

Extended __fastcall Payment(Extended Rate, int NPeriods, constExtended


PresentValue, const Extended FutureValue, TPaymentTime PaymentTime);

In the following examples, a customer is applying for a car loan. The car costs $15500. It
will be financed at 8.75% for 5 years. The dealer estimates that the car will have a value
of $2500 when it is paid off:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, TheRate, Payments, NPeriod;

Present = StrToFloat(edtLoan->Text);
Future = StrToFloat(edtFuture->Text);
TheRate = StrToFloat(edtRate->Text) / 12;
NPeriod = StrToFloat(edtNPeriods->Text);

double Rate = TheRate / 100;


// Apply the function
Payments = Payment(Rate, NPeriod, -Present,
Future, ptStartOfPeriod);
// Display the payments
edtPayments->Text = FloatToStrF(Payments, ffCurrency, 8, 2);

188 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

8.4.4 The Amount Paid as Principal


While the InterestPayment() function calculates the amount paid as interest for a loan,
the PeriodPayment() function calculates the actual amount that applies to the balance of
the loan. This is referred to as the principal. Its syntax is:

Extended __fastcall PeriodPayment(constExtended Rate, int Period, int NPeriods,


const Extended PresentValue, const Extended FutureValue, TPaymentTime
PaymentTime);

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, TheRate, PPayment;
int Periods, NPeriod;

Present = StrToFloat(edtLoan->Text);
Future = StrToFloat(edtFuture->Text);
TheRate = StrToFloat(edtRate->Text) / 12;
Periods = StrToInt(edtPeriod->Text);
NPeriod = StrToInt(edtNPeriods->Text);

double Rate = TheRate / 100;


// Apply the function
PPayment = PeriodPayment(Rate, Periods, NPeriod,
-Present, Future, ptStartOfPeriod);
// Display the payment
edtPPMT->Text = FloatToStrF(PPayment, ffCurrency, 8, 2);
}
//---------------------------------------------------------------------------

189 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.4.5 The Present Value of an Investment


The PresentValue() function calculates the total amount that future investments are
worth currently. Its syntax is:

Extended __fastcall PresentValue(constExtended Rate, int NPeriods, const


Extended Payment, const Extended FutureValue, TPaymentTime PaymentTime);

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, TheRate, Payments;
int NPeriod;

Future = StrToFloat(edtFuture->Text);
Payments = StrToFloat(edtPayments->Text);
TheRate = StrToFloat(edtRate->Text) / 12;
NPeriod = StrToInt(edtNPeriods->Text);

double Rate = TheRate / 100;


// Apply the function
Present = PresentValue(Rate, NPeriod,
-Payments, -Future, ptStartOfPeriod);
// Display the payment
edtPresent->Text = FloatToStrF(Present, ffCurrency, 8, 2);
}
//---------------------------------------------------------------------------

8.4.6 The Amount Paid As Interest


The InterestPayment() function is used to calculate the amount paid as interest for a
loan. Its syntax is:

Extended __fastcall InterestPayment(constExtended Rate, int Period, int NPeriods,


const Extended PresentValue, const Extended FutureValue, TPaymentTime
PaymentTime);

The PresentValue is the current value of the item. It could be the marked value of the car,
the current mortgage value of a house, or the cash amount that a bank is lending. The

190 © FunctionX, Inc.


Windows Events Borland C++ Builder

NPeriods is the number of periods that occur during a yearly cycle of the loan. The Rate
argument is a fixed percent value applied during the life of the loan. The Period argument
represents the payment period. The FutureValue is the total amount that the customer will
have paid when the loan is paid off. The PaymentTime specifies whether the periodic
(such as monthly) payment of the loan is made at the beginning or end of the period.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, Payment, TheRate;
int Periods, NPeriod;

Present = StrToFloat(edtPresent->Text);
Future = StrToFloat(edtFuture->Text);
Periods = StrToInt(edtPeriod->Text);
NPeriod = StrToInt(edtNPeriods->Text);
TheRate = StrToFloat(edtRate->Text) / 12;
double Rate = TheRate /100;

Payment = InterestPayment(Rate, Periods, NPeriod,


Present, Future, ptEndOfPeriod);

edtPayments->Text = FloatToStrF(Payment, ffCurrency, 8, 2);


}
//---------------------------------------------------------------------------

8.4.7 The Interest Rate


The InterestRate() function is used to find the interest applied to a loan. Its syntax is:

Extended __fastcall InterestRate(int NPeriods, constExtended Payment, const


Extended PresentValue, const Extended FutureValue, TPaymentTime
PaymentTime);

All of the arguments are the same as described for the InterestPayment() function. Here
is an example:

191 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
Extended Present, Future, Payments, Rate;
int NPeriod;

Present = StrToFloat(edtPresent->Text);
Future = StrToFloat(edtFuture->Text);
Payments = StrToFloat(edtPayments->Text);
NPeriod = StrToInt(edtNPeriods->Text);

Rate = InterestRate(NPeriod, Payments, Present,


Future, ptEndOfPeriod) * 12 * 100;
AnsiString Value = FloatToStrF(Rate, ffGeneral, 3, 2);
edtRate->Text = Value + "%";
}
//---------------------------------------------------------------------------

8.4.8 The Internal Rate of Return


The InternalRateOfReturn() function is used to calculate an internal rate of return
based on a series of investments. Its syntax is:

Extended __fastcall InternalRateOfReturn(constExtended Guess, const double *


CashFlows, const int CashFlows_Size);

The CashFlows is an array of cash amounts that a customer has made on an investment.
For example, a customer could make monthly deposits in a savings or credit union
accounts. Another customer could be running a business and receiving different amounts
of money as the business is flowing (or losing money). The cash flows do not have to be
the same at different intervals but they should (or must) occur at regular intervals such as
weekly (amount cut from a paycheck), bi-weekly (401k directly cut from paycheck,
monthly (regular investment), or yearly (income). The CashFlows argument must be
passed as an array and not an amount; otherwise you would receive an error.

The Guess is an estimate interest rate of return of the investment.

The CashFlow_Size is the dimension of the array – 1.

Here is an example:

192 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
double Goal;
double Month1, Month2, Month3, Month4, Month5, Month6;
Extended InterestGuess;
int Periods;

// Retrieve the estimate financial goal to achieve


Goal = edtGoal->Text.ToDouble();
// Retrieve the monthly investments
Month1 = edtMonth1->Text.ToDouble();
Month2 = edtMonth2->Text.ToDouble();
Month3 = edtMonth3->Text.ToDouble();
Month4 = edtMonth4->Text.ToDouble();
Month5 = edtMonth5->Text.ToDouble();
Month6 = edtMonth6->Text.ToDouble();
// Guess how much percentage
InterestGuess = StrToFloat(edtGuess->Text) / 100;

double Months[] = {-Goal,Month1,Month2,Month3,Month4,Month5,Month6};


Periods = (sizeof(Months) / sizeof(double)) - 1;
double IRR = InternalRateOfReturn(-InterestGuess, Months, Periods) * 100;

// Format the number to display only two decimals


AnsiString Value = FloatToStrF(IRR, ffGeneral, 3, 2);
// Display the result with a percent sign
edtIRR->Text = Value + "%";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
exit(0);
}
//---------------------------------------------------------------------------

193 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.4.9 NetPresentValue
The NetPresentValue() function uses a series of cash flows to calculate the present value
of an investment. Its syntax is:

Extended __fastcall NetPresentValue(const Extended Rate, const double *


CashFlows, const int CashFlows_Size, TPaymentTime PaymentTime);

The CashFlows is an array of payments made on an investment. Because it uses a series


of payments, any payment made in the past should have a positive value (because it was
made already). Any future payment should have a negative value (because it has not ben
made yet). The CashFlows should be passed as an array. The CashFlows_Size is the
number of payments – 1, which is also the dimension of the array –1.

The Rate is the rate of discount during one period of the investment.

The PaymentTime specifies whether the payment occurs at the beginning or end of the
period. It uses the TPaymentTime enumerator.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCalculateClick(TObject *Sender)
{
double Goal;
double Month1, Month2, Month3, Month4, Month5, Month6;
Extended Rate;
int Periods;

// Retrieve the estimate financial goal to achieve


Goal = edtGoal->Text.ToDouble();
// Retrieve the monthly investments
Month1 = edtMonth1->Text.ToDouble();
Month2 = edtMonth2->Text.ToDouble();
Month3 = edtMonth3->Text.ToDouble();
Month4 = edtMonth4->Text.ToDouble();
Month5 = edtMonth5->Text.ToDouble();
Month6 = edtMonth6->Text.ToDouble();
Rate = StrToFloat(edtRate->Text) / 100;

194 © FunctionX, Inc.


Windows Events Borland C++ Builder

double Months[] = { Month1, Month2, Month3, Month4, Month5, Month6 };


Periods = (sizeof(Months) / sizeof(double)) - 1;
double NPV = NetPresentValue(Rate, Months, Periods, ptEndOfPeriod) - Goal;

// Format the number to display as currency


edtNPV->Text = FloatToStrF(NPV, ffCurrency, 8, 2);
}
//---------------------------------------------------------------------------

8.5 Measurement Functions

A
R
C B

A circle is a group or series of distinct points drawn at an exact same distance from
Note
Equidistant
another point referred to as the center. The distance from the center C to one of these
means “same equidistant points is called the radius, R. The line that connects all of the points that are
distance” equidistant to the center is called the circumference of the circle. The diameter is the
distance between two points of the curcumference to the center; in other words, a
diameter is double the radius.

To manage the measurements and other related operations, the circumference is divided
into 360 portions. Each of these portions is called a degree. The unit used to represent the
degree is the degree, written as ˚. Therefore, a circle contains 360 degrees, that is 360˚.
The measurement of two points A and D of the circumference could have 15 portions of
the circumference. In this case, this measurement would be represents as 15˚.

The distance between two equidistant points A and B is a round shape geometrically
defined as an arc. An angle, ө, is the ratio of the distance between two points A and B of
the curcumference divided by the radius R. This can be written as:

Therefore, an angle ө is the ratio of an arc over the radius. Because an angle is a ratio and
not a “physical” measurement, which means an angle is not a dimension, it is
independent of the size of a circle. Obviously this angle represents the number of portions
included by the three points. A better unit used to measure an angle is the radian or rad.

195 © FunctionX, Inc.


Windows Events Borland C++ Builder

A cycle is a measurement of the rotation around the circle. Since the rotation is not
necessarily complete, depending on the scenario, a measure is made based on the angle
that was covered during the rotation. A cycle could cover part of the cycle in which case
the rotation would not have been complete. A cycle could also cover the whole 360˚ of
the circle and continue there after. A cycle is equivalent to the radian divided by 2 * Pi.

The VCL ships with functions used to perform conversions of values between different
units. To use any of these functions, you must include the VCL math header file as:

#include <math.hpp>

8.5.1 Pi
The word п, also written as Pi, is a constant number used in various mathematical
calculations. Its approximate value is 3.1415926535897932. The calculator of Windows
represents it as 3.1415926535897932384626433832795. Borland had included its value
in the math.h library as M_PI 3.14159265358979323846.

A diamter is two times the radius. In geometry, it is written as 2R. In C++, it is written as
2 * R or R * 2 (because the multiplication is symmetric). The circumference of a circle is
calculated by multiplying the diamter to Pi, which is 2Rп, or 2 * R * п or 2 * R * Pi.

A radian is 2Rп/R radians or 2Rп/R rad, which is the same as 2п rad or 2 * Pi rad.

To perform conversions between the degree and the radian, you can use the formula:

360˚ = 2п rad which is equivalent to 1 rad = 360˚ / 2п = 57.3˚

8.5.2 CycleToRad
Extended __fastcall CycleToRad(Extended Cycles);

The CycleToRad() function is used to convert the measurement of an angle from radians
to cycles. This function is equivalent to using the formula Radian = 2Pi * Cycle.

Here is an example:

//---------------------------------------------------------------------------
#include <MATH.HPP>
#include <vcl.h>
#pragma hdrstop

196 © FunctionX, Inc.


Windows Events Borland C++ Builder

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnConversionClick(TObject *Sender)
{
Extended Cyc = StrToFloat(edtCycle->Text);
Extended Rad = CycleToRad(Cyc);

edtRadian->Text = FloatToStr(Rad);
}
//---------------------------------------------------------------------------

8.5.3 DegToRad
Extended __fastcall DegToRad(Extended Degrees);

The DegToRad is used to calculate the equivalent value of an angle from degrees to
radians. This function follows the formula:

2Pi rad = 360˚ which is 1 rad = 360˚ / 2Pi = 180˚ / Pi = 57.3˚

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConversionClick(TObject *Sender)
{
Extended Deg = StrToFloat(edtDegrees->Text);
Extended Rad = DegToRad(Deg);
edtRadians->Text = FloatToStr(Rad);
}
//---------------------------------------------------------------------------

197 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.5.4 RadToCycle
Extended __fastcall RadToCycle(Extended Radians);

The RadToCycle() is used to convert the measurement of an angle from radians to cycles.
This function is equivalent to using the formula Cycle = Radian / 2Pi.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConversionClick(TObject *Sender)
{
Extended Rad = StrToFloat(edtRadian->Text);
Extended Cyc = RadToCycle(Rad);

edtCycle->Text = FloatToStr(Cyc);
}
//---------------------------------------------------------------------------

8.5.5 RadToDeg

Extended __fastcall RadToDeg(Extended Radians);

The RadToDeg() function is used to calculate the equivalent value of an angle from
radians to degrees. This function applies the formula:

360˚ = 2 * Pi which is 1˚ = 2 * Pi

Here is an example:

198 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConversionClick(TObject *Sender)
{
Extended Rad = StrToFloat(edtRadians->Text);
Extended Deg = RadToDeg(Rad);
edtDegrees->Text = FloatToStr(Deg);
}
//---------------------------------------------------------------------------

8.6 Statistics

8.6.1 MaxIntValue

int __fastcall MaxIntValue(const int * Data, const int Data_Size);

The MaxIntValue() function calculates the maximum value of an array of integers. The
first argument of the function, Data, represents the name of the array. The second
argument, Data_Size is the number-1 of members of the array.

To get the maximum value of a group of integers, declare an integral array of numbers.
You can initialize such a variable or request the values of its members from the user. The
value of the Data_Size argument must be 1 less than the total number of the array
members.

Here is an example that uses the MaxIntValue() function:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{

199 © FunctionX, Inc.


Windows Events Borland C++ Builder

int n, Numbers[100];

cout << "How many numbers? ";


cin >> n;

for(int i = 0; i < n; i++)


{
cout << "Number " << i + 1 << ": ";
cin >> Numbers[i];
}

int MaxInteger = MaxIntValue(Numbers, n-1);


cout << "The maximum of those numbers is " << MaxInteger;

getchar();
return 0;
}
//---------------------------------------------------------------------------

8.6.2 MaxValue

double __fastcall MaxValue(const double * Data, const int Data_Size);

The MaxValue is a numeric value that represents the maximum number of items of an
array. This function takes two arguments. The first argument, Data, represents an array of
integers or double-precision numbers. The second argument is the number-1 of the items
of the array; for example, if the considered array has 4 members, the Data_Size argument
would be 3.

To use the MaxValue() function, declare an array that involves the necessary numbers.
You can initialize such a variable or request the numbers from the user. To calculate the
maximum value of a range, supply the array and its size. If you do not know the
dimension of the array, you can use the sizeof operator to find it out. Here is an example
of using the MaxValue() function:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{
double Values[] = { 12.55, 10.15, 980.22, 50.50, 280.12 };
int Size = (sizeof(Values)/sizeof(double)) - 1;

double Maximum = MaxValue(Values,Size);


cout << "Maximum = " << Maximum;

getchar();
return 0;

200 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

8.6.3 Mean

Extended __fastcall Mean(const double * Data, const int Data_Size);

The Mean() function considers an array of numbers and calcuates the average value of
those numbers. The function takes two arguments. The first, Data, is the name of the
array of numbers. These number could integers or floating numbers. The second
argument, Data_Size represents the number-1 of members of the array. You can type an
integral number as the Data_Size or you can use the sizeof operator to get the dimension
of the array and subtract 1 from it. After the calculation, the function returns a long
double-precision number as the average of the numbers.

Here is an example:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{
double Values[] = { 12.55, 10.15, 980.22, 50.50, 280.12 };
int Size = (sizeof(Values)/sizeof(double)) - 1;

double Average = Mean(Values, Size);


cout << "Average = " << Average;

getchar();
return 0;
}
//---------------------------------------------------------------------------

8.6.4 MinIntValue

int __fastcall MinIntValue(const int * Data, const int Data_Size);

The MinIntValue() function calculates the minimum value of an array of integers. The
Data argument of the function is the name of the array. The second argument, Data_Size
is the number-1 of members of the array.

To get the minimum value of a group of integers, declare an integral array of numbers.
You can initialize the variable or request the values of its members from the user. The
value of the Data_Size argument must be 1 less than the total number of members.

Here is an example that uses the MaxIntValue() function:

201 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused
int main(int argc, char* argv[])
{
int n, Numbers[100];

cout << "How many numbers? ";


cin >> n;

for(int i = 0; i < n; i++)


{
cout << "Number " << i + 1 << ": ";
cin >> Numbers[i];
}

int MinInteger = MinIntValue(Numbers, n-1);


cout << "The minimum of those numbers is " << MinInteger;

getchar();
return 0;
}
//---------------------------------------------------------------------------

8.6.5 MinValue

double __fastcall MinValue(const double * Data, const int Data_Size);

The MinValue() function gets a numeric value that represents the minimum value of the
items of an array. This function takes two arguments. The first argument, Data, represents
an array of integers or double-precision numbers. The second argument is the number-1
of the items of the array; for example, if the considered array has 4 members, the
Data_Size argument would be 3.

To use the MinValue() function, declare an array that involves the necessary numbers.
You can initialize such a variable or request the values from the user. To calculate the
minimum value of a range, supply the array and its size. If you do not know the
dimension of the array, you can use the sizeof operator to find it out. Here is an example
that uses the MinValue() function:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

202 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

#pragma argsused
int main(int argc, char* argv[])
{
double Values[] = { 12.55, 10.15, 980.22, 50.50, 280.12 };
int Size = (sizeof(Values)/sizeof(double)) - 1;

double Minimum = MinValue(Values,Size);


cout << "Minimum = " << Minimum;

getchar();
return 0;
}
//---------------------------------------------------------------------------

8.6.6 Sum

Extended __fastcall Sum(const double * Data, const int Data_Size);

The Sum() function is used to calculate the sum value of a group of numbers. The first
argument of this function, Data, is the name of an array that holds the numbers
considered. The Data_Size argument isthe dimension of the array minus 1.

To get the sum of a group of numbers, declare an array to hold the necessary numbers.
The numbers can be integers or double precision values. You can initialize the array with
these numbers or request their values from the user.

Here is an example of calculating a total number after requesting grades from the user of
a program:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused

int main(int argc, char* argv[])


{
double English, GeogHist, CompSc, CompApl, Socio, Philo, Biol, Sports;
cout << "Enter the Kim's Grades\n";
cout << "English: "; cin >> English;
cout << "Geography and Hist: "; cin >> GeogHist;
cout << "Computer Sciences: "; cin >> CompSc;
cout << "Comp Applications: "; cin >> CompApl;
cout << "Sociology: "; cin >> Socio;
cout << "Philosophy: "; cin >> Philo;
cout << "Biology: "; cin >> Biol;

203 © FunctionX, Inc.


Windows Events Borland C++ Builder

cout << "Sports: "; cin >> Sports;

double Grades[] = { English, GeogHist, CompSc, CompApl,


Socio, Philo, Biol, Sports };
double Total = Sum(Grades, 7);

cout << "\n\nKim's Total: " << Total;


getchar();
return 0;
}
//---------------------------------------------------------------------------

8.6.7 SumInt

int __fastcall SumInt(const int * Data, const int Data_Size);

The SumInt() function is used to calculate the total of a group of integral numbers. This
function takes two arguments. The first, Data, is the name of the array that holds the
numbers. The numbers must be integers. If you want to calculate a total of floating-point
numbers, use the Sum() function. The second argument, Data_Size is the size of the array
minus one.

Here is an example that simulates a company inventory to count business assets:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused

int main(int argc, char* argv[])


{
int Tables, Chairs, BookShelves, TrashCans,
Desktops, Laptops, Printers, FaxMachines,
Books, Pens, Pencils, Others;

cout << "Company Inventory\nType the number of items of each category\n";


cout << "Desktops: "; cin >> Desktops;
cout << "Laptops: "; cin >> Laptops;
cout << "Printers: "; cin >> Printers;
cout << "Fax Machines: "; cin >> FaxMachines;
cout << "Chairs: "; cin >> Chairs;
cout << "Tables: "; cin >> Tables;
cout << "Book Shelves: "; cin >> BookShelves;
cout << "Books: "; cin >> Books;
cout << "Trash Cans: "; cin >> TrashCans;
cout << "Pens: "; cin >> Pens;
cout << "Pencils: "; cin >> Pencils;
cout << "Others: "; cin >> Others;

204 © FunctionX, Inc.


Windows Events Borland C++ Builder

int Assets[] = { Tables, Chairs, BookShelves, TrashCans,


Desktops, Laptops, Printers, FaxMachines,
Books, Pens, Pencils, Others };
int Items = (sizeof(Assets)/sizeof(int)) - 1;
int AllAssets = SumInt(Assets, Items);

cout << "\nTotal Number of Items: " << AllAssets;

cout << "\n\nPress Enter to send the inventory...";


getchar();
return 0;
}
//---------------------------------------------------------------------------

Company Inventory
Type the number of items of each category
Desktops: 12
Laptops: 2
Printers: 8
Fax Machines: 2
Chairs: 18
Tables: 14
Book Shelves: 10
Books: 20
Trash Cans: 15
Pens: 120
Pencils: 144
Others: 212

Total Number of Items: 577

Press Enter to send the inventory...

8.6.8 SumOfSquares

Extended __fastcall SumOfSquares(const double * Data, const int Data_Size);

The SumOfSquares() function performs a double operation on an array. First it calculates


the square S of each member of the array; then it calculates the total of the individual S
values. The first argument of the function, Data, is the name of the array, the second
argument, Data_Size represents the dimension of the array minus 1.

To calculate the total of the squares, declare an array variable. You can initialize the array
by providing the necessary list of numbers. Otherwise, request the different numbers
from the user. The function will take care of the rest.

Here is example:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

205 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

#pragma argsused

int main(int argc, char* argv[])


{
double Values[] = { 12.02, 30.35, 4.28, 44.12, 6.28 };

Extended TotalOfSquares = SumOfSquares(Values, 4);

cout << "The sum of the squares is: " << TotalOfSquares;
cout << "\n\nTo end, press Enter...";
getchar();
return 0;
}
//---------------------------------------------------------------------------

8.6.9 SumsAndSquares
void __fastcall SumsAndSquares(const double * Data, const int Data_Size, Extended
&Sum, Extended &SumOfSquares);

The SumsAnsSquares() function performs two operations and returns two values. Using a
group of numbers, the function calculates their total, Sum. It also calculates the square S
of each number then calculates the total of the S values, which produces a
SumOfSquares. The first argument, Data, is the array of the numbers considered. The
Data_Size argument is the number of items in the array minus 1. The Sum and the
SumOfSquares arguments are passed by reference, which allows the function to return
these last two values.

Here is an example:

//---------------------------------------------------------------------------
#include <iostream.h>
#include <math.hpp>
#pragma hdrstop

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

#pragma argsused

int main(int argc, char* argv[])


{
Extended Total, TotalOfSquares;
int Size;
double Values[] = { 32.12, 208.45, 14.80, 95.25,
30.32, 102.55, 88.20, 100.05 };

Size = (sizeof(Values)/sizeof(double)) - 1;
SumsAndSquares(Values, Size, Total, TotalOfSquares);

cout << "Sum of Numbers: " << Total << endl;


cout << "Sum Of Squares: " << TotalOfSquares << endl;

206 © FunctionX, Inc.


Windows Events Borland C++ Builder

cout << "\nThe End...";


getchar();
return 0;
}
//---------------------------------------------------------------------------

8.7 Trigonotric Functions

8.7.1 The Cosine Functions

8.7.1.1 Cosine
double cos(double x);
long double cosl(long double x);

The cos() function calculates the cosine of a number.

Consider AB the length of A to B, also referred to as the hypotenuse. Also consider AC


the length of A to C which is the side adjacent to point A. The cosine of the angle at point
A is the ratio AC/AB. That is, the ratio of the adjacent length, AC, over the length of the
hypotenuse, AB.

The returned value, the ratio, is a double-precision number between –1 and 1.

Example: A form contains an Edit control named edtValue. After the user has typed a
value and presses Enter, the OnKeyPress event retrieves the number typed in the edit box,
calculates its cosine and displays it in the same Edit control:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtValueKeyPress(TObject *Sender, char &Key)
{
if( Key == VK_RETURN )
{
double Value = edtValue->Text.ToDouble();
double Cosinus = cos(Value);
edtValue->Text = Cosinus;
}
}
//---------------------------------------------------------------------------

207 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.7.1.2 acos and ArcCos


acos

ArcCos
Calculates the inverse cosine of a given number.

8.7.1.3 Cosine Hyperbolic

Cosh

Calculates the hyperbolic cosine of an angle.

ArcCosh

Calculates the inverse hyperbolic cosine of a given number.

8.7.2 The Sine Functions

8.7.2.1 The sin and sinl


double sin(double x);
long double sinl(long double x);

The sin() function calculates the sine of a number.

Consider AB the length of A to B, also called the hypothenuse to point A. Also consider
CB the length of C to B, which is the opposite side to point A. The sine represents the
ratio of CB/AB; that is, the ratio of the opposite side, CB over the hypothenuse AB.

The sin() function takes a double-precision number and returns one between –1 and 1.
The sinl() function is used for 10-byte values.

Example: A form contains an Edit control named edtValue. After the user has typed a
value and presses Enter, the OnKeyPress event retrieves the number typed in the edit box,
calculates its sine and displays the result in the same Edit control:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtValueKeyPress(TObject *Sender, char &Key)
{
if( Key == VK_RETURN )
{

208 © FunctionX, Inc.


Windows Events Borland C++ Builder

double Value = edtValue->Text.ToDouble();


double Sinus = sin(Value);
edtValue->Text = Sinus;
}
}
//---------------------------------------------------------------------------

8.7.3 The Tangent Functions

8.7.3.1 The C/C++ tan


double tan(double x);
long double tanl(long double x);

The tan() function calculates the tangent of a number.

In geometry, consider AC the length of A to C. Also consider BC the length of B to C.


The tangent is the result of BC/AB; that is, the rario of BC over AB.

Example: A form contains an Edit control named edtValue. After the user has typed a
value and presses Enter, the OnKeyPress event retrieves the number typed in the edit box,
calculates its tangent and displays the result in the same Edit control:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtValueKeyPress(TObject *Sender, char &Key)
{
if( Key == VK_RETURN )
{
double Value = edtValue->Text.ToDouble();
double Tangent = tan(Value);
edtValue->Text = Tangent;
}
}
//---------------------------------------------------------------------------

209 © FunctionX, Inc.


Windows Events Borland C++ Builder

8.7.3.2 The Arc Tangent Functions

double atan(double x);

The atan() function is used to calculate the arc tangent of a number.

In geometry, consider BC the length of B to C. Also consider AC


the length of A to C. The arc tangent is the ratio of BC/AC.

The atan() function takes one argument, x, that represents the angle BA AC. After the
evaluation, the function returns a double-precision number between –PI/2 and PI/2.

If the number to be evaluated is larger than a double, use the atanl() function:

long double atanl(long double x);

This function takes a long double argument and returns a long double.

210 © FunctionX, Inc.


Windows Events Borland C++ Builder

Chapter 9: Date and Time

211 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.1 Dates
The date and time are at the core of computer use. The date is a unit that measures the
number of years, months, or days elapsed in a specific period. To represent the dates,
computers, applications, and compilers are configured with appropriates techniques. The
C++ Builder compiler counts dates from 12/30/1899 at midnight. With this compiler,
dates and related operations are dealt with using a class called TDateTime. Since this
class is not a control, you can use it with any control that displays text.

The dates used in your applications will mostly be based on the TDateTime class. To
perform most operations in your programs, you will need to know when, how, and where
to use this class. As an object, you will need to declare it.

9.1.1 Declaring a Date


To declare a date value, use one of the TDateTime constructors. The simplest way is to
use the default constructor and provide a valid C++ name. Here is an example:

TDateTime Mine;

If not assigned a value, this variable is initialized to 12/30/1899 at midnight. If you know
the exact date that you want to initialize, you have two alternatives. You can initialize the
variable using a string. Here is an example:

TDateTime Mine("12/05/1990");

This could also be written as:

AnsiString S = "05/04/1988";
TDateTime Mine = S;

You can also provide the integer values of the year, the mont, and the day respectively.
Here is an example:

TDateTime Mine(1990, 11, 26);

To initialize a date, you can also provide an integer that represents the number of days
passed since 1899 to the specified date. Here is and example:

TDateTime Mine = 33895;

9.1.2 The Date() Function


The simplest way to get the date in your application consists of calling the Date()
function. For example, you can use it to display the current date:
• In an Edit control: edtToday->Text = Date();
• On a label: Label1->Caption = Date();
• In a form’s title bar: Form1->Caption = Date();

212 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.2 Date, String, and Numeric Conversions

9.2.1 Converting a String to Date


Unless you are using a special control that recognizes date values, most of the controls
will receive and display text. For this reason, as far as the compiler is concerned, the user
or the client of a control would be supplying text derived from an AnsiString class.
Therefore, before performing any operation on such a text, you will have to convert the
content of the control to a valid date. In the same way, if you want the compiler to
consider a date value as a “normal” string, you would convert the date value into a string.

If the user types a valid date into an edit box, such as 10/4/1988, this is still considered a
string and you would not be able to use it in an operation. To convert a string to a date,
you can use the StrToDate() function. The syntax is:

TDateTime __fastcall StrToDate(const AnsiString S);

This function takes an argument as the string that needs to be converted. The string must
be provided in a recognizable format, following the Regional Settings of the Windows
Control Panel. For example, in the United States, the components of a date are separated
with a forward slash “/”. The typical formats of a date are:

If the string contains an invalid date, the conversion would fail and the program would
throw an error. If the conversion is successful, the function would return a valid date.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm2::btnConvertClick(TObject *Sender)
{
TDateTime Value = StrToDate(edtSource->Text);
edtTarget->Text = Value;
}
//---------------------------------------------------------------------------

213 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.2.2 Converting a Date to a String


The TDateTime and the AnsiString classes are configured to work in harmony and allow
great flexibility. This allows a TDateTime date value to be easily recognized by, and
converted to, an AnsiString string. Unless you are performing detailed formatting, a date
value can be transparenty identified as a string. For this reason, you can display a date
value as a string without any conversion. As an example, when the user clicks a button
named Button1 on a form, the date value of the AfewMonthsAgo variable would display
in an Edit control named Edit1:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime AFewMonthsAgo("04/28/1998");

Edit1->Text = AFewMonthsAgo;
}
//---------------------------------------------------------------------------

An AnsiString string is able to recognize a TDateTime value because the AnsiString is


overloaded in the TDateTime class. Its syntax is;

__fastcall operator AnsiString() const;

The operator AnsiString() function allows any valid TDateTime value to be automatically
converted to a string when needed. You can also explicitly use the function if necessary.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
TDateTime AFewMonthsAgo("04/28/1998");
AnsiString Converted = AFewMonthsAgo.operator AnsiString();
edtResult->Text = Converted;
}
//---------------------------------------------------------------------------

If you have a date value that needs to be converted to a string, you can use the
DateToStr() function. Its syntax is:

AnsiString __fastcall DateToStr(System::TDateTime Date);

This function takes one argument, which is the date value that needs to be converted. If
the argument is not a valid date, the conversion would fail and the program would throw

214 © FunctionX, Inc.


Windows Events Borland C++ Builder

an error (in simple but practical terms, the program would crash). If the conversion is
successful, the function returns a string.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
AnsiString Current = DateToStr(Date());
edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

Alternatively, you can use the TDateTime::DateString() function to convert a valid date
to a string. The syntax of the DateString() method is:

AnsiString __fastcall DateString() const;

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime Today = Date();

AnsiString Value = Today.DateString();


Edit1->Text = Value;
}
//---------------------------------------------------------------------------

9.2.3 Converting a Date to a Double-Precision Number


A TDateTime value can be configured to display as a decimal number. The syntax used
is:

__fastcall operator double() const;

The double data type was overloaded in the TDateTime class to allow converting a
TDateTime variable to a fractional equivalent. The number can be made of two parts. If
the number is round, that is, without a decimal value, it represents the number of days
elapsed since 12/30/1899. If the number has a decimal part, the decimal portion
represents a fraction of the day over a 24-hour period.

The operator double() function can be used to get the number of days and the amount of
time elapsed since 12/30/1899 at midnight and the time of the current date. In the
following example, the difference between the current date an time and 12/30/1899 at
midnight is displayed as a double-precision number in an Edit control of a form when the
form comes up:

//---------------------------------------------------------------------------
void __fastcall TForm2::FormCreate(TObject *Sender)
{
TDateTime RightNow = Now();

double Qty = RightNow.operator double();


Edit1->Text = Qty;

215 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

To convert a TDateTime value to double using the double overloaded operator, declare a
double variable and assign the TDateTime variable to it by calling the operator double()
function. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

TDateTime Diff = End - Start;


double d = Diff.operator double();

edtDifference->Text = d;
}
//---------------------------------------------------------------------------

9.2.4 Converting a Date to an Integer


Like the double data type, the int data type was overloaded in the TDateTime class to
convert a TDateTime value to an integer. The syntax of the function is:

__fastcall operator int() const;

To get the equivalent number of days of a TDateTime value, declare an integer and
assign it the desired TDateTime value by calling the operator int() function. If the
operator is applied on a variable that holds a particular date, the operator int() function
would produce the number of days elapsed since 12/30/1988. In the following example,
the number of days since 12/30/1988 to the current date is displayed in an Edit control
when the user clicks the button:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnShowDaysClick(TObject *Sender)
{
TDateTime Today = Date();
int Days = Today.operator int();

edtDifference->Text = Days;
}
//---------------------------------------------------------------------------

216 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.3 The Computer’s System of Displaying Dates


Your computer and your customer’s uses a set of attributes to display date values. These
are provided or configured in the Regional Settings. To access the Regional Settings, in
Microsoft Windows XP, click Start  Control Panel. From the Control Panel, click Date,
Time, Language, and Regional Options:

From the Date, Time, Language, and Regional Options window, click either Change the
Format of Numbers, Dates, and Times or Regional and Language Options. From the
Regional or Language Options, click the Regional Options property page and click the
Customize button:

217 © FunctionX, Inc.


Windows Events Borland C++ Builder

The computer uses two main categories of date display. These categories are based on the
language used by your computer. For example, most user computers that reside in the
United States use a standard known as US English. This commands how the date displays
in the continental US. Each category uses specific characters to represent its value. The m
or M is used for a month, the d or D is used for a day, and the y or Y is used for the year.

9.3.1 The Short Date Format


The Short Date Format is special string that all applications of your computer refer to in
order to display a date using the numeric version of a date.

The months hold the values 1=January, 2=February, 3=March, 4=April, 5=May, 6=June, 7=July,
8=August, 9=September, 10=October, 11=November, 12=December. Instead on numbers, a month is
represented with the letter m; the computer has the responsibility of finding the right month.

The computer refers to the following characters and it depends on how these characters
are retrieved:

Character Meaning Why use it?


m or M The month displays as a single digit if the Can be used to display May
numeric month is less than 10. as 5 instead of 05
mm or MM The month displays a leading 0 if the Can be used to display May
numeric month is less than 10. as 05 instead of 5
d or D The day displays as a single digit if the day Can be used to display the 8th
of the month is less than 10. of the month as 8 and not 08
dd or DD The day displays a leading 0 if the day of Can be used to display 8th day
the month is less than 10. of the month as 08 and not 8
y, yy, Y, or YY The year displays with two digits like 88 for Used when two digits suffice
1988 to display the year
yyy, YYY, yyyy, YYYY The year displays with 4 digits such as 1988 Used to display all digits for a
and not 88 year

To display a date value, use the syntax:

218 © FunctionX, Inc.


Windows Events Borland C++ Builder

ShortDateFormat = “Format”;

To create a format, assign an appropriate string to the ShortDateFormat variable. After


creating such a format, you can display a date value in the desirede control the same way
you would proceed. Before displaying the date, the compiler would scan the event and
find out what format to apply. Here are examples of displaying individual portions of a
date value:

//---------------------------------------------------------------------------
void __fastcall TfrmDates::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);

ShortDateFormat = "d";
edtd->Text = DateValue;
ShortDateFormat = "dd";
edtdd->Text = DateValue;
ShortDateFormat = "M";
edtM->Text = DateValue;

219 © FunctionX, Inc.


Windows Events Borland C++ Builder

ShortDateFormat = "MM";
edtMM->Text = DateValue;
ShortDateFormat = "y";
edty->Text = DateValue;
ShortDateFormat = "yy";
edtyy->Text = DateValue;
ShortDateFormat = "yyy";
edtyyy->Text = DateValue;
ShortDateFormat = "yyyy";
edtyyyy->Text = DateValue;
}
//---------------------------------------------------------------------------

Besides using any of these characters to display their corresponding portion of a date, you
can also combine these characters to display a semi or complete date. To do this, you will
need a symbol or character that separates the portions of a date. In the US English, the
most common character used to separate the portions of a date is the forward slash “/”.
Another character used is the dash “-“.

Using a set of combinations of the above characters, the operating system proposes a list of possible
formats for date display. To access this list, from the Regional Options property page of the Regional and
Language Options dialog box, you can click the arrow of the Short Date Format combo box. The
combinations are:

Here are examples of displaying the formats specified by the operating system:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);

220 © FunctionX, Inc.


Windows Events Borland C++ Builder

ShortDateFormat = "M/d/yyyy";
edtMdyyyy->Text = DateValue;
ShortDateFormat = "M/d/yy";
edtMdyy->Text = DateValue;
ShortDateFormat = "MM/dd/yy";
edtMMddyy->Text = DateValue;
ShortDateFormat = "MM/dd/yyyy";
edtMMddyyyy->Text = DateValue;
ShortDateFormat = "yy/MM/dd";
edtyyMMdd->Text = DateValue;
ShortDateFormat = "yyyy-MM-dd";
edtyyyyMMdd->Text = DateValue;
ShortDateFormat = "dd-MMM-yy";
edtddMMMyy->Text = DateValue;
}
//---------------------------------------------------------------------------

In the same way, you can create your own formats.

9.3.2 The Long Date Format


The operating system provides a more explicit system of displaying date values. This is
called the Long Date Format and it uses a global variable called LongDateFormat; this
variable is defined in the Regional Options of the Control Panel. When using the
LongDateFormat, there are various types of combinations applied to the characters,
depending on what you are trying to display.

To display the date using the Long Date Format formats, the computer uses the following
combinations:

d: The single d is used to display the numeric day of a month. Each month starts at 1,
then 2, and so on. The month of February can have 28 or 29 days depending on whether
the year is a leap year. The other months have 30 or 31 days. If the day occurs before the
10th, the number would display without the leading 0.
dd: The double d as dd displays the numeric day of the month, from 1 tom 31 depending
on the month and whether it is a leap year for February. If the month occurs before
October, it would display with the leading 0.

M: The single M is used to display the numeric position of the month. January is 1,
February is 2 and December is 12. If the month occurs before October, it would display
without the leading 0.
MM: The double M as MM displays the numeric position of a month from 1 to 12. If the
number is less than 10, it would display with the leading 0.
MMM: The triple M as MMM displays the name of the month using three letters. It uses
a global variable called ShortMonthNames. This variable is defined by the operating
system. By default, the names of the month are Jan, Feb, Mar, Apr, May, Jun, Jul, Aug,
Sep, Oct, Nov, and Dec.
MMMM: The quadruple M as MMMM displays the complete name of a month as
defined as the operating system. The variable used is called LongMonthNames. The
names of the months are January, February, March, April, May, June, July, August,
September, October, November, and December.

Y or YY: The single y or double yy is used to display the numeric year with the last two
digits.
YYY or YYYY: The triple y as yyy or the quadruple one as yyyy is used to display all
four digits of a year.

221 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.4 Using Dates

9.4.1 Displaying Dates


Any control that uses an AnsiString can display a date. From the declarations we have
seen, if you create an initialized date, you can use the DateToStr() function to display it.
If you use a date variable declared with the default construction, the control would
display the first date the compiler can recognize:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime Mine;
Edit1->Text = DateToStr(Mine);
}
//---------------------------------------------------------------------------

If the date is initialized with a valid date value, you can omit the conversion function:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime Mine("12/05/1990");
Edit1->Text = Mine;
}
//---------------------------------------------------------------------------

If you supply the integer values of the variable, the compiler would take care of
displaying the equivalent date:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime Mine(1990, 11, 26);
Edit1->Text = Mine;
}
//---------------------------------------------------------------------------

In the same way, if you initialize the variable with a number of days as an integer, the
compiler would calculate and display the corresponding date;

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime Mine = 33895;
Edit1->Text = Mine;
}
//---------------------------------------------------------------------------

222 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.4.2 Decoding a Date


A date variable declared from the TDateTime class is made of a year, a month, and a day
values. Decoding a date consists of isolating or retrieving these components of a date
value. To perform such an operation, the TDateTime class is equipped with the
DecodeDate() method. Its syntax is:

void __fastcall DecodeDate(unsigned short* year, unsigned short* month, unsigned


short* day) const;

Each component is retrieved using a pointer to an unsigned short. The presence of


pointers allows you to pass “empty” variables whose value would be altered by the
function and returned with new values.

In the following example, the current date is stored in a TDateTime variable. Then the
year, month, and day of the variable are extracted before constructing a sentence to
display on a label:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TDateTime Today = Date();

unsigned short Year, Month, Day;


Today.DecodeDate(&Year, &Month, &Day);

Label1->Caption = "Today is the " + String(Day) +


" of month " + Month +
" of the year " + Year + ".";
}
//---------------------------------------------------------------------------

If you want to display a better English version of the sentence above, you can format the
date components to your liking. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TDateTime Today = Date();
AnsiString Dayth, Monthth;

unsigned short Year, Month, Day;


Today.DecodeDate(&Year, &Month, &Day);

if( Day == 1 )
Dayth = "st";
else if( Day == 2 )
Dayth = "nd";
else if( Day == 3 )
Dayth = "rd";
else
Dayth = "th";

if( Month == 1 )
Monthth = "st";
else if( Month == 2 )
Monthth = "nd";

223 © FunctionX, Inc.


Windows Events Borland C++ Builder

else if( Month == 3 )


Monthth = "rd";
else
Monthth = "th";

Label1->Caption = "Today is the " + String(Day) + Dayth +


" of the " + Month + Monthth +
" month of the year " + Year + ".";
}
//---------------------------------------------------------------------------

The DecodeDate() function comes in two versions. Besides the TDateTime’s, the VCL
provides another version whose syntax is:

void __fastcall DecodeDate(System::TDateTime Date, Word &Year, Word


&Month, Word &Day);

Since this version is class-independent, the first argument you must supply is a
TDateTime value or variable. This time, the year, the month, and the day values are
passed by reference, which also allows the function to return them altered.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDecodeClick(TObject *Sender)
{
TDateTime Typed = StrToDate(edtDate->Text);
Word Year, Month, Day;

DecodeDate(Typed, Year, Month, Day);

edtDay->Text = Day;
edtMonth->Text = Month;
edtYear->Text = Year;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{

224 © FunctionX, Inc.


Windows Events Borland C++ Builder

Close();
}
//---------------------------------------------------------------------------

If you want to get or display the English name of the decoded month, you can write a
conditional switch whose cases would represent the months by their integral position.
You can also declare an AnsiString variable to hold the names of months and retrieve the
necessary one when needed. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDecodeClick(TObject *Sender)
{
TDateTime Typed = StrToDate(edtDate->Text);
Word Year, Month, Day;
AnsiString Months[] = { "",
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December" };

DecodeDate(Typed, Year, Month, Day);

edtDay->Text = Day;
edtMonth->Text = Months[Month];
edtYear->Text = Year;
}
//---------------------------------------------------------------------------

9.4.3 Encoding a Date


Encoding a date consists of supplying the necessary components of a TDateTime to the
compiler to create a valid TDateTime value. The function used to perform this operation
is:

TDateTime __fastcall EncodeDate(Word Year, Word Month, Word Day);

This function takes three positive integers (unsigned short) that represent:

• the year: valid values range from 0 to 9999;


• the month: valid values range from 1 to 12; January is 1, February is 2, etc;
• the day: this could be 28, 29, 30, or 31 depending on the month and whether the
year is a leap year, which controls the number of days for the month of
February.

225 © FunctionX, Inc.


Windows Events Borland C++ Builder

The following form is equipped with four Edit controls named edtDay, edtMonth,
edtYear and edtDate. When the user clicks the Encode button named btnEncode, the
OnClick event retrieves the values of the day, the month, and the year from their
respective edit box. Then the compiler creates a date from those and displays it in the
Date edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEncodeClick(TObject *Sender)
{
Word Day, Month, Year;

Day = edtDay->Text.ToInt();
Month = edtMonth->Text.ToInt();
Year = edtYear->Text.ToInt();

TDateTime Value = EncodeDate(Year, Month, Day);


edtDate->Text = Value;
}
//---------------------------------------------------------------------------

9.4.4 Finding Out the Leap Year


One of the arduous operations performed on dates is to find out out whether the year
value of a date is a leap year. Luckily, the IsLeapYear() function can perform it. The
syntax of this function is:

bool __fastcall IsLeapYear(Word Year);

This function takes an unsigned short integer argument variable and examines it. If the
argument, which must be a valid year number, is a leap year, the function returns true;
otherwise, it would return false. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if( IsLeapYear(Edit1->Text.ToInt()) )
Edit2->Text = "Leap Year";
else
Edit2->Text = "Not";
}
//---------------------------------------------------------------------------

226 © FunctionX, Inc.


Windows Events Borland C++ Builder

The following example starts by requesting a date value from the user using an
InputBox() function. Then the date is decoded to retrieve the year value. The year is
examined to find out whether it is a leap year, using the IsLeapYear() function. The
function displays a message box to show its findings:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnLeapYearClick(TObject *Sender)
{
unsigned short Year, Month, Day;
AnsiString Value =
InputBox("Date and Time", "Enter a date: ", "01/01/1900");

TDateTime Examiner = StrToDate(Value);


Examiner.DecodeDate(&Year, &Month, &Day);
AnsiString LeapYear =
IsLeapYear(Year) ? " is a leap year" : " is not a leap year";

ShowMessage("The date you typed was " + Value + "\n" +


AnsiString(Year) + LeapYear);
}
//---------------------------------------------------------------------------

9.4.5 The Day of the Week


The VCL is equipped with a special function that can be used to retrieve the day of the
week of a given date. The function used is the DayOfWeek() and its syntax is:

int __fastcall DayOfWeek(System::TDateTime Date);

To use this function, pass a TDateTime value or variable to the DayOfWeek() function.
The TDateTime object passed as argument must hold a valid date value. After execution,
the function returns an integer between 1 (included) and 7 (included) that represents the
position of the day. Sunday is referred to as the first day of the week and has a value of 1;
Monday is 2, etc.

Here is an example:

227 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
TDateTime Value = StrToDate(edtDate->Text);
int Day = DayOfWeek(Value);

edtDay->Text = Day;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

Of course, sometimes you will want to get or display the English name of the day. To do
this, you can write a switch conditional statement that would display a name accordingly.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
TDateTime Value = StrToDate(edtDate->Text);
int Day = DayOfWeek(Value);
AnsiString DayName;

switch(Day)
{
case 1:
DayName = "Sunday";
break;
case 2:
DayName = "Monday";
break;
case 3:
DayName = "Tuesday";
break;
case 4:
DayName = "Wednesday";
break;
case 5:
DayName = "Thursday";
break;
case 6:
DayName = "Friday";
break;
case 7:
DayName = "Saturday";
}

edtDay->Text = DayName;
}
//---------------------------------------------------------------------------

228 © FunctionX, Inc.


Windows Events Borland C++ Builder

An alternative would be to declare an array of AnsiString strings to hold the names of the
week days, then retrieve the necessary one using its corresponding position. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
TDateTime Value = StrToDate(edtDate->Text);
int Day = DayOfWeek(Value);
AnsiString DayName[] = { "", "Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday" };

edtDay->Text = DayName[Day];
}
//---------------------------------------------------------------------------

The DayOfWeek() function comes in two versions. Besides the VCL’s, the TDateTime
class also is equipped with this method. Its syntax is:

int __fastcall DayOfWeek() const;

This version does not take an argument. Instead, it is called by a TDateTime variable that
needs it. This function returns an integer that represents the weekly position of the day if
the execution is successful. The equivalent version of the above program would be:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
TDateTime Value = StrToDate(edtDate->Text);
int Day = Value.DayOfWeek();

edtDay->Text = Day;
}
//---------------------------------------------------------------------------

9.4.6 Increasing Months on a Date


The addition operator of the TDateTime class is used to add a number of days to a date
value. If you want to add months to a date value, you can use the IncMonth() function. Its
syntax is:

TDateTime __fastcall IncMonth(const TDateTime Source, int Months);

This function takes two arguments. The first is the date value or variable that serves as
the source or reference to work on. This argument must hold a valid TDateTime date

229 © FunctionX, Inc.


Windows Events Borland C++ Builder

value; otherwise the execution would fail. The second argument, Months is an integer
that represents the number of months to be added to the first argument. If the addition is
successful, the IncMonth() function returns a new TDateTime value.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtMonthsExit(TObject *Sender)
{
TDateTime StartDate = edtStartDate->Text;
int Months = edtMonths->Text.ToInt();

TDateTime NextPeriod = IncMonth(StartDate, Months);

edtNextPeriod->Text = NextPeriod;
}
//---------------------------------------------------------------------------

The IncMonth() is used to both add and subtract months from a date. To subtract
months, pass the Months argument with a negative value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtMonthsExit(TObject *Sender)
{
TDateTime StartDate, NextPeriod;
int Months;

if(edtMonths->Text != "")
{
StartDate = edtStartDate->Text;
Months = edtMonths->Text.ToInt();
NextPeriod = IncMonth(StartDate, Months);
edtNextPeriod->Text = NextPeriod;
}
else
edtNextPeriod->Text = edtStartDate->Text;
}
//---------------------------------------------------------------------------

9.4.7 Replacing a Date


void __fastcall ReplaceDate(TDateTime &Target, const TDateTime Source);

230 © FunctionX, Inc.


Windows Events Borland C++ Builder

The ReplaceDate() function allows replacing one date with another. On the function, the
Target argument is the new date whose value needs to be replaced by that of the Source
argument. Since the starting point of the TDateTime class is on 12/30/1899, if the Source
argument occurs before that the date, the ReplaceDate() function takes care of reconciling
the negative date. Here is an example of using the function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnReplaceClick(TObject *Sender)
{
TDateTime Original = StrToDate(edtOriginal->Text);
TDateTime Replacement;

ReplaceDate(Replacement, Original);
edtReplacement->Text = DateToStr(Replacement);
}
//---------------------------------------------------------------------------

9.5 Comparison Operations on Dates


The TDateTime class was configured with many arithmetic and comparison operators.
These are used on date values allowing you to use TDateTime variables as if they were
regular variables.

9.5.1 The Comparison for Equality


To find out whether two data values are the same, simply apply the Equality operator on
their values. Once you have two TDateTime values or variables, the compiler is
configured to perform this comparison.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if(Start == End)
pnlComparison->Caption = "Both dates are the same";
else
pnlComparison->Caption = "Those are different dates!";
}
//---------------------------------------------------------------------------

231 © FunctionX, Inc.


Windows Events Borland C++ Builder

This comparison is possible because the Equality operator “==” was overloaded in the TDateTime class. Its
syntax is:

bool __fastcall operator ==(const TDateTime& Target) const;

To compare two dates using the overloaded Equality operator, call the operator==() on
the desired date and supply the argument date value that is being compared against ar the
Target. The above could have been written:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start.operator ==(End) )


pnlComparison->Caption = "Both dates are the same";
else
pnlComparison->Caption = "Those are different dates!";
}
//---------------------------------------------------------------------------

9.5.2 The Comparison for Inequality


To find out whether two data values are not the same, simply apply the inequality
operator on their values. Once you have two TDateTime values or variables, the compiler
is configured to perform this comparison.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start != End )


pnlComparison->Caption = "Those are different dates!";
else
pnlComparison->Caption = "Both dates are the same";
}
//---------------------------------------------------------------------------

232 © FunctionX, Inc.


Windows Events Borland C++ Builder

This comparison is possible because the inequality operator “!=” is overloaded in the TDateTime class. Its
syntax is:

bool __fastcall operator !=(const TDateTime& Target) const;

To compare two dates using the overloaded inequality operator, call the operator==() on
the desired date and supply the argument date value that is being compared against ar the
Target. The above could have been written:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start.operator !=(End) )


pnlComparison->Caption = "Those are different dates!";
else
pnlComparison->Caption = "Both dates are the same";
}
//---------------------------------------------------------------------------

9.5.3 The Comparison for Inferiority


To find if Source date occurs prior to a Target date, apply the “less than” comparison operator. To do this,
use the operator as if both date values were normal integral or floating-point values. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start < End )


pnlComparison->Caption = DateToStr(Start) + " occurs prior to " +
DateToStr(End);
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

233 © FunctionX, Inc.


Windows Events Borland C++ Builder

Alternatively, you can use the overloaded “less than” operator to find out when one date
is less than another. The syntax used is:

bool __fastcall operator <(const TDateTime& Target) const;

To perform the above “less than” comparison, you could implement the event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start.operator<(End) )
pnlComparison->Caption = DateToStr(Start) + " occurs prior to " +
DateToStr(End);
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

9.5.4 The Comparison for Inferiority or Equality


Two TDateTime values can be compared to find out whether they are the same or if a source date occurs
prior to a target date. To perform this comparison, apply the “less than or equal” operator as if the values
were regular integer or floating-points.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start <= End )


pnlComparison->Caption = "Your film will be ready after 5 O'Clock";
else
pnlComparison->Caption = "Wrong date sequence";
}
//---------------------------------------------------------------------------

This comparison operator is useful because the “less than or equal to” operator “<=” was
overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator <=(const TDateTime& Target) const;

234 © FunctionX, Inc.


Windows Events Borland C++ Builder

Using the <= overloaded operator, The comparison in the above event could have been
written as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start.operator <=(End) )


pnlComparison->Caption = "Your film will be ready after 5 O'Clock";
else
pnlComparison->Caption = "Wrong date sequence";
}
//---------------------------------------------------------------------------

9.5.5 The Comparison for Superiorty


To find if a source date occurs after a target date, apply the “greater than” comparison operator. This
operator is used the same way you would for a regular integer or a floating-point values. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start > End )


pnlComparison->Caption = DateToStr(Start) + " occurs after " +
DateToStr(End);
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

This “greater than” comparison between two date values is possible because its operator
was overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator >(const TDateTime& Target) const;

Using the overloaded operator, the previous event could have been implemented as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)

235 © FunctionX, Inc.


Windows Events Borland C++ Builder

{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start.operator >(End) )


pnlComparison->Caption = DateToStr(Start) + " occurs after " +
DateToStr(End);
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

9.5.6 The Comparison for Superiority or Equality


Two TDateTime values can be compared to find out whether they are the same or if a source date occurs
after a target date. To perform this comparison, apply the “greater than or equal” operator as if the values
were regular integer or floating-points.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start >= End )


pnlComparison->Caption = "Testing for ""\"Greater Than Or Equal To""\"";
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

Using this comparison, you can validation an intermediary operation. Even after finding
out whether the first date is greater than or equal to the second, you can further refine
your comparison inside of the comparison. In the following example, a message box
displays if the “greater than or equal to” comparison returns false:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start >= End )


{
pnlComparison->Caption = "Testing for ""\"Greater Than Or Equal To""\"";
if( Start > End )
ShowMessage(DateToStr(Start) + " occurs after " + DateToStr(End));
else if( Start == End )
ShowMessage("Both dates occur at the same time");
}
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

236 © FunctionX, Inc.


Windows Events Borland C++ Builder

This comparison operator is useful because the “greater than or equal to” operator “<=”
was overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator >=(const TDateTime& Target) const;

To perform the comparison in the above event using the <= overloaded operator, call the
operator>=() method on the source date value and include the compared date as the
Target argument. The above event could be written as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

if( Start.operator >=(End) )


{
pnlComparison->Caption = "Testing for ""\"Greater Than Or Equal To""\"";
if( Start > End )
ShowMessage(DateToStr(Start) + " occurs after " + DateToStr(End));
else if( Start == End )
ShowMessage("Both dates occur at the same time");
}
else
pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

9.6 Operations on Dates


The TDateTime and other VCL functions allow you to perform various types of
operations on a date value. The TDateTime class is very sophisticated, especially when
copled with the Sysutils functions. Almost all types of operations and all types of
comparisons are possible. All arithmetic and all logic comparison operators were
overloaded to permit as much flexibility as possible. Some of the operations are possible
directly on date values. When not possible or difficult, the decoder and encoder functions
can be used to let the compiler work behind the scenes.

9.6.1 Assigning One Date to Another


To assign one date to another, simply use the assignment operator “=” as if the variables
were regular values. In the following example, the user enters a starting date in an Edit
control and finds out the number of days a customer of a car rental wants to keep the car.
The clerk enters this value in the # of Days edit box. When the clerk clicks somewhere
else, that is, when the edit box loses focus, the content of the edit box is checked. If the
number of days is 1 or less, which means the customer wants the car for only one day, the
first date is assigned to a second TDateTime variable and displays in the End Date edit
box:

237 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::edtNbrOfDaysExit(TObject *Sender)
{
TDateTime Start, End;
int NbrOfDays;

Start = StrToDate(edtStartDate->Text);
NbrOfDays = StrToInt(edtNbrOfDays->Text);

if(NbrOfDays <= 1)
{
End = Start;
edtEndDate->Text = End;
}
else
{
edtEndDate->Text = "";
edtEndDate->SetFocus();
}
}
//---------------------------------------------------------------------------

Alternatively, the TDateTime has the assignment operator overloaded to allow assigning
a date variable to another. The syntaxes of the function are:

TDateTime& __fastcall operator =(const TDateTimeBase& rhs);


TDateTime& __fastcall operator =(const TDateTime& rhs);
TDateTime& __fastcall operator =(const double rhs);
TDateTime& __fastcall operator =(const int rhs);

To assign one date to another using the operator =() function, use a valid TDateTime
value or declare a TDateTime variable and call the operator=() overloaded function by
supplying the intended target TDateTime variable. The above event could be rewritten as;

//---------------------------------------------------------------------------
void __fastcall TForm1::edtNbrOfDaysExit(TObject *Sender)
{
TDateTime Start, End;
int NbrOfDays;

Start = StrToDate(edtStartDate->Text);
NbrOfDays = StrToInt(edtNbrOfDays->Text);

if(NbrOfDays <= 1)
{
End.operator =(Start);
edtEndDate->Text = End;

238 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
else
{
edtEndDate->Text = "";
edtEndDate->SetFocus();
}
}
//---------------------------------------------------------------------------

9.6.2 Adding Values to a Date


To add a number of days to a TDateTime value, simply add an integer to the intended
date value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAdditionClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);

TDateTime Addition = Start + 5;

edtAddition->Text = Addition;
}
//---------------------------------------------------------------------------

You can also get the number of days from the user by using another control on the
application. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEstimateClick(TObject *Sender)
{
TDateTime DepositDate = edtDepositDate->Text;
int Days = edtDays->Text.ToInt();
TDateTime PickupDate = DepositDate + Days;

edtPickupDate->Text = PickupDate;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::btnCloseClick(TObject *Sender)


{
Close();

239 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

The addition operation is possible on a date value because its operator is overloaded in
the TDateTime class. The TDateTime class provides a mechanism of adding a number of
days to a date value. The syntaxes of the overloaded operator are:

TDateTime __fastcall operator +(const TDateTimeBase& rhs) const;


TDateTime __fastcall operator +(const TDateTime& rhs) const;
TDateTime __fastcall operator +(const double rhs) const;
TDateTime __fastcall operator +(const int rhs) const;

When applied to a TDateTime value, the addition operator “+” adds a number of days to
a date. If the number added exceeds the end of year, the class will calculate and encode a
date that corresponds to the date of the subsequent year:

To add a number of months to a date value, decode the date to retrieve its year, month,
and day values. Add the intended number of months to your date and re-encode the date.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAdditionClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtDate->Text);
int Months = StrToInt(edtValue->Text);
unsigned short Year, Month, Day;

Start.DecodeDate(&Year, &Month, &Day);


TDateTime End(Year, Month+Months, Day);
edtResult->Text = DateToStr(End);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{

240 © FunctionX, Inc.


Windows Events Borland C++ Builder

Close();
}
//---------------------------------------------------------------------------

To add a number of years to a date value, decode it to extract the year, month, and day
values. Add the integral number of years to the source year. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAdditionClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtDate->Text);
int Years = StrToInt(edtValue->Text);
unsigned short Year, Month, Day;

Start.DecodeDate(&Year, &Month, &Day);


TDateTime End(Year+Years, Month, Day);
edtResult->Text = DateToStr(End);
}
//---------------------------------------------------------------------------

9.6.3 Assigning an Added Date


You can add a value to a date variable and assign the new value to the original date. This
is the same as using the += operator. The syntaxes used for this operator are:

TDateTime& __fastcall operator +=(const TDateTimeBase& rhs);


TDateTime& __fastcall operator +=(const TDateTime& rhs);
TDateTime& __fastcall operator +=(const double rhs);
TDateTime& __fastcall operator +=(const int rhs);

To add an number of days to an existing date value, you can use the += operator as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
TDateTime OneDay = StrToDate(edtDate->Text);
TDateTime Added;
OneDay += 5;
edtResult->Text = DateToStr(OneDay);
}
//---------------------------------------------------------------------------

241 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.6.4 Subtracting Dates


To get the number of days between two dates, perform the subtraction operation on their
values. To do this, you can declare a double precision number or an integer that would
store the subtracted number from the later date to the earlier. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);
int Diff = End - Start;

edtDifference->Text = Diff;
}
//---------------------------------------------------------------------------

To get the difference of years between two dates, apply the subtraction operator on their
values to get the integral number of days. Then divide this number by 365. This
difference produces the number of years in ranges of 365 days. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);
int Years = End - Start;
edtYears->Text = (Years / 365);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

As an alternative, you can decode both dates and subtract their year values; this would
produce the difference of years with regards to the years, not the real dates. For example,

242 © FunctionX, Inc.


Windows Events Borland C++ Builder

the difference between 12/31/2001 and 01/01/2002 would produce a year. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);
unsigned short StartYear, StartMonth, StartDay,
EndYear, EndMonth, EndDay;

Start.DecodeDate(&StartYear, &StartMonth, &StartDay);


End.DecodeDate(&EndYear, &EndMonth, &EndDay);

int Years = EndYear - StartYear;


edtYears->Text = Years;
}
//---------------------------------------------------------------------------

To get the difference of months between two dates, perform the subtraction operator on
their values to get the number of days elapsed and divide the result by 30. This would
produce a number of months. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

int Months = End - Start;


edtYears->Text = Months / 30;
}
//---------------------------------------------------------------------------

The subtraction operation is possible on TDateTime values because the subtraction


operator “-“ is overloaded in the TDateTime class as follows:

TDateTime __fastcall operator -(const TDateTimeBase& rhs) const;


TDateTime __fastcall operator -(const TDateTime& rhs) const;
TDateTime __fastcall operator -(const double rhs) const;
TDateTime __fastcall operator -(const int rhs) const;

The subtraction operator “-“ is overloaded in the TDateTime class to allow getting the
difference of days, that is, the elapsed number of days between two dates. The subtraction
is performed as Date2 – Date1. In this case, if Date2 occurs after Date1, the result would
be a positive number; otherwise a negative value would indicate that Date2 occurs before
Date1.

You can also use the operator int() overloaded function to get the difference of days
between two dates. To do this, declare an integer that stores the subtracted number
between two TDateTime dates. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
TDateTime Start = StrToDate(edtStart->Text);
TDateTime End = StrToDate(edtEnd->Text);

243 © FunctionX, Inc.


Windows Events Borland C++ Builder

TDateTime Diff = End - Start;


int Days = Diff.operator int();

edtDifference->Text = Days;
}
//---------------------------------------------------------------------------

9.6.5 Assigning a Subtracted Date


The -= operator is used to subtract a number of days from a date and assign the new value
to the date (whose value has been subtracted). This operation is performed using the
overloaded -= operator that uses the following syntaxes:

TDateTime& __fastcall operator -=(const TDateTimeBase& rhs);


TDateTime& __fastcall operator -=(const TDateTime& rhs);
TDateTime& __fastcall operator -=(const double rhs);
TDateTime& __fastcall operator -=(const int rhs);

To subtract a number of days from a date, you can use the subtraction operator. To assign
the subtracted value to the original date, use the -= operator. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
int IntValue = StrToInt(edtSubtract->Text);

DateValue -= IntValue;
edtResult->Text = DateToStr(DateValue);
}
//---------------------------------------------------------------------------

9.6.6 Decrementing a Date


To decrement a date value, declare a TDateTime variable and apply the – operator on its
value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
static TDateTime Start = StrToDate(edtStartDate->Text);
edtStartDate->Text = Start--;
}

244 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

The TDateTime class allows subtracting one day from a TDateTime value. This is done
using the overloaded decrement operator whose syntaxes are:

TDateTime& operator --();


TDateTime operator --(int);

To decrement a date value using the -- overloaded operator, you have two options. To use
the pre-decrement operator, as if you were using “--Value”, call the operator--() function.
This would apply the operator before recalling the variable. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
static TDateTime Start = StrToDate(edtStartDate->Text);
edtStartDate->Text = Start.operator --();
}
//---------------------------------------------------------------------------

To use the post-increment operator, which is the same as “Value--“, in which case the
statement is called before being incremented, use the operator--(int) method. The int
argument is not specific but you must supply it. Therefore, type any integer number
between the parentheses. Remember that the argument supplied is not the decrementing
value; it is only a “witness” but it is necessary. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
static TDateTime Start = StrToDate(edtStartDate->Text);
edtStartDate->Text = Start.operator --(2);
}
//---------------------------------------------------------------------------

9.6.7 Incrementing a Date


To increment a date value, declare a TDateTime variable and use the ++ operator on its
value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnIncrementClick(TObject *Sender)
{
static TDateTime Original = StrToDate(edtDate->Text);
edtIncremented->Text = Original++;
}
//---------------------------------------------------------------------------

The TDateTime class allows you to add one day from a TDateTime value. This is done
using the overloaded increment operator with the following syntaxes:

245 © FunctionX, Inc.


Windows Events Borland C++ Builder

TDateTime& operator ++();


TDateTime operator ++(int);

To apply the pre-increment operator, as if you were using “++Value”, call the
operator++() function. This would apply the operator before recalling the variable. Here
is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnIncrementClick(TObject *Sender)
{
static TDateTime Original = StrToDate(edtDate->Text);
edtIncremented->Text = Original.operator ++();
}
//---------------------------------------------------------------------------

To use the post-increment operator, which is the same as “Value++“, in which case the
statement is called before being incremented, use the operator++(int). The int argument
is not specific but you must supply it. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnIncrementClick(TObject *Sender)
{
static TDateTime Original = StrToDate(edtDate->Text);
edtIncremented->Text = Original.operator ++(12);
}
//---------------------------------------------------------------------------

This was the opening dialog box: This was performed after the first click:

9.7 Formatting and Controlling the Display of Dates


The TDateTime class and the VCL provide special functions that can be used to control
how the date values display in your application. Calling one of these functions, a date can
use almost any format you see fit or any that makes your application user-friendly.

To control how a date value displays, the TDateTime class uses the FormatString()
method. Its syntax is:

AnsiString __fastcall FormatString(const AnsiString& format);

The TDateTime::FormatString() method takes a string argument that specifies what


format to apply. After formatting the date value, the method returns an AnsiString string.

Alternatively, the VCL has its own function that performs the same operation. Its syntax
is:

246 © FunctionX, Inc.


Windows Events Borland C++ Builder

AnsiString __fastcall FormatDateTime(const AnsiString Format,


System::TDateTime DateValue);

The FormatDateTime() function takes two arguments. The Format argument is a string
that specifies how the date should be formatted. Since this function is not part of the
TDateTime class, it needs a valid TDateTime date value to work on; that is the role of the
DateValue argument.

9.7.1 The Default Display


The default format used by both the TDateTime::FormatString() and the
FormatDateTime() functions conforms to the ShortDateFormat of the Windows
Control Panel. For these functions, that format is represented by the “c” string. You can
still use it explicitly. For the TDateTime::FormatString() method, an example would
be:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime DateValue("10/22/2001");
Edit1->Text = DateValue.FormatString("c");
}
//---------------------------------------------------------------------------

A similar example applied on the FormatDateTime() function would be:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime DateValue("10/22/2001");
Edit1->Text = FormatDateTime("c", DateValue);
}
//---------------------------------------------------------------------------

9.7.2 Displaying the Numeric Day


The days of months are numbered from 1 to 31, depending on the month. The formatting
functions represent each of these days with the “d” format. Here is an example used for
the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatStringClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("d");
}
//---------------------------------------------------------------------------

This would produce:

247 © FunctionX, Inc.


Windows Events Borland C++ Builder

The implementation of this format using the FormatDateTime() function is:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatDateTimeClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatDateTime->Text = FormatDateTime("d", DateValue);
}
//---------------------------------------------------------------------------

When the day has a numeric value that is less than 10, the default “c” and the “d” formats
display its value without the leading 0. To display the leading 0 as in 02 or 08, use the
“dd” format. Here is an example implemented using the TDateTime::FormatString()
method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("dd");
}
//---------------------------------------------------------------------------

Using the FormatDateTime() function, you could have written the same event as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = FormatDateTime("dd", DateValue);
}
//---------------------------------------------------------------------------

9.7.3 Displaying Weekday Names


The names of the week use two formats: 3 letters or full name. To display a name with 3
letters, use the “ddd” format. The names will be Sun, Mon, Tue, Wed, Thu, Fri, or Sat.
Here is an example using the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);

248 © FunctionX, Inc.


Windows Events Borland C++ Builder

edtFormatString->Text = DateValue.FormatString("ddd");
}
//---------------------------------------------------------------------------

The same event using the FormatDateTime() function would be written as:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = FormatDateTime("ddd", DateValue);
}
//---------------------------------------------------------------------------

To display the weekday and the numeric day of the month, you can create a format that
combines both strings. When creating this string, the format must be separated inside the
string so the compiler would know which format to apply and where. To separate the
formats, you can use (almost) any character but you should conform to those used in your
regional settings. One of the most regularly used separators on dates is the comma but the
simplest separator is an empty space. Here is an example (using the
TDateTime::FormatString() method):

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("ddd dd");
}
//---------------------------------------------------------------------------

To display the complete name of a weekday, use the “dddd” format string. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("dddd");
}
//---------------------------------------------------------------------------

You can also display the weekday followed by the numeric day of the month. Here is an
example that uses the FormatDateTime() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);

249 © FunctionX, Inc.


Windows Events Borland C++ Builder

edtFormatString->Text = FormatDateTime("dddd dd", DateValue);


}
//---------------------------------------------------------------------------

9.7.4 Displaying Numeric Months


Months are displayed using two categories: a number or a name.

To display the numeric range of a month, use the “m” format. The months are numbered
as follows: 1=January, 2=February, 3=March, 4=April, 5=May, 6=June, 7=July,
8=August, 9=September, 10=October, 11=November, and 12=December. Here is an
example that displays the numeric month of a date, using the
TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("m");
}
//---------------------------------------------------------------------------

Following the rules we applied to display a combination of a weekday and a month’s


numeric day, you can display a month day and the month’s numeric value. This time,
instead of an empty space, you should use a character that would indicate that the date is
displaying a combination of month and day (or day and month). The best character to
use is the one that conforms to the regional settings of your computer. In the United
States’ English, this would be the forward slash “/”. Here is an example that uses the
FormatDateTime() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = FormatDateTime("m/dd", DateValue);
}
//---------------------------------------------------------------------------

In the same way you can combine a weekday short name followed by the combination of
day/month (or month/day) as you see fit. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = FormatDateTime("ddd m/dd", DateValue);
}
//---------------------------------------------------------------------------

This would produce:

250 © FunctionX, Inc.


Windows Events Borland C++ Builder

When using the “m” format, if the number of the month is less than 10, the compiler
would display it as 1, 2, 3, 4, 5, 6, 7, 8 or 9, without the leading 0. If you want to display
the leading zero for a month between 1 and 9, as 01 or 07, use the “mm” format. Here is
an example with the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("mm");
}
//---------------------------------------------------------------------------

You can also use this format when constructing a combined date:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("dddd, mm/dd");
}
//---------------------------------------------------------------------------

9.7.5 Displaying Months Names


You can display a month by its name using one of two formats: short or long name. The
short names of months are: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, and
Dec. To display a month with one of these names, use the “mmm” format. The following
example uses the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("mmm");
}
//---------------------------------------------------------------------------

This time, the name of the month would become more explicit in a combined format,
allowing the application to be more explicit. To create such a combined date, apply the
rules we have reviewed so far. The following TDateTime::FormatString()
implementation displays a date as short weekday-day-short month name combination:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{

251 © FunctionX, Inc.


Windows Events Borland C++ Builder

TDateTime DateValue = StrToDate(edtDate->Text);


edtFormatString->Text = DateValue.FormatString("ddd dd mmm");
}
//---------------------------------------------------------------------------

You can also use a comma and space to separate the name of the weekday from the other
components. The following event uses the FormatDateTime() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = FormatDateTime("dddd, dd mmm", DateValue);
}
//---------------------------------------------------------------------------

To display a complete name of a month, use the “mmmm” format. The name would
display as one of the following: January, February, March, April, May, June, July,
August, September, October, November, and December; confirming to the Regional
Settings of your computer. Here is an example that uses the
TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
AnsiString Formatter = "ddd, d mmmm";
edtFormatString->Text = DateValue.FormatString(Formatter);
}
//---------------------------------------------------------------------------

Another implementation that uses the FormatDateTime() function can display the
weekday-day-month combination with an empty space as the separator:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
AnsiString Formatter = "dddd, dd mmmm";
edtFormatString->Text = FormatDateTime(Formatter, DateValue);

252 © FunctionX, Inc.


Windows Events Borland C++ Builder

}
//---------------------------------------------------------------------------

9.7.6 Displaying the Year


A year value can be displayed using 2 or 4 digits. To display a year value as a number
between 00 and 99, use the “y” or the “yy” formats as follows (this event uses the
TDateTime::FormatString() method):

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("y");
}
//---------------------------------------------------------------------------

To make the displays we have used so far a little more explicit, you can include the year
value in a combined date string, as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("ddd dd mmm yy");
}
//---------------------------------------------------------------------------

Therefore, you can apply any combination of the formats we have used so far to display a
date, as illustrated in the following FormatDateTime() function call:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
AnsiString Formatter = "dddd dd mmmm yy";
edtFormatString->Text = FormatDateTime(Formatter, DateValue);
}
//---------------------------------------------------------------------------

A year value represented with two digits is hardly explicit, unless you have a good reason
for using it. The alternative is to use all four digits to display a year. This format is
created with the “yyy” or the “yyyy” strings. Here is an example with the
TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
edtFormatString->Text = DateValue.FormatString("yyy");
}
//---------------------------------------------------------------------------

Since this format would be the only one with four digits in a combined string, it makes a
date easier to read. Once again, you can apply the rules we have used so far, to create and
display a combined date. The default format used by Microsoft Windows for the English

253 © FunctionX, Inc.


Windows Events Borland C++ Builder

language is as Sunday, January 27, 2002. You can use the TDateTime::FormatString()
method to create such a format as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
AnsiString Formatter = "dddd, mmmm dd, yyyy";
edtFormatString->Text = DateValue.FormatString(Formatter);
}
//---------------------------------------------------------------------------

Using these rules, you can display a date as you wish. The following FormatDateTime()
function display a date differently than the event above:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
TDateTime DateValue = StrToDate(edtDate->Text);
AnsiString Formatter = "dddd d mmmm yyyy";
edtFormatString->Text = FormatDateTime(Formatter, DateValue);
}
//---------------------------------------------------------------------------

9.8 Doing Time


The time is a unit that measures the number of hours, minutes, or seconds that divide a
day. A day is made of 24 non-spatial divisions called hours. An hour is made of 60 parts
called minutes and a minute is made of 60 seconds.

As done with dates, most of the operations performed on time values are centered around
the TDateTime class. This class is based on a double-precision number initialized at 0.00.
The constant 0.00 corresponds to 12/30/1899 at midnight. A double-precision number is
made of two sections: an integer part and a decimal side. The integral part is a natural
number with no decimal value, such as 8, 1450, or 32. For the TDateTime class, the
integral section represents the number of days that have elapsed since 12/30/1899.

On a double-precision number, such as 204.58, the decimal part starts with a period “.”
and is made of all digits on the right side of the period. For the TDateTime class, the
decimal part represents the number of seconds that have elapsed since midnight.

By default, the compiler refers to the Regional Settings of your computer to display the
time, separating it in hour, minute, second, and AM/PM. The default symbol to separate
the hour and the minute, or the minute and the second is “:”. To separate the seconds and
the AM/PM, the compiler leaves a one-character empty space between them.

254 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.8.1 Declaring Time Variables


The time portion of a TDateTime object can be declared and manipulated as a value. To
declare time variables, you will use one of the constructors of the TDateTime class. If
you declare a variable using the default constructor, as TDateTime TimeValue, the time
will be initialized to midnight or 12:00:00 AM.

The time in regular value is a floating number that ranges from 0 included to 1 excluded.
More precisely, the time is a value defined as follows:

0 >= Time >= 0.99999

The 0 constant represents midnight while the 0.99999 double-precision number


represents 12:59:59 PM. In between, 0.50 represents 12:00:00 PM (noon time), 0.325
represents 7:48:00 AM, and 0.738 represents 5:42:43 PM.

To declare a time variable, use the TDateTime class and specify the name for the
variable. Here is an example:

TDateTime Mine;

If not assigned a valued, this variable is initialized at midnight or 12:00:00 AM. You can
display its value in an Edit control as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeValue;
Edit1->Text = TimeValue;
}
//---------------------------------------------------------------------------

You can initialize a time value with a double-precision number between 0.00000 and
0.99999. Here is an example:

TDateTime Value = 0.2185;

Such an initialization is the same as:

TDateTime Value(0.2185);

You can also get the value from an intermediary action or request it from the user. This
allows you, if necessary, to convert any floating-point number to a time value, as follows:

You can also use an independent floating-point number to initialize a time variable. Here
is an example:

255 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTimeClick(TObject *Sender)
{
double Number = edtNumber->Text.ToDouble();
TDateTime TimeValue = Number;

edtTime->Text = TimeValue;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

Still using the default constructor, if you know the time you want to initialze a variable
with, you can provide it. To do that, declare an instance of the TDateTime constructor
and type the time value between the double-quotes of the parentheses. If the time is
known only for the hour(s) and the minute(s), you can initialize it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeValue("08:22");
Label3->Caption = TimeValue;
}
//---------------------------------------------------------------------------

When using this formula, the hour value must be between 0 and 23. Any other value
outside of this range will cause an error. The minute value must range from 0 to 59;
otherwise, an error would be thrown. If the hour portion has a value between 0 and 11:59,
the time is set in the morning with the AM in the AM/PM section. If the hour portion is
between 12 and 23, the time is set in the afternoon. When displaying it, the compiler, by
default, calculates and displays the 0 to 12 portion and then displays PM in the AM/PM
section.

You can also initialize a time value using the Hour:Minute:Second formula as a string.
Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeValue("20:22:52");
Label3->Caption = TimeValue;
}
//---------------------------------------------------------------------------

Once again, in the absence of an AM/PM section, the compiler would consider the hour
portion to evaluate whether the time occurs in the morning or in the afternoon. The value
of the seconds must be between 0 and 59; otherwise, an error will be thrown.

You can also initialize a time value by specifying the AM/PM portion as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

256 © FunctionX, Inc.


Windows Events Borland C++ Builder

TDateTime TimeValue("10:22:52 AM");


Label3->Caption = TimeValue;
}
//---------------------------------------------------------------------------

The AM and the PM can be in uppercase or lowercase. In otherwords the AM/PM portion
can be represented as AM, Am, aM, am, PM, Pm, pM, or pm. Only the characters A and
P (uppercase or lowercase) are accepted as the first character. Only the M or m characters
are accepted as the second character. Any other combination or other character will cause
an error.

If you know the values of the hour, the minute, the second, and the millisecond, you can
use them to initialize a time variable. To do this, you must supply the arguments in order
following the constructor:

__fastcall TDateTime(unsigned short Hour, unsigned short Minute, unsigned short


Second, unsigned short Millisecond);

The hour value must be between 0 and 23. The minutes must be between 0 and 59. The
Second argument must have a value between 0 and 59. Whenever the seconds are not
important to represent the time, provide their value as 0. The milliseconds must range
from 0 to 999. If you do not know the millisecond value, provide it as 0. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeValue(8, 20, 42, 605);
ShowMessage("The time considered is " + TimeValue);
}
//---------------------------------------------------------------------------

Since a double-precision number has a decimal section that represents the time of the
day, you can assign such a value to a TDateTime variable to initialize a time value. If the
integral part of the value is greater than 0, it would represents the number of days. If it is
0, only the time would be recognized as a fraction of the day. Using this, you can initia
The integral part is section y number

9.8.2 The Time() Function


To get or display the time on your application, you can use the Time() function. You can
display it on:
• An edit box: edtTime->Text = Time();
• A label: lblCurrent->Caption = “Now is the time: “ + Time();
• A panel: pnlTime->Caption = “At this time, we have “ + Time();

9.8.3 Converting a String to Time


To convert a string to a time value, use the StrToTime() function whose syntax is:

TDateTime __fastcall StrToTime(const AnsiString S);

257 © FunctionX, Inc.


Windows Events Borland C++ Builder

This function takes a string as argument. The string must be in a in a valid time format,
following the Regional Rettings of the Control Panel. For example, in the United States,
the components of a time are separated with a colon “:”. The typical formats of a time
are:

If the string contains an invalid date, the conversion would fail and the program would
throw an error. If the conversion is successful, the function returns a valid time. Here is
an example:

//---------------------------------------------------------------------------
void __fastcall TForm2::btnConvertClick(TObject *Sender)
{
TDateTime Value = StrToTime(edtSource->Text);
edtTarget->Text = Value;
}
//---------------------------------------------------------------------------

9.8.4 Converting a Time Value to a String


A time value is, default, recongnized and treated as a string whenever necessary. This
flexibility allows you to perform transparent conversions from a time variable to a string
value. Therefore, it perfectly legimate to write the following assignment:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeValue("22:32:58");
AnsiString Right = TimeValue;

Edit1->Text = Right;
}
//---------------------------------------------------------------------------

This conversion is possible because the AnsiString constructor is overloaded in the


TDateTime class. Its syntax is:

__fastcall operator AnsiString() const;

Therefore, to convert a time value to a string, you can simply assign the time to a string
variable. You can also explicity call the overloaded AnsiString as follows:

258 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime StartTime("9:05:00 AM");
AnsiString ToDisplay = StartTime.operator AnsiString();

Edit1->Text = ToDisplay;
}
//---------------------------------------------------------------------------

The TDateTime class is also equipped with a method that can be used to convert a time
value to a string when necessary. The syntax used is:

AnsiString __fastcall TimeString() const;

To convert a time value to a string, declare a TDateTime variable and call the
TimeString() method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeValue("22:32:58");
AnsiString ToDisplay = TimeValue.TimeString();

Edit1->Text = ToDisplay;
}
//---------------------------------------------------------------------------

Alternatively, to convert a time value to a string, you can use the TimeToStr() function.
Its syntax is:

AnsiString __fastcall TimeToStr(System::TDateTime Date);

This function takes one argument, which is the time value that needs to be converted. If
the argument is not a valid time value, the conversion would fail and the program would
throw an error. If the conversion is successful, the function returns an AnsiString value.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
AnsiString Current = TimeToStr(Time());
edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

9.8.5 Converting a Time Value to a Double-Precision Number


A TDateTime time value is a number that represents a fraction of the day on a 24-hour
basis. This is quite helpful in algebraic operation related assignments.

To convert a time value to a double-precision number, simply cast the time value to a
double. In the following example, the current time is converted to double and displayed
in an edit box when the user clicks a button on a form:

259 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeX = Time();
double Value = double(TimeX);
Edit1->Text = Value;
}
//---------------------------------------------------------------------------

The conversion of a time value to a double-precision number is possible because the


double data type was overloaded in the TDateTime to allow this conversion. The syntax
of the function used is:

__fastcall operator double() const;

You can use this function transparently as done in the previous example. You can also
call it explicitly call it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime TimeX("09:42:18 AM");
double Value = TimeX.operator double();
Edit1->Text = Value;
}
//---------------------------------------------------------------------------

9.9 Using Time

9.9.1 Displaying the Time


The AnsiString class is highly compatible with the TDateTime class. This flexibility
allows any text-based control to be able to display a time value. Thanks to this feature,
you do not have to convert a time value in order to display. For example, to show the
current time on the caption of a form, you can just write:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Caption = Time();
}
//---------------------------------------------------------------------------
This ability is independent of the format of the time; that is, it independent of the form of
initialization or source of the time value.

9.9.2 Decoding a Time


A time variable declared with the TDateTime class is made of an hour, a minute, a
second, and a millisecond portions. Decoding a time consists of isolating these
components from a valid time value. To perform such an operation, the TDateTime class
is equipped with the DecodeTime() method. Its syntax is:

260 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall DecodeTime(unsigned short* hour, unsigned short* min, unsigned


short* sec, unsigned short* msec) const;

Each component is retrieved using a pointer to an unsigned short. The presence of


pointers allows you to pass “empty” variables whose values would be altered by the
function and returned with new values.

In the following example, the current time is stored in a TDateTime variable named
RightNow. A form is equipped with four Edit controls named edtTime edtHours,
edtMinutes, and edtSeconds. Although the mSec argument is required to decode a time
value, it was used only during the decoding operation. After calling the function, the
hour, the minute, and the second are retrieved and displayed in the corresponding edit
boxes:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDecodeClick(TObject *Sender)
{
TDateTime RightNow = Time();

unsigned short Hours, Minutes, Seconds, Milliseconds;


RightNow.DecodeTime(&Hours, &Minutes, &Seconds, &Milliseconds);

edtTime->Text = RightNow;
edtHours->Text = Hours;
edtMinutes->Text = Minutes;
edtSeconds->Text = Seconds;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

261 © FunctionX, Inc.


Windows Events Borland C++ Builder

Besides the TDateTime::DecodeTime() method, the VCL provides a function that can be
used to decode a time value. Its syntax is:

void __fastcall DecodeTime(System::TDateTime Time, Word &Hour, Word &Min,


Word &Sec, Word &MSec);

The global DecodeTime() function is called in the same circumstances as the


TDateTime::DecodeTime() method except that it takes five arguments. The first is and
must be a valid TDateTime time value; this could be a time value in a recognizable
format or an already initialized variable. If this argument does not carry a valid time, the
function will fail and throw an error. The other four arguments are positive integers
(unsigned short) passed as reference. This allows the function to alter them and return
their changed values.

9.9.3 Encoding a Time


Encoding a time consists of supplying the necessary components of a TDateTime to the
compiler to create a valid time value. The function used to perform this operation is:

System::TDateTime __fastcall EncodeTime(Word Hour, Word Min, Word Sec,


Word MSec);

This function takes four positive integers (unsigned short) that represent:

• the hours: the values range from 0 to 23; midnight is 0 while 3 PM is 15


• the minutres: the values range from 0 to 59;
• the seconds: the values range from 0 to 59;
• the milliseconds: the values range from 0 to 999.

Example: the following form is equipped with five Edit controls named edtHours,
edtMinutes, edtSeconds, edtMilliseconds, and edtTime. When the user clicks the Encode
button named btnEncode, the OnClick event retrieves the of the hour, the minute, the
second, and the millisecond values from their respective edit boxes. The the compiler
creates a time from those valules and displays the result in the Time edit box:

262 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEncodeClick(TObject *Sender)
{
Word Hours, Minutes, Seconds, Milliseconds;

Hours = edtHours->Text.ToInt();
Minutes = edtMinutes->Text.ToInt();
Seconds = edtSeconds->Text.ToInt();
Milliseconds = edtMilliseconds->Text.ToInt();

TDateTime Value = EncodeTime(Hours, Minutes, Seconds, Milliseconds);


edtTime->Text = Value;
}
//---------------------------------------------------------------------------

9.9.4 Replacing a Time Value


To change the time of a TDateTime value, you can use the ReplaceTime() function. Its syntax is:

void __fastcall ReplaceTime(TDateTime &TimeTarget, const TDateTime


TimeSource);

The ReplaceTime() function takes two arguments. The second argument is the original
time that is used as the time reference. The first argument is the time value that needs to
be changed or replaced. The TimeSource argument must be a valid time variable or in a
recognizable format; otherwise, the function would fail and throw an error. The
TimeTarget argument can be an existing time value of a TDateTime variable. After the
function has executed, if successful, the time portions of both arguments would be the
same.

EXAMPLE

9.10 Comparison Operations On Time Values


The TDateTime class provides various functions used to perform any type of
comparisons between time values. By default, these operatiorns can be applied the same
way as done on regular variables. They can also be customized for more detailed
comparisons.

263 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.10.1 The Comparison for Equality


To find out whether two values carry the same time formats, apply the equality
comparison, exactly the same way you would proceed for regular variables.

In the following example, two time values are retrieved from two edit boxes for
comparison. If both times are the same, a message displays accordingly on a panel:

//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
TDateTime StartTime = StrToTime(edtStart->Text);
TDateTime EndTime = StrToTime(edtEnd->Text);

if( StartTime == EndTime )


Panel1->Caption = "Same Time";
else
Panel1->Caption = "";
}
//---------------------------------------------------------------------------

The equality comparison works on time values thanks the overloaded equality operator
on the TDateTime class:

bool __fastcall operator ==(const TDateTime& rhs) const;

The equality comparison works on all components of a time value. If either the hour, the
minute, the second, or the AM/PM is not the same the operation renders false. If you
want to compare just the hours, you should decode the time values and then perform the
comparison on the hours.

9.10.2 The Comparison for Difference


As opposed to the equality operation, you can use the inequality operator to find out
whether two dates are different. To do this, simply apply the operator the same way you
would do on regular variables. Here is an example following the same logic as above:

//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
TDateTime StartTime = StrToTime(edtStart->Text);
TDateTime EndTime = StrToTime(edtEnd->Text);

if( StartTime != EndTime )


Panel1->Caption = "Different Times";
else
Panel1->Caption = "";
}
//---------------------------------------------------------------------------

The difference comparison works on all four entities of a time value. It examines the
hours, minutes, seconds, and AM/PM of the values provides on both sides of the
operator. If any of both similar components are different, the operation produces a true
result. This operation is based on the overloaded != operator whose syntax is:

bool __fastcall operator !=(const TDateTime& rhs) const;

264 © FunctionX, Inc.


Windows Events Borland C++ Builder

9.10.3 The Comparison for Previous Occurrence


To find out whether a certain time occurs before another, use the “less than” operator “<”
the same way you would proceed for a regular variable. In the following example, when
the user click the Compare button on a form, the time values on two edit boxes and
retrieved and examined. If the time displayed in the Start Shift edit box occurs before the
time in the End Shift edit box, a dialog box displays a message accordingly:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
TDateTime Start = StrToTime(edtStart->Text);
TDateTime End = StrToTime(edtEnd->Text);

if( End < Start )


ShowMessage("Invalid Time Sheet. Please verify accuracy.");
}
//---------------------------------------------------------------------------

The “less than” comparison is based on its overloaded operator in the TDateTime class
using the following syntax:

bool __fastcall operator <(const TDateTime& rhs) const;

9.10.4 The Comparison for Previous or Equal Occurrence


The “less than or equal to” operator “<=” is used to check whether a time occurs previous
to, or in concordance with, another time. To use this operator on time values, proceed as
if you were dealing with regular variables. Here is an example based on the above event:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
TDateTime Start = StrToTime(edtStart->Text);
TDateTime End = StrToTime(edtEnd->Text);

if( End <= Start )


ShowMessage("Make sure your time sheet is correct.\n"
"If you didn't work on this day, "
"you don't have to sign the time sheet."
"\n\t\t\t\t\t\tThanks");
}
//---------------------------------------------------------------------------

The operator that allows this comparison uses the following syntax:

bool __fastcall operator <=(const TDateTime& rhs) const;

9.10.5 The Comparison for Subsequent Occurrence


To find out whether one time occurs after another, use the “greate than” operator “>”.
This operator works the same way it would for a regular variable. Here is an example:

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

265 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall TForm1::btnCompareClick(TObject *Sender)


{
TDateTime Start = StrToTime(edtStart->Text);
TDateTime End = StrToTime(edtEnd->Text);

if( Start > End )


{
lblMessage->Caption = "Your time sheet is not correct.";
edtStart->SetFocus();
}
}
//---------------------------------------------------------------------------

The “greater than” operator compare the hours, minutes, seconds, and AM/PM portions
of two dates and evaluates if the left date occurred after the right date; in this case, the
operator would produce a true Boolean value. This operation is based on its overloaded
operator from the TDateTime class. Its syntax is:

bool __fastcall operator >(const TDateTime& rhs) const;

9.10.6 The Comparison for Latter or Same Time


If a time occurs after or in concordance with another time, you can find this out using the
“greater than or equal operator. This operator is applied on two valid time values the
same way it would be used on regular variables. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
TDateTime Start = StrToTime(edtStart->Text);
TDateTime End = StrToTime(edtEnd->Text);

if( Start >= End )


{
lblMessage->Caption = "Your time sheet is not correct.";
edtStart->SetFocus();
}
}
//---------------------------------------------------------------------------

This comparison is possible thanks to the following overloaded operator in the


TDateTime class:

bool __fastcall operator >=(const TDateTime& rhs) const;

9.11 Controlling Time Display


The TDateTime class and the systdate.h file provide various techniques to control how
the time displays. Fundamentally the time displays according to the settings of the
Control Panel. There are two main functions for this purpose.

The TDateTime class is equipped with the FormatString() function whose syntax is:

AnsiString __fastcall FormatString(const AnsiString& Format);

266 © FunctionX, Inc.


Windows Events Borland C++ Builder

This function takes, as an argument, a string that specifies how the components of the
time value should display. The VCL provides an alternative function to apply the same
technique.; Its syntax is:

extern PACKAGE AnsiString __fastcall FormatDateTime(const AnsiString


Format, System::TDateTime Time);

When calling the FormatDateTime() function, you must pass two arguments. The Time
argument represents a time value or a variable that holds a valid time value. The Format
argument is a string that specifies how the time of the Time argument should display.

9.11.1 Displaying in Default Format


By default, the FormatDateTime() and the TDateTime::FormatString() functions
follow the format set by the computer’s Regional Settings of the Control Panel, which
usually ignores the 0 for hours less than 10.

To display the time using the default format, call the TDateTime::FormatString() method
and provide the Format argument as “c”. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime RightNow = Time();
RightNow.FormatString("c");

Edit1->Text = RightNow;
}
//---------------------------------------------------------------------------

9.11.2 Displaying the Leading Zero


When the hour portion of a time value is less than 10, you can control whether to display
the leading zero. This also applies to the minutes and the seconds. Each of these entities
provide two formats to take care of this. The syntax used to display the time is

hh:nn:ss AM/PM

The hh, nn, and ss portions are not case sensitive.

To ignore a leading zero when an hour less than 10 displays, use only h for the hour
portion. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime RightNow = Time();

Edit1->Text = RightNow.FormatString("h:nn:ss AM/PM");


}
//---------------------------------------------------------------------------

267 © FunctionX, Inc.


Windows Events Borland C++ Builder

To display the leading zero, use the hh format for the hour portion. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime RightNow = Time();

Edit1->Text = RightNow.FormatString("hh:nn:ss AM/PM");


}
//---------------------------------------------------------------------------

The rule to display or not display the leading zero for the minutes is the same. To avoid
the leading zero, use only one n when displaying the time. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTimeClick(TObject *Sender)
{
TDateTime TimeX("08:05:52 AM");

// Displaying the minutes without the leading zero


edtStart->Text = TimeX.FormatString("HH:n:ss AM/PM");
// Displaying the minutes with the leading zero
edtEnd->Text = TimeX.FormatString("hh:nn:ss AM/PM");
}
//---------------------------------------------------------------------------

These same rules apply for the seconds portions of the time display.

The AM/PM portion is case sensitive. This allows you display it in uppercase or in
lowercase. To display the AM/PM section in lowercase, type am/pm or ampm in the
AM/PM section. On the other hand, to display it in uppercase, type it as AM/PM or
AMPM. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTimeClick(TObject *Sender)
{
TDateTime TimeX("18:05:52");

// Displaying the AM/PM portion in lowercase

268 © FunctionX, Inc.


Windows Events Borland C++ Builder

edtStart->Text = TimeX.FormatString("hh:n:ss am/pm");


// Displaying the AMPM portion in uppercase
edtEnd->Text = TimeX.FormatString("hh:nn:ss AM/PM");
}
//---------------------------------------------------------------------------

9.12 Combining Date and Time

9.12.1 Fundamental Functions: Now()


C++ Builder provides a function that combines date and time. This function, called
Now(), can be used to display its value on:
• An edit box: edtNow->Text = “Date and Time: “ + Now();
• A label: lblNow->Caption = “Now: “ + Now();
• A form’s caption: Caption = Now();

9.12.2 Converting a String to Date and Time


To convert a string to a valid date and time, use the StrToDateTime() function. This
function follows the same rules as the StrToDate() function. Its syntax is:

TDateTime __fastcall StrToDateTime(const AnsiString S);

This function takes a string as argument. The string must have a valid TDateTime format;
otherwise, the operation would faild. If everything works fine, after converting the string,
the function returns a valid TDateTime value.

In the following example, a form is created with a MaskEdit control named edtSource, an
Edit control named edtTarget, two Button controls named btnConvert and btnExit. The
EditMask of the MaskEdit control is configured as follows:

!99/99/0000 !90:00:00 >LL;1;_

Here is the OnClick event of the Convert button:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
TDateTime Current = StrToDateTime(edtSource->Text);
edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

269 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall TForm1::btnExitClick(TObject *Sender)


{
Close();
}
//---------------------------------------------------------------------------

9.12.3 Converting a Date and Time to a String


To convert a date and time value to a string, use the DateTimeToStr(). Its syntax is:

AnsiString __fastcall DateTimeToStr(System::TDateTime Date);

This function takes, as argument, a valid TDateTime variable or value. If the argument is
not a valid date and time value, an error would result. After performing the conversion on
the date and time value, the function returns the value as a string.

In the following example, when the user clicks a button named btnConvert, the event uses
the Now() funtion to retrieve the current date and time then converts it to string and
displays the string in an Edit control named edtTarget:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
AnsiString Current = DateTimeToStr(Now());
edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

An alternative method to converting a date and time value to a string consists of using the
TDateTime::DateTimeString() method. Its syntax:

AnsiString __fastcall DateTimeString() const;

This function does not need an argument. To use it, declare a TDateTime date variable
and call the DateTimeString() method. Here is an example;

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime Current = Now();
AnsiString Right = Current.DateTimeString();

Edit1->Text = Right;
}
//---------------------------------------------------------------------------

270 © FunctionX, Inc.


Windows Events Borland C++ Builder

271 © FunctionX, Inc.


Windows Events Borland C++ Builder

Chapter 10:
Using C++ in VCL
Applications

272 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

10.1 Programmer Defined Objects, Functions, and Variables


The applications you write will usually consist of three categories of data types,
functions, or objects. The most usual objects will come from the Visual Components
Library. To compensate where the VCL is lacking a functionality or Borland simply
decided not to implement a behavior that already exists and is easy to implement, you
will also use data types, constants, or objects of the Win32 library. When a function or
object does not exist in any of these libraries, you will have to create your own. This will
happen regularly because the compiler designers could not write everything for you since
they could not predict what particular behavior you would like to implement in your
application. Equipped with the fundamentals of C++ that you have learned already, you
can add your own variables, functions or object.

10.1.1 Programmer Defined Functions and Variables


We are going to simulate a form used to calculate the total and average grades for a
student. We will also calculate the ranges of grades:

10.1.2 Local Variables


A local variable is one you create in an event as you need it. We have used a few already.
To declare a variable, you can use:
• A C/C++ data type followed by a name

int Age;
double Distance;
char FirstName[12];

• A Win32 data type

INT MemberID;
BOOLEAN IsWorking;

273 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

• A VCL redefined data type

Cardinal ItemLength;
Extended TotalPrice;

• A Win32 object

CHARFORMAT2 cfm;
HBITMAP hBitmap;

• A VCL object

TOpenDialog* FileOpener;
Tform *Locker;

Practical Learning: Using Programmer-Declared Variables


1. Start a new project with the default form
2. Change the form’s caption to Students Grades and its BorderStyle to bsDialog

3. Add labels to the form as on the above pictures


4. Add Edit controls corresponding to each label. Name each Edit control to its
corresponding label as follows: edtEnglish, edtFrench, edtGeography,
edtHistory, edtSports.
5. Add two buttons on the left and the right section of a the form. Name the buttons
btnCompute and btnExit respectively. Set their captions to &Compute and
E&xit respectively. Set the Default property of the Compute button to true. Set
the Cancel property of the Exit button to true.
6. To declare your own variables and initialize them, double-click the Compute
button and implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnComputeClick(TObject *Sender)
{
// Declare a variable for each grade needed
Double English, French, Geography, History, Sports;

274 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

// Initialize each variable to the corresponding Edit control


English = edtEnglish->Text.ToDouble();
French = edtFrench->Text.ToDouble();
Geography = edtGeography->Text.ToDouble();
History = edtHistory->Text.ToDouble();
Sports = edtSports->Text.ToDouble();
}
//---------------------------------------------------------------------------
7. Press F12 to display the form. Double-click the Exit button and implement it as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
8. To test the form, on the main menu, click Run  Run.
9. After viewing the dialog, click the Exit button to close it.

10. To use more variables, add two labels and two Edit controls to the form. Name
the Edit controls edtTotal and edtAverage respectively.
11. To use the new edit boxes, change the btnComputeClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnComputeClick(TObject *Sender)
{
// Declare a variable for each grade needed
Double English, French, Geography, History, Sports;
Double Total, Average;

// Initialize each variable to the corresponding Edit control


English = edtEnglish->Text.ToDouble();
French = edtFrench->Text.ToDouble();
Geography = edtGeography->Text.ToDouble();
History = edtHistory->Text.ToDouble();
Sports = edtSports->Text.ToDouble();

275 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

// Calculate the total and the average of grades


Total = English + French + Geography + History + Sports;
Average = Total / 5;

// Display the total and the average in the appropriate edit boxes
edtTotal->Text = Total;
edtAverage->Text = Average;
}
//---------------------------------------------------------------------------
12. Test the form. Here is an example:

13. After using the form, return to Bcb.

10.1.3 Local Functions


There are various ways you can use your own functions in an application. To create a
function in a source file, you can declare it on top of the file prior to defining it. This
allows any other function or event that would need it to easily call it:

//---------------------------------------------------------------------------
Double GetMin(Double g[], int size);
Double GetMax(Double g[], int size);
void Ranges(Double g[], int& r1, int& r2, int& r3, int& r4, int& r5);
//---------------------------------------------------------------------------

If you call a function after it has been defined, you do not need to declare it in the top
section of the source file.

To define a function, implement its behavior as you see fit. For example, the following
function receives two integer arguments, use them to create a long integer that represents
an RGB color, converts the the result to a TColor enumerator, and returns the resulting
color:

TColor BackColor(int X, int Y)


{
TColor Clr;
Clr = TColor(RGB((X % 255), (Y % 255), ((X+Y)%255)));

return Clr;

276 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

You can also define a function using __fastcall.

Practical Learning: Using Programmer Defined Functions


1. Continue designing the form as follows.

2. Add two new labels to the form as on the above picture. Once again, the Edit
controls are named after their corresponding labels: edtHighest and edtLowest
3. To add your own functions that calculate the highest and lowest values, change
the source file as follows:

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
Double __fastcall GetMin(Double g[], int size)
{
// Set the minimum as the first member of the array
Double Min = g[0];

// Scan the array members to compare them


for(int i = 0; i < size; ++i)
if( Min > g[i] )
Min = g[i];
return Min;
}

277 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

//---------------------------------------------------------------------------
Double __fastcall GetMax(Double g[], int size)
{
// Set the maximum as the first member of the array
Double Max = g[0];

// Scan the array members to compare them


for(int i = 0; i < size; ++i)
if( Max < g[i] )
Max = g[i];
return Max;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnComputeClick(TObject *Sender)
{
// Declare a variable for each grade needed
Double English, French, Geography, History, Sports;
Double Total, Average, Highest, Lowest;

// Initialize each variable to the corresponding Edit control


English = edtEnglish->Text.ToDouble();
French = edtFrench->Text.ToDouble();
Geography = edtGeography->Text.ToDouble();
History = edtHistory->Text.ToDouble();
Sports = edtSports->Text.ToDouble();

// Create an array that comprises the grades


Double Grades[] = { English, French, Geography, History, Sports };
// Calculate the total and the average of grades
Total = English + French + Geography + History + Sports;
Average = Total / 5;

// Find the highest value of the array


// by passing the array to the GetMax() function
Highest = GetMax(Grades, 5);
// Do the same to find the minimum value
Lowest = GetMin(Grades, 5);
// Pass the array and the range of values as references

// Display the total and the average in the appropriate edit boxes
edtTotal->Text = edtTotal->Text.sprintf("%.2f", Total);
edtAverage->Text = edtAverage->Text.sprintf("%.2f", Average);
edtHighest->Text = edtHighest->Text.sprintf("%.2f", Highest);
edtLowest->Text = edtLowest->Text.sprintf("%.2f", Lowest);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
4. Test the form.
5. To improve your application, enlarge the form and add the following labels and
Edit controls. The Edit controls will be named after their labels as follows:
edtBiology, edtTechnology, edtCompArchitecture, edtCompSciences,
edtMorale:

278 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

6. Also add a new button named btnReset with a caption of &Reset.


7. Set the Tab Order so that the edit boxes of the grades appear first:

8. To add the grades of the new edit boxes, change the btnComputeClick event as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnComputeClick(TObject *Sender)
{
// Declare a variable for each grade needed
Double English, French, Geography, History, Sports,
Biology, Technology, CompArch, CompSciences, Morale;
Double Total, Average, Highest, Lowest;

// Initialize each variable to the corresponding Edit control

279 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

English = edtEnglish->Text.ToDouble();
French = edtFrench->Text.ToDouble();
Geography = edtGeography->Text.ToDouble();
History = edtHistory->Text.ToDouble();
Sports = edtSports->Text.ToDouble();
Biology = edtBiology->Text.ToDouble();
Technology = edtTechnology->Text.ToDouble();
CompArch = edtCompArchitecture->Text.ToDouble();
CompSciences = edtCompSciences->Text.ToDouble();
Morale = edtMorale->Text.ToDouble();

// Create an array that comprises the grades


Double Grades[] = { English, French, Geography, History, Sports,
Biology, Technology, CompArch, CompSciences, Morale };
// Calculate the total and the average of grades
Total = English + French + Geography + History + Sports +
Biology + Technology + CompArch + CompSciences + Morale;
Average = Total / 5;

// Find the highest value of the array


// by passing the array to the GetMax() function
Highest = GetMax(Grades, 5);
// Do the same to find the minimum value
Lowest = GetMin(Grades, 5);
// Pass the array and the range of values as references

// Display the total and the average in the appropriate edit boxes
edtTotal->Text = edtTotal->Text.sprintf("%.2f", Total);
edtAverage->Text = edtAverage->Text.sprintf("%.2f", Average);
edtHighest->Text = edtHighest->Text.sprintf("%.2f", Highest);
edtLowest->Text = edtLowest->Text.sprintf("%.2f", Lowest);
}
//---------------------------------------------------------------------------
9. Press F12 to display the form. Double-click the Reset button and implement it as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnResetClick(TObject *Sender)
{
edtEnglish->Text = AnsiString("0.00");
edtFrench->Text = AnsiString("0.00");
edtGeography->Text = AnsiString("0.00");
edtHistory->Text = AnsiString("0.00");
edtSports->Text = AnsiString("0.00");
edtBiology->Text = AnsiString("0.00");
edtTechnology->Text = AnsiString("0.00");
edtCompArchitecture->Text = AnsiString("0.00");
edtCompSciences->Text = AnsiString("0.00");
edtMorale->Text = AnsiString("0.00");
edtTotal->Text = AnsiString("0.00");
edtAverage->Text = AnsiString("0.00");
edtHighest->Text = AnsiString("0.00");
edtLowest->Text = AnsiString("0.00");
}
//---------------------------------------------------------------------------

280 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

10. Test the form. Here is an example:

11. After testing the edit boxes with some values between 0 and 100, click the Reset
button.
12. Click the Exit button to return to Bcb.
13. To further improve your application, we will find the number of grades that
range in some categories.
Add the following labels and Edit controls. Named after their labels, the Edit
controls are called edtedtRange90100, edtRange8089, edtRange7079,
edtRange6069, edtBelow60:

14. We need a function that would take the array of grades and compute the ranges
of its members. After the function has finished examining the array, it should
return the results of each range. One of the ways we can do this is to pass each
integer range as reference (we could also pass them as pointers); this allows a
function, even declared as void, to return multiple values. To create this
function, define it on top of the btnComputeClick event, as follows:

//---------------------------------------------------------------------------
void __fastcall Ranges(Double g[], int& r1, int& r2, int& r3, int& r4,
int& r5)
{

281 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

// Examine each grade value to label its range


for(int Count = 0; Count < 5; Count++)
{
if( (g[Count] >= 90) && (g[Count] <= 100) )
r1++;
else if( (g[Count] >= 80) && (g[Count] < 90) )
r2++;
else if( (g[Count] >= 70) && (g[Count] < 80) )
r3++;
else if( (g[Count] >= 60) && (g[Count] < 70) )
r4++;
else
r5++;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnComputeClick(TObject *Sender)
15. Now that we can get the ranges of values of the array, we will need to display
them in their corresponding edit boxes.
First declare an integer for each range. Since each one of these integers will
represent a total, you should initialize it to 0. Then, after declaring and
initializing the array, call the Ranges function with the needed arguments.
Finally, display the values on the form:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnComputeClick(TObject *Sender)
{
// Declare a variable for each grade needed
Double English, French, Geography, History, Sports,
Biology, Technology, CompArch, CompSciences, Morale;
Double Total, Average, Highest, Lowest;

// Declare each needed variable and initialize it


int Range1 = 0, Range2 = 0, Range3 = 0, Range4 = 0, Range5 = 0;

// Initialize each variable to the corresponding Edit control


English = edtEnglish->Text.ToDouble();
French = edtFrench->Text.ToDouble();
Geography = edtGeography->Text.ToDouble();
History = edtHistory->Text.ToDouble();
Sports = edtSports->Text.ToDouble();
Biology = edtBiology->Text.ToDouble();
Technology = edtTechnology->Text.ToDouble();
CompArch = edtCompArchitecture->Text.ToDouble();
CompSciences = edtCompSciences->Text.ToDouble();
Morale = edtMorale->Text.ToDouble();

// Create an array that comprises the grades


Double Grades[] = { English, French, Geography, History, Sports,
Biology, Technology, CompArch, CompSciences, Morale };
// Calculate the total and the average of grades
Total = English + French + Geography + History + Sports +
Biology + Technology + CompArch + CompSciences + Morale;
Average = Total / 10;

// Pass the array and the range of values as references


Ranges(Grades, Range1, Range2, Range3, Range4, Range5);

282 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

// Find the highest value of the array


// by passing the array to the GetMax() function
Highest = GetMax(Grades, 10);
// Do the same to find the minimum value
Lowest = GetMin(Grades, 10);
// Pass the array and the range of values as references

// Display the total and the average in the appropriate edit boxes
edtTotal->Text = edtTotal->Text.sprintf("%.2f", Total);
edtAverage->Text = edtAverage->Text.sprintf("%.2f", Average);
edtHighest->Text = edtHighest->Text.sprintf("%.2f", Highest);
edtLowest->Text = edtLowest->Text.sprintf("%.2f", Lowest);
edtRange90100->Text = Range1;
edtRange8089->Text = Range2;
edtRange7079->Text = Range3;
edtRange6069->Text = Range4;
edtBelow60->Text = Range5;
}
//---------------------------------------------------------------------------
16. To synchronize with resetting the grade values, change the btnResetClick event
as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnResetClick(TObject *Sender)
{
...
edtRange90100->Text = 0;
edtRange8089->Text = 0;
edtRange7079->Text = 0;
edtRange6069->Text = 0;
edtBelow60->Text = 0;

}
//---------------------------------------------------------------------------
17. Test the form. Here is an example:

18. To enhance the look of the form, add one bevel around the grades, another bevel
around the calculated boxes, and a bsRaised Style bevel around the buttons:

283 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

19. Once test the application before closing it.

10.2 Global Variables and Functions


There are two types of global variables and functions, those that are local to your
applications but accessible by many functions or events, and those that are accessible by
any application and any unit. The second category of functions are part of the C++
language, the C++ Builder compiler, or the Win32 library. The first category includes
functions you create while you are working on a particular project

There are various ways you can create your own global variables and functions. To use a
function available to other functions or event, in the private or public sections of the unit
that will need it, declare the function:

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
WORD Salute();
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

If you add it to the private section, it will be accessible only to other functions or events
of the same unit. Otherwise, if you want the function to be accessible outside of its unit,
declare it in the public section:

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
WORD Salute();
public: // User declarations
Extended CalcMeasure();
__fastcall TForm1(TComponent* Owner);

284 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

};
//---------------------------------------------------------------------------

Probably one of the most efficient ways of adding a function is by using the
ClassExplorer where you can right-click a class such as TForm and add a Method.

After declaring a function in the header file, you should define it in the source file. Once
it has been defined, it can be called by any function or event of the same unit.

If you declare a function as public, you can indirectly access it from another unit or form.

10.2.1 The Karyne Restaurant Application


Karyne Lamond owns a fast food restaurant that serves subs and other side orders. The
subs are served in 6” or 12” roll of bread. A customer can choose a sub, side order or
drinks in any combination. Karyne needs a program that would allow her to take and
process orders using a computer. After getting a list of the items that the store sells, we
can start planning the application.

10.2.2 Designing the Application


The main form of the application will be used to take and process orders. The program
will find out how many units of a particular item the customer has selected. The
application will perform a live calculation of the total order. The unit prices of items will
be stored in a dialog box. On the main form, the user, referred to as a clerk, will not be
able to change the prices of items. After the customer has made choices, the clerk can get
another dialog box to calculate the change or difference based on the amount tended.

Pracitcal Learning: Designing the Application


1. To create a new project, on the main menu of C++ Builder, click File  New…
2. Change the caption of the starting form to Karyne’s Resto – Food Order
3. Change the name to frmFoodOrders
4. Set the biMaximize field of the BorderIcons property to false
5. Change the height of the form to 300 and its width to 490
6. To save the current project, on the Standard toolbar, click the Save All button.
7. Locate the folder where the exercises are installed.
8. Click the Create New Folder button, type Karyne and press Enter.
9. Display the Karyne folder in the Save In combo box.

285 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

10. Change the name of the Unit1.cpp to FoodOrder

11. Click Save.


12. Type KaryneResto to replace the name of the project and press Enter
13. To add one of C++ Builder’s dialog boxes, on the main menu, click File  New
14. On the Object Repository, click the Dialogs property page.
15. Click Standard Dialog (Vertical)
16. Click OK.
Here is the dialog box we will design

17. Change the caption of the new dialog box to


Karyne’s Resto – Money Change

18. Change the name of the dialog box to frmChange


19. There is already a bevel on the dialog. Change its properties as follows: Height
= 140, Left = 8, Top = 8, Width 210.
20. Add another bevel with the following properties: Height = 10, Left = 24, Shape
= bsBottomLine, Top = 88, Width 180.

286 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

21. Move the existing buttons to Left = 236.


22. Change the height of the dialog to 192 and its width to 335
23. Design the dialog by adding two labels captioned Total Order: and Amount
Tended

24. Add one label captioned Difference and named lblChange


25. Add three Edit controls named edtTotalOrder, edtAmountTended, and
edtChange respectively.

26. Make sure you delete the content of the Text field for each edit box
27. Click the OK button and press Delete to delete it.
28. Set the Caption property of the Cancel button to Close.
29. Add a button control with a caption of &Calculate and a name of btnCalculate
30. Set the Default property of the btnCalculate control to true.
31. Right-click in the middle of the dialog and click Tab Order.
32. Arrange the tab order as follows:

33. Click OK
34. To save the new form and unit, on the Standard toolbar, click the Save button.
35. Make sure Karyne is displaying in the Save In combo box. Type Change and
press Enter.
36. To add another one of C++ Builder’s dialog boxes, on the main menu, click File
 New
37. On the Object Repository, click the Dialogs property page.
38. Click Standard Dialog (Horizontal)
39. Click OK.

287 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

40. To save the new dialog box, on the Standard toolbar, click the Save button.
41. Type FoodPrices and press Enter
Here is the design for the new dialog box:

42. Change the caption of the new dialog to Karyne’s Resto – Food Prices
43. Change the dimensions to Height = 288 and Width = 430
44. Change the name to frmFoodPrices
45. Besides the existing bevel, add another bevel control to the right side of the
form.
46. Change the Shape property to bsFrame
47. Place a label on the top line of the left bevel with a caption of Food Menu
48. Add another label to the top of the right bevel with a caption of Side Orders
49. Design the dialog box using the following tables:

Label Edit1 Names Text Edit2 Names Text


Philadelphia Cheese EdtPC6Price 5.45 edtPC12Price 6.25
Ham && Cheese edtHC6Price 5.35 edtHC12Price 6.15
Steak, Ham && Cheese edtSHC6Price 5.65 edtSHC12Price 6.50
Filet O’ Fish edtFOF6Price 5.25 edtFOF12Price 6.65
Cheeseburger edtC6Price 5.45 edtC12Price 6.35
Chicken Breast edtCB6Price 5.55 edtCB12Price 6.45
Tuna Salad edtTS6Price 5.45 edtTS12Price 5.85

Caption Edit Name Text


French Fries edtFFPrice 1.15
Onion Rings edtORPrice 1.15
Milk Shake edtMSPrice 1.25
Apple Pie edtAPPrice 0.95
Dutch Pie edtDPPrice 1.00

288 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

Soda edtSPrice 0.85


Orange edtOJPrice 1.25
Juice

50. To select everything on the form, on the main menu, click Edit  Select All.
Notice that all controls on the form are selected.
51. To copy the selection to the clipboard, on the main menu, click Edit  Copy.
52. To display the starting form, press Shift + F12.
53. On the View Form dialog box, click FoodOrders and click OK.
54. To paste the items and their prices, on the main menu, click Edit  Paste. Press
Esc to deselect everything.
Here is the design we will apply to the Food Orders form

55. Click the OK button to select it and press Delete


56. Click the Cancel button and press Delete
57. Set each price Edit control’s ReadOnly property to true:

Edit1 Names Edit Name


Read ReadOnly
Only
Edit2 Names edtFFPrice
Read
true
Only

EdtPC6Price edtORPrice
true true
edtPC12Price
true edtMSPrice
true
edtHC6Price
true edtAPPrice
edtHC12Price true
true
edtDPPrice
edtSHC6Price true

289 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

true
edtSHC12Price edtSPrice
true true

edtFOF6Price edtOJPrice
true true
edtFOF12Price
true

edtC6Price
true
edtC12Price
true

edtCB6Price
true
edtCB12Price
true

edtTS6Price
true
edtTS12Price
true

58. Move the right bevel and all of its content to the right section of the form (since
the bevel is not a container, it cannot “carry” its controls; you will select each
manually). Enlarge the left bevel.
59. Add the # edit boxes using the following tables:

Label Nbr Of 6” Subs Text Nbr Of 12” Buns Text


Philadelphia Cheese edtPC6Nbr 0 edtPC12Nbr 0
Ham && Cheese edtHC6Nbr 0 edtHC12Nbr 0
Steak, Ham && Cheese edtSHC6Nbr 0 edtSHC12Nbr 0
Filet O’ Fish edtFOF6Nbr 0 edtFOF12Nbr 0
Cheeseburger edtC6Nbr 0 edtC12Nbr 0
Chicken Breast edtCB6Nbr 0 edtCB12Nbr 0
Tuna Salad edtTS6Nbr 0 edtTS12Nbr 0

Caption Nbr Of Units Text


French Fries edtFFNbr 0
Onion Rings edtORNbr 0
Milk Shake edtMSNbr 0
Apple Pie edtAPNbr 0
Dutch Pie edtDPNbr 0
Soda edtSNbr 0
Orange Juice edtOJNbr 0

290 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

60. Add a panel to the bottom of the form. Set its BevelInner property to
bvLowered and its BevelOuter property to bvRaised
61. Inside of the panel, add the following controls

Control Caption Name


Label Total Order:
Button Change &Prices btnChangePrices
Button Get the &Change btnGetChange Default = true
Button E&xit btnExit Cancel = true
Edit Name edtTotalOrder
Text 0.00

291 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

62. Right-click in the middle of the form, click Tab Order and arrange the sequence
of control navigation as follows:

63. Click OK

10.2.3 Coding the Application


We will store the price of each item in a global variable. This price will be a combination
of the number of an item and its unit price. To use these prices in another calculation, we
will declare them in the header file. It does not matter where the variables are declared
since we will not deal with any inheritance, but to keep matters a little simpler, we will
declare the variables as private.

When the user has made changes to the prices using an appropriate dialog box, she will
click OK and the new prices will be replicated to the main form

Practical Learning: Coding the Karyne Resto’s Application


1. We are still working on the Food Orders form.
To switch to the form’s code, press F12.
2. Double-click the Exit button to access its OnClick event. Implement it as
follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::btnExitClick(TObject *Sender)
{
Close();
}

292 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

//---------------------------------------------------------------------------
3. To declare a global variable, right-click the Class Explorer window and click
New Field…

4. Set the Field Name to PricePC6 and in the Add To Class combo box, select
TfrmFoodOrders. In the Type combo box, type d and then double-click the
down-pointing arrow to display double. Click the Private radio button.

11. Click OK:

private:
double PricePC6; // User declarations
12. To display the form, press F12.
13. To include the header file of the Food Prices form, on the main menu, click File
 Include Unit Hdr…
14. On the Use Unit dialog box, click FoodPrices and click OK
15. On the form, double-click the Change Prices button and implement its OnClick
event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::btnChangePricesClick(TObject *Sender)
{
// Find out whether the user clicked OK
if( frmFoodPrices->ShowModal() == mrOk )
{
// Since the user clicked OK, transfer each price changed
// from the Food Prices dialog box to the Food Order form
edtPC6Price->Text = frmFoodPrices->edtPC6Price->Text;
edtPC12Price->Text = frmFoodPrices->edtPC12Price->Text;
edtHC6Price->Text = frmFoodPrices->edtHC6Price->Text;
edtHC12Price->Text = frmFoodPrices->edtHC12Price->Text;
edtSHC6Price->Text = frmFoodPrices->edtSHC6Price->Text;
edtSHC12Price->Text = frmFoodPrices->edtSHC12Price->Text;
edtFOF6Price->Text = frmFoodPrices->edtFOF6Price->Text;
edtFOF12Price->Text = frmFoodPrices->edtFOF12Price->Text;
edtC6Price->Text = frmFoodPrices->edtC6Price->Text;
edtC12Price->Text = frmFoodPrices->edtC12Price->Text;
edtCB6Price->Text = frmFoodPrices->edtCB6Price->Text;
edtCB12Price->Text = frmFoodPrices->edtCB12Price->Text;

293 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

edtCB6Price->Text = frmFoodPrices->edtCB6Price->Text;
edtCB12Price->Text = frmFoodPrices->edtCB12Price->Text;
edtTS6Price->Text = frmFoodPrices->edtTS6Price->Text;
edtTS12Price->Text = frmFoodPrices->edtTS12Price->Text;
edtFFPrice->Text = frmFoodPrices->edtFFPrice->Text;
edtORPrice->Text = frmFoodPrices->edtORPrice->Text;
edtMSPrice->Text = frmFoodPrices->edtMSPrice->Text;
edtAPPrice->Text = frmFoodPrices->edtAPPrice->Text;
edtDPPrice->Text = frmFoodPrices->edtDPPrice->Text;
edtOJPrice->Text = frmFoodPrices->edtOJPrice->Text;
}
}
//---------------------------------------------------------------------------
16. To actucal price of each item is calculated by multiplying the quantity set of the
item by the unit price. Since there are many items that perform the same
calculation, we will use a global function that takes the content of a quantity edit
box and the content of a unit price. After the calculation, the function will return
the total price of the particular item.
Right-click in the Class Explorer and click New Method…
17. Set the method name to CalcItemPrice
18. In the Add to Class combo box, select TfrmFoodOrders and the arguments as
AnsiString StrQty, AnsiString StrUnitPrice
19. In the Function Result combo box, type d and then double-click the down-
pointing arrow. The double data type should be selected. Otherwise, set the
Function Result to double. Click the __fastcall check box:

20. Click OK and implement the function as follows:

//---------------------------------------------------------------------------
double __fastcall TfrmFoodOrders::CalcItemPrice(AnsiString StrQty,

294 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

AnsiString StrUnitPrice)
{
int Qty;
double UnitPrice, Price;

// Get the number of items ordered


if(StrQty == "" )
{
StrQty == "0";
Qty = 0;
}
else
Qty = StrToInt(StrQty);

// Get the unit price of this item


UnitPrice = StrToFloat(StrUnitPrice);

// Calculate the total price of this unit based on the number


Price = Qty * UnitPrice;
return Price;
}
//---------------------------------------------------------------------------
21. Press F12 to display the form again.
22. Double-click the first # edit box, which is the number of 6”Philadelphia Cheese
subs.
23. We will declare two local string variables, each will be used to retrieve the
content of an Edit control. To do that, implement the OnChange event as
follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtPC6NbrChange(TObject *Sender)
{
AnsiString Quantity, UnitPrice;

Quantity = edtPC6Nbr->Text;
UnitPrice = edtPC6Price->Text;
}
//---------------------------------------------------------------------------

24. Once we have two strings that represent the quantity and the unit orice
respectively, we can pass them to the CalcItemPrice() function. We will use the
returned value to set the total price of this unit. Therefore, change the
edtPC6Nbr OnClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtPC6NbrChange(TObject *Sender)
{
AnsiString Quantity, UnitPrice;

Quantity = edtPC6Nbr->Text;
UnitPrice = edtPC6Price->Text;

PricePCBun = CalcItemPrice(Quantity, UnitPrice);


}
//---------------------------------------------------------------------------

295 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

25. We will use this same technique to find the total price of each item. Once we
have the prices, we can display the total price of the order in the Total edit box.
To display this total, we will use a global function that can add all of the total
prices and display the result in the Total.
If it is not expanded yet, click the + sign of the KaryneResto – Classes folder.
Right-click TfrmFoodOrders and click New Method…
26. Set the Method Name to DisplayTotal
27. Make sure the Add to Class combo box displays TfrmFoodOrders. Leaving the
Arguments empty, set the Function Result to void and click the __fastcall check
box. Click OK.
28. Implement the DisplayTotal() function as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::DisplayTotal()
{
double TotalOrder = PricePC6;

edtTotalOrder->Text = edtTotalOrder->Text.sprintf("%.2f", TotalOrder);


}
//---------------------------------------------------------------------------
29. Although the DisplayTotal() function is only used to calculate and display the
grand-total, we can call it every time the user (clerk) changes the quantity of an
item. This is because a new calculation of the total price of an item is performed
everytime a quantity changes.
As an example of implementing this behavior, change the implementation of the
edtPC6NbrChange event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtPC6NbrChange(TObject *Sender)
{
AnsiString Quantity, UnitPrice;

Quantity = edtPC6Nbr->Text;
UnitPrice = edtPC6Price->Text;

PricePC6 = CalcItemPrice(Quantity, UnitPrice);


DisplayTotal();
}
//---------------------------------------------------------------------------
30. To test the form, on the main menu, click Run  Run.
31. On the form, change the quantity of 6” Philly Cheese to 2 and see how the total
instantaneously displays the total. Change the same quantity to 6 and verify the
result.
32. To close the form, click the Exit button.
33. Declare the other quantity and unit prices in the header file of the Food Order
form as follows:

private: // User declarations


double PricePC6, PriceHC6, PriceSHC6, PriceFOF6,
PriceC6, PriceCB6, PriceTS6;
double PricePC12, PriceHC12, PriceSHC12, PriceFOF12,

296 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

PriceC12, PriceCB12, PriceTS12;


double PriceFF, PriceOR, PriceMS, PriceAP, PriceDP, PriceS, PriceOJ;
34. Press F12 to display the form. Double-click each quantity Edit control and
implement their OnChange events as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtHC6NbrChange(TObject *Sender)
{
PriceHC6 = CalcItemPrice(edtHC6Nbr->Text, edtHC6Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtSHC6NbrChange(TObject *Sender)
{
PriceSHC6 = CalcItemPrice(edtSHC6Nbr->Text, edtSHC6Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtFOF6NbrChange(TObject *Sender)
{
PriceFOF6 = CalcItemPrice(edtFOF6Nbr->Text, edtFOF6Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtC6NbrChange(TObject *Sender)
{
PriceC6 = CalcItemPrice(edtC6Nbr->Text, edtC6Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtCB6NbrChange(TObject *Sender)
{
PriceCB6 = CalcItemPrice(edtCB6Nbr->Text, edtCB6Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtTS6NbrChange(TObject *Sender)
{
PriceTS6 = CalcItemPrice(edtTS6Nbr->Text, edtTS6Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtPC12NbrChange(TObject *Sender)
{
PricePC12 = CalcItemPrice(edtPC12Nbr->Text, edtPC12Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtHC12NbrChange(TObject *Sender)
{
PriceHC12 = CalcItemPrice(edtHC12Nbr->Text, edtHC12Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtSHC12NbrChange(TObject *Sender)
{
PriceSHC12 = CalcItemPrice(edtSHC12Nbr->Text, edtSHC12Price->Text);
DisplayTotal();

297 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtFOF12NbrChange(TObject *Sender)
{
PriceFOF12 = CalcItemPrice(edtFOF12Nbr->Text, edtFOF12Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtC12NbrChange(TObject *Sender)
{
PriceC12 = CalcItemPrice(edtC12Nbr->Text, edtC12Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtCB12NbrChange(TObject *Sender)
{
PriceCB12 = CalcItemPrice(edtCB12Nbr->Text, edtCB12Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtTS12NbrChange(TObject *Sender)
{
PriceTS12 = CalcItemPrice(edtTS12Nbr->Text, edtTS12Price->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtFFNbrChange(TObject *Sender)
{
PriceFF = CalcItemPrice(edtFFNbr->Text, edtFFPrice->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtORNbrChange(TObject *Sender)
{
PriceOR = CalcItemPrice(edtORNbr->Text, edtORPrice->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtMSNbrChange(TObject *Sender)
{
PriceMS = CalcItemPrice(edtORNbr->Text, edtORPrice->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtAPNbrChange(TObject *Sender)
{
PriceAP = CalcItemPrice(edtAPNbr->Text, edtAPPrice->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtDPNbrChange(TObject *Sender)
{
PriceDP = CalcItemPrice(edtDPNbr->Text, edtDPPrice->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtSNbrChange(TObject *Sender)
{
PriceS = CalcItemPrice(edtSNbr->Text, edtSPrice->Text);

298 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

DisplayTotal();
}
//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::edtOJNbrChange(TObject *Sender)
{
PriceOJ = CalcItemPrice(edtOJNbr->Text, edtOJPrice->Text);
DisplayTotal();
}
//---------------------------------------------------------------------------

35. If the user decides to change the price of items, we had decided that this would
be performed on a different form. When the price of items has been changed and
the clerk clicks OK, since it is likely that an order processing was going on, we
need to immediately recalculate the total price. To do that, we will ask each item
to re-evaluate itself:

//---------------------------------------------------------------------------
void __fastcall TfrmFoodOrders::btnChangePricesClick(TObject *Sender)
{
// Find out whether the user clicked OK
if( frmFoodPrices->ShowModal() == mrOk )
{
...
}
edtPC6NbrChange(Sender);
edtHC6NbrChange(Sender);
edtHC6NbrChange(Sender);
edtSHC6NbrChange(Sender);
edtFOF6NbrChange(Sender);
edtC6NbrChange(Sender);
edtCB6NbrChange(Sender);
edtTS6NbrChange(Sender);
edtPC12NbrChange(Sender);
edtHC12NbrChange(Sender);
edtSHC12NbrChange(Sender);
edtFOF12NbrChange(Sender);
edtC12NbrChange(Sender);
edtCB12NbrChange(Sender);
edtTS12NbrChange(Sender);
edtFFNbrChange(Sender);
edtORNbrChange(Sender);
edtMSNbrChange(Sender);
edtAPNbrChange(Sender);
edtDPNbrChange(Sender);
edtSNbrChange(Sender);
edtSNbrChange(Sender);
edtOJNbrChange(Sender);
}
//---------------------------------------------------------------------------
36. To test the form, on the main menu, click Run  Run
37. Change the quantities of different items and make sure that the calculation is
performed and the total order is displayed immediately.
38. After using the form, close it.
39. Display the Food Order form.

299 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

40. To include the header file of the Change form, on the main menu, click File 
Include Unit Hdr…
41. On the Use Unit dialog box, the Change unit should be selected because it is the
only one. Otherwise, select Change and click OK.
42. Double-click the Get the Change button and implement its OnClick event as
follows:

void __fastcall TFoodOrder::btnGetChangeClick(TObject *Sender)


{
frmChange->edtTotalOrder->Text = frmFoodOrders->edtTotalOrder->Text;
frmChange->ShowModal();
}
43. To display the View Form dialog, press Shift + F12
44. On the View Form dialog, click frmChange and click OK
45. Double-click the Calculate button and implement its OnClick event as follows:

//---------------------------------------------------------------------
void __fastcall TfrmChange::btnCalculateClick(TObject *Sender)
{
double TotalOrder, AmountTended, Difference;

// Convert the content of the Total Order box to a float number


TotalOrder = StrToFloat(edtTotalOrder->Text);

// If the user has not typed anything yet as Amounted Tended,


if(edtAmountTended->Text == "") // Consider it 0
AmountTended = 0.00;
else // Otherwise, get the amount tended
AmountTended = StrToFloat(edtAmountTended->Text);

// Calculate the difference


Difference = AmountTended - TotalOrder;

// If the difference is positive, display how much the clerk owes


// to the customer.
if( Difference >= 0 )
{
lblChange->Font->Color = clBlack;
lblChange->Caption = "Change:";
edtChange->Font->Color = clBlack;
edtChange->Text = edtChange->Text.sprintf("%.2f", Difference);
}
else// If the difference is negative, that means the customer still owes
{
// Display the label in red to alert the clerk not to close
// Display the amount owed in red.
lblChange->Font->Color = clRed;
lblChange->Caption = "Please Add:";
edtChange->Font->Color = clRed;
Difference = fabs(Difference);
edtChange->Text = edtChange->Text.sprintf("%.2f", Difference);
}
}
//---------------------------------------------------------------------------

300 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

46. On top of the current source file, include the math.h library:

//---------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
47. To test the application, on the main menu, click Run  Run.

10.3 Programmer Created Classes


You can create specifc classes for use in an applications. These classes or structures abide
to C++ classes.

301 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

Chapter 11:
Progress Controls

302 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

11.1 The UpDown Control


Progress Controls are used to monitor an activity, which allows either the programmer or
the user to make decisions. These controls come in various flavors to accomplish
purposes.
A spin button provides the user with an edit box used to increment or decrement values
by clicking a pointing arrow of a tagged adjacent control.

11.1.1 The UpDown Control Properties


To create a spin button, you can use the UpDown control from the Win32 tab. The
control by itself has no meaning. Therefore, you should add an edit control that would
display the spinning value. After adding the UpDown control on the form, use the Object
Inspector to control its properties. The most usually way to add the Edit control is to
position it on the left side of the spin button:

The most important property of the UpDown property is the Associate property. It is
used to specify the control that would display the incrementing value of the control. To
associate a text control to the UpDown control, click the Associate field to display its
combo box. Click the arrow and select the desired control. You can also associate a
control programmatically using code such as:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
UpDown1->Associate = Edit1;
}
//---------------------------------------------------------------------------

The values that display in the associated edit box are short integer numbers. These
numbers range from a minimum controlled by the Min property to a maximum value
controlled by the Max property. By default, a freshly added UpDown control on a from
has its Min and Max set to 0 and 100 respectively. In reality, you can set the minimum
value of the control to –32768 and the maximum to 32767. These values are set using the
Min and Max fields of the Object Inspector. You can change these values
programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
UpDown1->Associate = Edit1;
UpDown1->Min = -224;
UpDown1->Max = -1;
}

303 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

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

If you use numbers in the thousands, the edit control will display the values using the
comma to separate the thousands. This is because the UpDown control is configured, by
default to separate the thousands. You do not want this feature, change the value of the
Thousands property from true to false.

When using the spin button, the user clicks one of the arrows of the control to increase or
decrease the value. By default, the value increases or decreases by 1. If you want the
value to augment by more than 1, set an integer value using the Increment property. To
set the Increment value programmatically, you can use code as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
UpDown1->Associate = Edit1;
UpDown1->Max = 125;
UpDown1->Min = 10;
UpDown1->Increment = 5;
}
//---------------------------------------------------------------------------

When an UpDown control is accessed, the value it displays is usually set by its Position.
You can use this property to set which value the edit control would display when the
control comes up. It should be an integer between the Min and the Max. You can also set
it programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
UpDown1->Associate = Edit1;
UpDown1->Max = 125;
UpDown1->Min = 10;
UpDown1->Increment = 5;
UpDown1->Position = 55;
}
//---------------------------------------------------------------------------

The Position property also allows you to find out the value of the UpDown control at any
time. After setting the Increment value, when the user clicks the arrow buttons, the value
would increase accordingly. When the maximum value is reached, the control would use
the Wrap property to find out what to do. If the Wrap Boolean property is set to false
(the default, the increment would stop at the Max value even if the Max valus is not
divisible by the Increment. The same goes for the Min value. If the Wrap property is set
to true and if the user increases the value of the control, the incrementing would stop to
the last value divisible by the Increment but less than the Max; the same would apply
when decrementing the value of the control.

The UpDown control appears with two arrows pointing up and down, respectively. This
feature is control by the Orientation. An alternative is to point the arrows to left and
right. To do this, use the Orientation property to set arrow to your liking.

The UpDown control usually has its associated edit box on the left side. This is
controlled by the AlignButton property. Alternatively, you can ask it to have the Edit
control on is right side by setting the AlignButton property to udRight. At design time,
both controls still display as they are designed. If you change the AlignButton value, the
control would apply the value only at runtime.

304 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

One of the nicest features that make the spin button easy to use is that the user can change
its values by pressing the up and down arro key of the keyboard. This ability is by default
set to true from the Boolean ArrowKeys property. If you want to prevent the user from
using the keyboard to increase or decrease the value of the UpDown control, set the
ArrowKeys property to false.

Practical Learning: Designing an UpDown control


1. Start Borland C++ Builder with its starting form.
2. Change the caption of the form to Progress Controls.
3. From the Standard tab of the Component Palette, add an Edit control to the
form.
4. Change the name of the new edit control to edtSpin and delete the content of the
Text field.

5. On the Win32 tab, click the UpDown control and click on the right side of
the edit box on the form:

6. On the Object Inspector, make sure the AlignButton field displays udRight.
7. Click Associate and type e
8. Notice that the edtSpin name is selected.
9. Make sure the Increment field display 1, the Max field displays 100 and the Min
field displays 0.
10. To test the new control, press F9.
11. On the form, click the up pointing arrow; then click the down pointing arrow,
using the mouse.
12. Press the up and down arrow keys of the keyboard to change the values of the
spin button.
13. After playing with the spin button, close the form.

11.1.2 The UpDown Methods


The UpDown control is created as a TUpDown object. This class has only two methods: a constructor and
a destructor. The TUpDown constructor is used to dynamically create a spin button.

If cannot design a spin button, you can programmatically create one in a function or
event. To do this, declare an instance of a TUpDown object. You need to specify the
control that owns the spin button. This is usually a form but could also be any control
container. You will also have to specify the parent of this control. You can create it as
follows:

305 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TUpDown *Counter = new TUpDown(this);
Counter->Parent = this;
}
//---------------------------------------------------------------------------

Unfortunately, an UpDown control standing alone means nothing; you will need a control
to associate it with. If you already have an Edit control, you can use it. Otherwise, you
may create one dynamically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TUpDown *Counter = new TUpDown(this);
Counter->Parent = this;
TEdit *Displayer = new TEdit(this);
Displayer->Parent = this;
}
//---------------------------------------------------------------------------

Equipped with these controls, you can set their positions and configure their properties. When setting their
dimensions and positions, set the edit box’ width according to the range of values you are planning to
display. If you plan to position the UpDown control to the right side of the edit box, set the UpDown Left
to the left alignment + width of the edit box. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TUpDown *Counter = new TUpDown(this);
Counter->Parent = this;
TEdit *Displayer = new TEdit(this);
Displayer->Parent = this;

Displayer->Left = 16;
Displayer->Top = 16;
Displayer->Width = 32;
Counter->Left = Displayer->Left + Displayer->Width;
Counter->Top = Displayer->Top;
Counter->Min = 12;
Counter->Max = 248;
Counter->Increment = 2;
Counter->Position = 36;
Counter->Associate = Displayer;
}
//---------------------------------------------------------------------------

If you are planning to access the UpDown control from more than one event or function, create it globally
using the form’s header file.

11.1.3 The UpDown Control Events


The main event of the UpDown control occurs when the user clicks one of the arrows.
Whether the user clicks the up pointing arrow to increase or the down pointing arrow to
decrease the value or position of the control, the OnClick event is fired. The pointing

306 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

arrows are represented using the TUDBtnType enumerator that has two values. The up
or right pointing arrow is recognized as btNext while the down or left pointing arrow is
referred to as btPrev. When the user clicks one of the arrows, you can write code to
perform an action depending on the button that was clicked. Using this OnClick event,
you do not have to associate the UpDown control with anedit box to display integers; you
can use the event to format the value or configure any other behavior you see fit. For
example, instead of displaying an integer, you can display a floating number, a string,
anything, that is tradionationally not allowed.

The arrows of the UpDown controlled are configured so that when the user clicks a
pointing arrow, the UpDown control fires the OnMouseDown event; the OnMouseUp
event is fired when the user releases the mouse.

When the user clicks one of the arrows of the UpDown control, the operating system is
notified just before this action occurs. This notification is done through the OnChanging
event. This allows you to perform a last minute configuration before the value or position
of the control changes. You can also use this event to deny changing the value of the
control.

The OnChangingEx event also fires just before the value of the UpDown control
changes. This time, you can set a new value for the control if the change is successful.

It is important that you always make sure that the user can use the up and down arrow
keys of the keyboard to increase or decrease the value of the Updown control. If he user
presses and holds the up array key, the UpDown control wold be incrementing its value
until either the user releases the key or the control reaches its maximum limit. Here is an
example of how to track the OnMouseUp keyboard event of the UpDown control:

void __fastcall TForm1::UpDown1MouseUp(TObject *Sender,


TMouseButton Button, TShiftState Shift, int X, int Y)
{
ShowMessage("You stopped spinning at " + AnsiString(edtSpin->Text));
}

Practical Learning: Using the UpDown OnClick Event

1. Start a new project with the default form.


2. Save the project in a new folder called GasStation

307 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

3. Name the unit as Main and the project as GasStation


4. From the main menu, click Tools  Image Editor
5. From the main menu of Image Editor, click File  New…  Resource File
(.res)
6. Right-click inside of the Untitled.res window and click New  Icon
7. On the Icon Properties dialog box, make sure the 32x32 (Standard Icon) and the
16 Color radio buttons are selected and click OK
8. On the Untitled.res window, double-click Icon to open the edit window.
9. Design the icon as follows:
10. Close the icon editor window.
11. On the Untitled.res window, right-click Icon1 and click Rename
12. Type Pomp and press Enter.
13. On the main menu of Image Editor, click File  Exit
14. When asked whether you want to save Untitled.res, click Yes
15. Locate and select the GasStation folder you created earlier. There is already a
file called GasStation.res. Click it to select it
16. Click Save. When asked whether you want to replace the existing file, click Yes
17. Back in Bcb, on the main menu, click Project  Add to project…
18. Change the Files of Type to Compiled Resource (*.res)
19. Click GasStation.res and click Open.
20. Design the form as follows:

21. The radio buttons are named rdo87, rdo89, and rdo92. Their corresponding Edit
controls are named edt87, edt89, and edt92 respectively. The button is named
btnClose and the UpDown button is named udnGallons. Make sure you add the
bevels. The Edit controls inside the right bevel are named edtUnitPrice,
edtGallons, and edtTotal

308 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

22. On the form, double-click the Close button and implement its OnClick event as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
23. Right-click in the Code Editor window and click Open Source/Header File. In
the private section of the Main.cpp file, declare a double variable named
UnitPrice:

private:
double UnitPrice; // User declarations
24. Display the form. Double-click the 87 radio button to access its OnClick event.
Double-click the other radio buttons. Implement the OnClick events as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::rdo87Click(TObject *Sender)
{
UnitPrice = edtPrice87->Text.ToDouble();
edtUnitPrice->Text = FloatToStr(UnitPrice);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::rdo89Click(TObject *Sender)
{
UnitPrice = edtPrice89->Text.ToDouble();
edtUnitPrice->Text = FloatToStr(UnitPrice);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::rdo92Click(TObject *Sender)
{
UnitPrice = edtPrice92->Text.ToDouble();
edtUnitPrice->Text = FloatToStr(UnitPrice);
}
//---------------------------------------------------------------------------
25. Run the program to test it. Make sure that when you click a radio button, its
price in the corresponding edit box is transferred to the Unit Price edit box.
Change the prices of each category and make sure the changed price display in
the Unit Price edit box when you click the radio buttons again. Close the form to
return to Bcb.
26. To save the project, on the main menu, click File  Save All
27. On the form, click the UpDown to select it. On the Object Inspector, click the
Events tab.
28. Double-click the empty field on the right isde of OnClick and implement it as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::udnGallonsClick(TObject *Sender, TUDBtnType Button)
{
Double Total;
static int Gallons;

309 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

UnitPrice = edtUnitPrice->Text.ToDouble();
if( Button == btNext )
{
edtGallons->Text = Gallons++;
Total = (Gallons * UnitPrice) - UnitPrice;
edtTotal->Text = edtTotal->Text.sprintf("$ %.2f", Total);
}
else
{
edtGallons->Text = 0;
edtTotal->Text = "$ 0.00";
Gallons = 0;
}
}
//---------------------------------------------------------------------------
29. Save the project. Test it. Close it.

11.2 The Spin Button


The Spin button is a Windows control used to increase and decrease value by clicking an
up or down buttons. Visually the spin button resembles the UpDown control. They have
some differences with regard to their respective configuration.

11.2.1 The Spin Button Properties


To add a spin button to your application, use the CSpinButton from the Samples tab of
the Component Palette. You can place the control on a form or any other container.

Two of the properties that differentiate the UpDown from the CSpinButton controls is
that the the CSpinButton allows you to add your own button indicators as bitmaps. To
specify which bitmap must point up on the control, click the ellipsis button on the
UpGlyph field of the Object Inspector. You can also specify a bitmap that would point
down using the DownGlyph property:

11.2.2 The Spin Button Methods


The spin button is equipped with a constructor and a destructor. The TCSpinButton
class’ constructor is typically used to dynamically create a spin button. To do that,
declare an instance of a TCSpinButton class, specifying the owner of the control and its
parent. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TCSpinButton *LetMe = new TCSpinButton(Form1);
LetMe->Parent = Form1;
}

310 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

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

11.2.3 The Spin Button Events


The biggest difference between an UpDown control and a spin button is one the way each
handles the incrementing and decrementing of its values. Simply put, the spin button does
not have a value to the sense of a progress control; you must set, assign, and configure
the value or position of the spin button on your own. While the main event of an Updown
control occurs when the user clicks one of its arrows, to apply a specific behavior, you
can either consider the whole event or find out what button was clicked. The spin button
uses two different events for each button. Clicking the up pointing arrow fires the
OnUpClick event while the OnDownClick event fires when the user clicks the down
pointing arrow.

Practical Learning: Using the Spin Button


1. Start a new project with the default form.
2. On the Standard tab of the Component Palette, click the Edit button and click on
the form.
3. On the Component Palette, click the Samples tab.
4. Click CSpinButton and flick on right side of the Edit control on the form.
5. display the header file of the form. In the private section of the header file,
declare a Value integer as follows;

private:
int Value; // User declarations
6. In the form’s constructor, intialize the value to 0:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Value = 0;
}
//---------------------------------------------------------------------------
7. On the form, click the SpinButton control to select it. On the Object Inspector,
click the Events tab.
8. Double-click the empty field on the right side of OnUpClick and implement the
event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::CSpinButton1UpClick(TObject *Sender)
{
Edit1->Text = Value++;
}
//---------------------------------------------------------------------------
9. On the Object Inspector, double-click the field of the OnDownClick event and
implement it as follows:

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

311 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

void __fastcall TForm1::CSpinButton1DownClick(TObject *Sender)


{
Edit1->Text = Value--;
}
//---------------------------------------------------------------------------
10. To test the form, on the main menu, click Run  Run.
11. After experimenting with the spin button, close the form.

11.3 The Spin Edit Control

Without a doubt, the SpinEdit control is the easiest spin control of the three sets of
updown controls. There is hardly any configuration to do.

To add a SpinEdit to your application, from the Samples tab of the Component Palette,
click the CSpinEdit button and click in the desired location on the form.

11.3.1 The SpinEdit Properties


The SpinEdit control is used to display integer value in the edit box section of the control. The displaying
value is controlled by the MinValue and the MaxValue that can be set in the Object Inspector. You can also
specify their values programmatically as follows;

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
CSpinEdit1->MinValue = -12;
CSpinEdit1->MaxValue = 228;
}
//---------------------------------------------------------------------------

By default, the values of a SpinEdit control increase by 1 and decrease by –1. If that
value is not appropriate for your application, you can change it using the Increment
property in the Object inspector.

When a SpinEdit control appears at startup, the control displays the value 0 even if its
MinValue is set to a value other than 0. To set the default position of the SpinEdit
control, use the Value property. You can control it at desing time or at runtime. If you set
the Value property to a value that is less than the MinValue, the value would be
automatically set to the minimum value. If you try to set it to a value greater than the
MaxValue in the Object Inspector, the Value would be reset to the MaxValue.

11.3.2 The Spin Edit Methods


Like with all windowed control, the CSpinEdit has a constructor and a destructor. The constructor is
typically used to dynamically create the create at runtime. To do this, declare an instance of a TCSpinEdit
class. You must specify the owner and the parent of the control. You can create such a control in an event
or a function. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TCSpinEdit* Staple = new TCSpinEdit(this);
Staple->Parent = this;

312 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

}
//---------------------------------------------------------------------------

You must include the CSPIN.h header file to the form or unit that would be using the Spin Edit control

1. On the Object Inspector, click the Event tab.


2. Double-click the box of the OnMouseUp event and implement it as follows:

3. Test the form.


4. as follows:

5. To display the form, press F12.

6. On follows:

7. To test the CSpinButton control, press F9

11.4 Track Bars


A trackbar is a Windows control used to slide a small bar or pointer, also called a thumb,
along a continuous line. To use the trackbar, the user can drag the thumb in one of two
directions. This changes the position of the thumb. The user can also click the desired
position to place the thumb at the desired location. Alternatively, when the trackbar has
focus, the user can also use the arrow keys of the keyboard to move the slider or thumb.

A trackbar is configured with a set of values from a minimum to a maximum. Therefore,


the user can make a selection included in that range. Optionality, a trackbar can be
equipped with small marks called ticks. These can visually guide the user for the
available positions of the thumb mark. A trackbar can be used as a progress control to
help the user monitor an activity. A trackbar also allows to user to specify a value that
conforms to a range. When equipped with small indicators, also called ticks, a trackbar
can be used to control exact values that the user can select in a range, preventing the user
from setting just any desired value.

To add a trackbar to a form, from Win32 tab of the Component Palette, double-click the
TrackBar button.

Trackbar Properties
The properties of a trackbar control how it displays and behaves. After placing a
TrackBar control on a form of other container, by default, its assumes a horizontal
direction. The direction of the trackbar is controlled by the TTrackBarOrientation
enumerator:

313 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

enum TTrackBarOrientation { trHorizontal, trVertical };

To change the direction of the control, on the Object Inspector, set the Orientation
property to the desired value. For example, to make it vertical, change the field from
trHorizontal to trVertical. To change this property at runtime, assign the desired value
to the property. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TrackBar1->Orientation = trVertical;
}
//---------------------------------------------------------------------------

The Min property controls the minimum positional value of the control while the Max
value controls the opposite. The user is allowed to slide only between these two values.
These two properties are set in Object Inspector using their respective fields. By default,
the minimum value is set to 0 and the maximum is 10. As integers, the lowest minimum
allowed is INT_MIN which is –2147483647. The maximum allowed value is INT_MAX
which is 2147483647. To change the minimum or maximum values programmatically,
assign the desired value to the appropriate proprety. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TrackBar1->Min = -1205;
TrackBar1->Max = -540;
}
//---------------------------------------------------------------------------

Always make sure that the minimum value is lower than the maximum. This safe
measure will allow you to better control the current value of the control. At designtime, if
you try inversing the values, C++ Builder would reset them. For example, if the Min field
is 12 and you try setting it to 48 when the Max field is 25, the Min field would be reset to
its original value 12. At runtime, if you try setting wrong values as follows,

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TrackBar1->Min = 55;
TrackBar1->Max = 12;
}
//---------------------------------------------------------------------------

The minimum would be set the previous minimum value the property had and the new
maximum value would be kept. If you do not know for sure which value would be greater
due to an intermediary action of the user, you can write a conditional statement that
would control the minimum and the maximum values.

When using the trackbar, the user can slide the thumb in the desired direction, thus
changing the value of the control. While it is moving, you can control the incrementing of
the thumb. By default, the thumb advances or regresses by 1 unit each time it is slided.
This unit is controlled by the Frequence property.

The thumb’s visual display appears as a small standing pentagon with two straight
borders. Its size is set using the ThumbLength property; the smaller the value, the
narrower the thumb. This ability is controlled by the ThumbLength property. The visual

314 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

apperance of the thumb is controlled by the SliderVisible property whose Boolean value
is by default set to true. Therefore, if you wish to hide the thumb, set its SliderVisible
property to false.

A trackbar is also equipped with small bars “|” that serve as indicators of the position
occupied by the slider. These bars are called ticks. By default, the tick marks are
positioned on the same side the slider is pointing. This conditional position of the ticks is
controlled by the value of TickMarks property set from the TTickMark enumerator:

enum TTickMark { tmBottomRight, tmTopLeft, tmBoth };

By default, when you add a new TrackBar control to a form, it is horizontally oriented,
the slider points down, the tick marks are positioned under the sliding field. In this
setting, the TickMarks property is set to tmBottomRight. To place the tick marks above
the sliding field, change the value of the TickMarks property to tmTopLeft; this also
has the effect of reversing the direction of the slider. As a third option, you can have the
tick marks on both sides of the slider. To get this, set the TickMarks property to tmBoth.
With this value, the thumb becomes a small rectangle (changing from its pentagon
shape).

The sliding field of a trackbar is a rectangle with a with background. It stayed white even
as the user slides the thumb to change the control’s value.cause their

11.4.1 Designing a Track Bar

1. From the Win32 tab, click the TrackBar control and click on the form
under the existing control. That’s all it takes.
2. On the Object Inspector, change the Cursor field to crHandPoint.
3. Click Frequency and type 2
4. Click Max and type 20
5. Change the TickMarks to tmTopLeft
6. To test the program, press F9.
7. Slide the pointer of the track bar to the right and left, using the mouse.
8. While the trackbar has focus, use the left and right arrow keys on the keyboard
to change its positions.
9. Close the form

11.4.2 Track Bar Events


A track bar is important when you can get its value and use it in a transaction. The most
fundamental operation you can do is to display its value in an edit or a label controls.
When the value of the track bar changes, we will use its OnChange event to track its
position and display its value on a label.

1. From the Standard tab of the component palette, add a label to the form and
under the track bar control.
2. On the form, double-click the TrackBar to access its OnChange event.

315 © FunctionX, Inc.


Windows Controls 1 Borland C++ Builder

3. Implement it as follows:

void __fastcall TForm1::TrackBar1Change(TObject *Sender)


{
Label1->Caption = TrackBar1->Position;
}

4. Test the form and return to Bcb


5. On the Object Inspector, double-click the box of the OnKeyUp event and
implement it as follows:

void __fastcall TForm1::TrackBar1KeyUp(TObject *Sender, WORD &Key,


TShiftState Shift)
{
if( (Key == VK_LEFT) || (Key == VK_RIGHT) )
edtSpin->Text = TrackBar1->Position;
}

6. Test the program

11.5 Progress Bars


The Progress Bar is used to display the evolution of an activity, especially for a long
operation. Like a label control, a progress bar is used only to display information to the
user who cannot directly interact with it.

The Progress Bar is created using the ProgressBar control from the Win32 tab.

Practical Learning: Progress Bars

1. Create a new project with the starting form


2. We will need a spin button to monitor the progress control.
On the Component Palette, click the Samples tab. Click the CSpinEdit control
3. Click on the top section of the form.
4. On the Object Inspector, change the MaxValue to 100 and the MinValue to 0
5. On the Object Inspector, click the Win32 tab.
6. Click the ProgressBar control and click on the form under the spin button. Make
sure the Max value is set to 100

316 © FunctionX, Inc.


Borland C++ Builder Lists

7. On the form, double-click the spin button to access its OnClick event.
8. Implement it as follows:

void __fastcall TForm1::CSpinEdit1Change(TObject *Sender)


{
ProgressBar1->Position = CSpinEdit1->Value;
}
9. To test the progress bar, press F9
10. When the form displays, increase the value of the spin button and notice that the
position or selection of the progress bar changes.
11. After viewing the form, close it.
12. To display the form, press F12.
13. On the Win32 tab of the Object Inspector, click the TrackBar control.
14. While the track bar is still selected, change its Max value to 100
15. On the form, double-click the track bar and implement its OnChange event as
follows:

void __fastcall TForm1::TrackBar1Change(TObject *Sender)


{
ProgressBar1->Position = TrackBar1->Position;
}
16. To test the form, press F9.

11.6 ScrollBars

A scrollbar is a control that allows the user to navigate a document in two directions
along a control by clicking the mouse on the appropriate arrow. This control can assume
only one of two directions: horizontal or vertical. For its functionality, a scroll bar is
made of three parts:
1. a button arrow of each side of the control: Up or Down .
2. a horizontal or vertical bar
3. a scrolling region

To use a scrollbar control in your application, on the Standard tab of the Component
Palette, click the ScrollBar button and click on the form, then configure its properties.

11.6.1 The ScrollBar Properties


There are two forms of the scroll bars. The horizontal scroll bar allows the user to scroll
in the left and right directions. The vertical scroll bar allows scrolling up and down. By
default, when you add a scroll bar to a form, the control assumes the horizontal position.
This position is controlled by the Kind property, which, by default, is sbHorizontal. To
change the direction of the control to vertical, set this property to sbVertical. The Kind
property is controlled using the TScrollBarKind enumerator defined as follows:

enum TScrollBarKind { sbHorizontal, sbVertical };

317 © FunctionX, Inc.


Borland C++ Builder Lists

To set this property programmatically, assign the desired value to this property. Here is
an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
}
//---------------------------------------------------------------------------

When using a scroll bar, the user can navigate from one end of the control to the other
end. These are the control’s minimum and maximum values. For a horizontal scrollbar,
the minimum is the far left position that the bar can assume; for a vertical scrollbar, this
Note would be most bottom position. The maximum would be the opposite. These two values
The Min value must are controlled by the Min and Max properties. By default, a newly added scrollbar allows
always by less than the scrolling from 0 to 100. To change these values at design time, type an integer number
Max value. for each field in the Object Inspector. The lowest number the Min property can have is –
2147483648 and the highest number for Max would be 2147483647. To change any of
these properties programmatically, you can use code such as:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
ScrollBar1->Min = -122;
ScrollBar1->Max = 240;
}
//---------------------------------------------------------------------------

The primary technique the user applies to a scrollbar is to click one of the arrows at the
ends of the control. As the bar slides insides of the control, it assumes an integer position
from Min to Max. At design time, you can use the Position property to set the position
that the scrollbar would assume when the form opens. If you set the Position to a value
less than the Min, the Object Inspector would restore it to the Min. If you set a Position
greater than the Max, the Object Insopector would assign it the Max value. To
programmatically set the position of the bar, assign the desired value, which must be
between Min and Max, to the Position property. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
ScrollBar1->Min = -122;
ScrollBar1->Max = 240;
ScrollBar1->Position = 38;
}
//---------------------------------------------------------------------------

When the user clicks an arrow of a scrollbar, the bar slides one unit. This unit is called
SmallChange and is set to 1 by default. If you want the bar to slide more than one unit,
change the SmallChange property to an integer value between Min and Max. The bigger
the value, the faster the sliding would occur because the bar would jump by
SmallChange units. You can also set this value programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)

318 © FunctionX, Inc.


Borland C++ Builder Lists

{
ScrollBar1->Kind = sbVertical;
ScrollBar1->Min = -122;
ScrollBar1->Max = 240;
ScrollBar1->Position = 38;
ScrollBar1->SmallChange = 4;
}
//---------------------------------------------------------------------------

There are two main ways the user can scroll faster using scrollbars: by pressing either
page buttons or by clicking the scrolling region. The amount covered using this technique
is controlled by the LargeChange property. Once again, the user can scroll only between
Min and Max; this means you can set this value only to an integer from Min to Max. To
find the scrolling amount, the compiler would divide the actual scrolling range (the
difference between the Max and Min) by the LargeChange value. When the user clicks
in the scrolling region or presses the Page Up or Page Down keys, the bar would jump by
LargeChange up to the scrolling amount value. You can change the LargeChange
property programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
ScrollBar1->Min = -122;
ScrollBar1->Max = 240;
ScrollBar1->Position = 38;
ScrollBar1->SmallChange = 4;
ScrollBar1->LargeChange = 20;
}
//---------------------------------------------------------------------------

The bar inside the scroll region has a size relative to the Min and Max value. By default,
it is square of the approximate size of the arrow buttons. This size of the bar is controlled
by the PageSize property. Approximately, this represents the percentage of the scrolling
range (the difference between the Max and Min). You can change this value at design
time in the Object Inspector, by an integer value between Min and Max. To change it
programmatically, assign the desired integer to the PageSize property. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ScrollBar1->Kind = sbVertical;
ScrollBar1->Min = -122;
ScrollBar1->Max = 240;
ScrollBar1->Position = 38;
ScrollBar1->SmallChange = 4;
ScrollBar1->LargeChange = 20;
ScrollBar1->PageSize = 85;
ScrollBar1->PageSize = 75;
}
//---------------------------------------------------------------------------

Practical Learning: Scroll Bars


1. Create a new project.

319 © FunctionX, Inc.


Borland C++ Builder Lists

2. To add a scroll bar, on the Standard tab of the Component Palette, click the

ScrollBar control .
3. Click on the form.
4. Move the scroll bar to the top left section of the form.
5. While the scrollbar is still selected, on the Object Inspector, click the Max field
and type 150
6. To add another scrollbar, on the Component Palette, double-click the ScrollBar
control
7. While the second scroll bar is still selected, on the Object Inspector, click the
Kind field.
8. Click the arrow of the Kind field and selected sbVertical
9. Move the second scroll bar to the middle section of the form
10. Click the Max field and type 180
11. Click the Min field and type 20

11.6.2 The ScrollBar Methods


The ScrollBar control is equipped with a constructor, TScrollBar, that is typically used
to dynamically create a scrollbar. To do this, declare an instance of a TScrollBar object.
Specify the owner of the control, which is usually the form on which it is positioned.
Also specify the parent of the control. This is usually the form but can also be any
container that is hosting the scroll bar. This dynamic creation can be inside of an event or
a function. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;
}
//---------------------------------------------------------------------------

After declaring the variable, you can set its properties as desired. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;

Scroller->Left = 24;
Scroller->Width = 228;
Scroller->Top = 35;
Scroller->Kind = sbVertical;
Scroller->Max = 1500;
Scroller->Position = 780;
Scroller->SmallChange = 5;
Scroller->LargeChange = 150;

320 © FunctionX, Inc.


Borland C++ Builder Lists

Scroller->PageSize = 250;
}
//---------------------------------------------------------------------------

Another method of a the TScrollBar class is the SetParams(). It allows you to set the
Position, Min, and Max values using one function. Here is an example of using it;

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TScrollBar * Scroller = new TScrollBar(Form1);
Scroller->Parent = Form1;

Scroller->Left = 24;
Scroller->Width = 228;
Scroller->Top = 35;
Scroller->Kind = sbVertical;
// Scroller->Max = 1500;
// Scroller->Position = 780;
Scroller->SmallChange = 5;
Scroller->LargeChange = 150;
Scroller->PageSize = 250;
Scroller->SetParams(780, 0, 1500);
}
//---------------------------------------------------------------------------

11.6.3 Scroll Bar Events


The most fundament event of a scrollbar occurs when the bar slides. This happens when:
• The user clicks one of the arrows.
• The user presses one of the arrow keys.
• The user presses Page Up or Page Down

Every time the user performs one of these actions, the position of the bar changes unless
it is already at one of the extremes. When the position of the bar has changed, a message
is sent to the operating system that the bar has changed its position. Using the OnChange
event of the scrollbar, you can tell the compiler what to do. Fundamentally you can find
out the new position and display it on a label. Here is an example:

void __fastcall TForm1::ScrollBar1Change(TObject *Sender)


{
Label1->Caption = ScrollBar1->Position;
}

The OnScroll event occurs when the user scrolls the bar. This event is appropriate if or
when you want to capture the specific action that caused the scrolling action. These
actions relate to the TScrollCode enumerator:

321 © FunctionX, Inc.


Borland C++ Builder Lists

enum TScrollCode {scLineUp, scLineDown, scPageUp, scPageDown, scPosition,


scTrack, scTop, scBottom, scEndScroll};

The syntax of the OnScroll event is:

void __fastcall (__closure *TScrollEvent)(System::TObject* Sender, TScrollCode


ScrollCode, int &ScrollPos);

Practical Learning: Using the ScrollBar Events

We will create a small application simply used to change the background color of a form.
There are three entities in this application that need to be synchronized as closely as
possible. When the form starts, we have made sure that the positions of the scroll bars,
the values in the edit boxes and the color of the Preview panel are synchronized. When
the user scrolls any of the scrollbars, we will change the color of the Preview panel and
allow the corresponding edit box to keep with the position of the its scrollbar. When the
user changes the value in an edit box, we will update the position of the corresponding
scrollbar and change the color of the Preview panel.

1. Start a new project with a new form.


2. Change the form’s dimensions to Height = 340 and Width = 415
3. Change its Caption to Color Variation
4. From the Standard tab of the Component Palette, double-click the ScrollBar
control.
5. On the Object Inspector, change the Kind field to sbVertical
6. Change the name to scrRed
7. Set the Max value to 255 and Min to 0
8. Set the Position value to 0
9. Move the scroll bar to Left = 328 and Top = 24

322 © FunctionX, Inc.


Borland C++ Builder Lists

10. On the form, click the scrollbar control to select it.


11. Press Ctrl + C to copy the control.
12. Press Ctrl + V to paste it on the form
13. Change the name of the new scrollbar to scrGreen, set its Position to 107, and
move it the right side of the other scrollbar.
14. Click on the form and press Ctrl + V
15. Change the name of the new scroll bar to scrBlue, set its Position to 159, move
it the right side of the other scrollbars.
16. Add an Edit control named edtRed with a Text field of 0
17. Add another Edit control named edtGreen with a Text field of 107
18. Add one more Edit control named edtBlue with a Text field of 159
19. Add a panel named pnlPreview and delete its caption.
20. While the panel is still selected, double-click the value of the Color field to
access the Color dialog box.
21. Change the color values to Red = 0, Green = 107, and Blue = 159
22. Add a second panel to the form. Change its caption to &Close and its name to
pnlClose

23. Design the form according to the figure above.


24. To display the Code Editor, press F12.
25. Right in the Code Editor and click Open Source/Header File.
26. Define the Preview function as follows:

public: // User declarations


__fastcall TForm1(TComponent* Owner);
void __fastcall Preview();
27. Click the .cpp tab.
28. Implement the Preview function as follows:

void __fastcall TForm1::Preview()


{
pnlPreview->Color =
TColor(RGB(scrRed->Position, scrGreen->Position, scrBlue->Position));
}
29. To display the form, press F12.
30. On the form, double-click the scrRed scroll bar and implement its OnChange
event as follows:

void __fastcall TForm1::scrRedChange(TObject *Sender)


{
edtRed->Text = scrRed->Position;
Preview();
}

323 © FunctionX, Inc.


Borland C++ Builder Lists

31. Press F12 to display the form.


32. Double-click the scrGreen scrollbar and implement its OnChange event as
follows:

void __fastcall TForm1::scrGreenChange(TObject *Sender)


{
edtGreen->Text = scrGreen->Position;
Preview();
}
33. Display the form and double-click the scrBlue scrollbar. Implement its event as
follows:

void __fastcall TForm1::scrBlueChange(TObject *Sender)


{
edtBlue->Text = scrBlue->Position;
Preview();
}
34. Display the form and click the edtRed edit control to select it.
35. On the Object Inspector, click the Events tab, and double-click the OnExit field.
36. Implement the OnExit event as follows:

void __fastcall TForm1::edtRedExit(TObject *Sender)


{
b
}
37. Implement the OnExit event of the edtGreen edit control as follows:

void __fastcall TForm1::edtGreenExit(TObject *Sender)


{
if( edtGreen->Text == "" )
edtGreen->Text = "0";
scrGreen->Position = StrToInt(edtGreen->Text);
Preview();
}
38. Implement the OnExit event of the edtBlue edit control as follows:

void __fastcall TForm1::edtBlueExit(TObject *Sender)


{
if( edtBlue->Text == "" )
edtBlue->Text = "0";
scrBlue->Position = StrToInt(edtBlue->Text);
Preview();
}
39. Press F12 to display the form.
40. Double-click the Close panel and implement its OnClick event as follows:

void __fastcall TForm1::pnlCloseClick(TObject *Sender)


{
Close();
}

324 © FunctionX, Inc.


Borland C++ Builder Lists

41. To test the form, press F9.

325 © FunctionX, Inc.


Borland C++ Builder Lists

Chapter 12:
Selection Controls

326 © FunctionX, Inc.


Borland C++ Builder Lists

12.1 Selection Controls


The Microsoft Windows operating systems provide four main style of controls that allow
the user to make a selection of items while interacting with the computer. Radio buttons
and combo boxes allow the user to select one item in a group. A group of check boxes
allows the user select more than one item in a group. Depending on it configuration, a
listbox can let the user to select one or more items on its group. Although they all are
designed to display a list of items, the selection controls are used for different purposes.

12.1.1 Descriptions

Radio Buttons

Radio buttons come in a group


where the user is asked to select
one (and only one) item (at a
time).

The most economical of the group, the Combo Boxes


combo box takes less space by allowing the
user to see only one item at a time. The item
is either set by the program or by a previous
action. Combo boxes have various designs
and can display the list or part of it to the
user.

Check Boxes

Like radio buttons, check boxes come in a group.


This time, the user can select more than one item,
including all those that are available.

327 © FunctionX, Inc.


Borland C++ Builder Lists

List Boxes

As its name implies, a list box


displays a list of items. Like a
group of check boxes, but
depending on the configuration of
the list box, the user can select
more than one item.

Control/Selection One Selection Multiple Selection


Radio Button Yes No
Check Boxes Yes Yes
List Boxes Yes Yes
Combo Boxes Yes No

12.1.2 Radio Button and Check Box Containers


Besides the form, Borland C++ Builder is equipped with three main placeholders for
other controls such as radio buttons, check boxes, and any other that would benefit from a
group. Not only can these hosts provide a good-looking design, but also they can treat
their hosted controls as children, hiding or displaying them as a group.

The GroupBox is the most universally known control as a group holder. It can “carry” or
hold any of the other controls.

The RadioGroup is more appropriate for a group of radio buttons because it is already
equipped to treat those radio buttons as one control holding only one name.

The panel control provides a very efficient means of holding other controls.

12.2 Radio Buttons


A radio button is a control that appears in two parts: a round box “o” and a label. The
label informs the user as to what the control is used for. The user makes his or her
decision by selecting or clicking the round box . In reality, a radio button is
accompanied by one or more other radio buttons that appear and behave as a group. The
user decides which button is valid by selecting only one of them. When the user clicks
one button, its round box fills with a (big) dot: . When one button is selected, the other
round buttons of the (same) group are empty. The user can select another by clicking a
new choice, which empties the previous selection. This technique of selecting is referred
to as mutually-exclusive.

12.2.1 Adding a Radio Button


Because they come in a group, radio buttons should (with emphasis) be organized in a
specific container. To implement their mutual exclusiveness, radio buttons should be
positioned in either a RadioGroup control (the best choice), GroupBox, or a panel. If

328 © FunctionX, Inc.


Borland C++ Builder Lists

you add the radio buttons on this type of container, by default, they will be treated as a
group. You should refrain from positioning radio buttons on the form.

At design time, to create a group of radio buttons, first position a container on the form;
this could be a RadioGroup control. There are two main ways you can create a group of
radio buttons. If you are using a RadioGroup as the container, this control considers its
“children”, the radio buttons it hosts, as a list of strings. Therefore, you can type the label
of each radio button in the String List Editor. The radio buttons created as a list of
strings are not controls to their full extent, althouth this technique provides the fastest and
a very efficient method of creating a group of radio buttons. If you want each radio
button to behave like a full control, first position a GroupBox (the better choice) or a
panel controls on the form. To add each radio button, from the Standard tab of the
Component Palette, click the RadioButton anc click inside of the container.

12.2.2 Radio Button Properties


From the programmer’s standpoint, one of the most important property of any control is
its name. This allows you and the compiler to refer to the control at any time. If you
create your radio buttons using a RadioGroup control, the radio buttons, because they
are string objects, would not have names. If you use a GroupBox or a panel, you can
name each radio button as you fit, respecting C++ naming rules. To set the name of a
control, in the Object Inspector, click Name and type the desired name.

Two properties are of particular importance to both you and the user: the label and the
state of the control. The label is text that specifies what a particular radio button is used
for. If you decide to use a RadioGroup control, after placing it on the form, on the Object
Inspector, click the Items field to reveal its ellipsis button . Click the ellipsis button to
call the String List Editor. To create each radio button, type a label and press Enter for
each

After creating the list, click OK. The container will take care of positioning the radio
buttons so they can fit inside the host. If you type too many or too long strings for the
host, resize the container. If you have a RadioGroup control on the form but could not or
forgot to create a list of radio buttons, you can do so programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
grpEmplStatus->Items->Add("Part-Time");

329 © FunctionX, Inc.


Borland C++ Builder Lists

grpEmplStatus->Items->Add("Full-Time");
grpEmplStatus->Items->Add("Contractor");
grpEmplStatus->Items->Add("Consultant");
}
//---------------------------------------------------------------------------

If you are using a GroupBox or a panel controls to host the radio buttons, after adding it
to the form, on the Component Palette, click the RadioButton and click in the host. To
set the label of a radio button, on the Object Inspector, click Caption and type the desired
label. Repeat this for each radio button. If you want to change a radio button’s caption at
runtime, you can do so programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
rdoGender1->Caption = "&Man";
}
//---------------------------------------------------------------------------

The second of the most important properties of a radio button is its state: whether it is
selected or not. When the user clicks a radio button, it becomes exclusively selected. This
is seen by the dot inside its rounded box. When a radio button is selected, it is said to be
checked. By default, a newly created radio button is not checked. At design time, if you
created the radio buttons using a RadioGroup control, you can set which radio button is
selected by changing the integer value of the ItemIndex property. Since no radio button
is selected by default, its value is –1. The items in the string are counted starting at 0,
then 1, and so on. For example, to set the second radio button as checked, set the
ItemIndex property of the RadioGroup control as 1. This property can be changed only
after the list is created. Therefore, if you create the list programmatically, you can also
decide which radio button would be selected when the list shows up:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
grpEmplStatus->Items->Add("Part-Time");
grpEmplStatus->Items->Add("Full-Time");
grpEmplStatus->Items->Add("Contractor");
grpEmplStatus->Items->Add("Consultant");
grpEmplStatus->ItemIndex = 2;
}
//---------------------------------------------------------------------------

If you create the radio buttons using a GroupBox or a panel controls, you can set a radio
button using the Checked property. This same property allows you to decide which
button would be selected when the form opens. As a Boolean property, to set the
Checked state of a radio button, set this value to true. At runtime, to set a particular radio
button as checked, assign a true value to its name:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
rdoGender2->Checked = True;
}
//---------------------------------------------------------------------------

Once one button has been checked in a group, even if there was no selection in the
beginning, one radio button is always selected in the group. The user cannot deselect all

330 © FunctionX, Inc.


Borland C++ Builder Lists

radio buttons. Only the developper can do this at runtime. By setting the Checked
property of a radio button to false, you can remove its selection.

In the same way you can deselect all radio buttons. If the radio buttons were created
using a RadioGroup control, assign a –1 value to its ItemIndex proerty:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
rdoGender2->Checked = False;
}
//---------------------------------------------------------------------------

Otherwise, you can assign a false value to the Checked property of each radio button.

When dessigning your radio buttons, to manage the space, you can distribute them on
more than one column. If the radio buttons were created using a RadioGroup control, on
the Object Inspector, change the (interger) value of the Columns property. You can also
do this at runtime:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
grpEmplStatus->Items->Add("Part-Time");
grpEmplStatus->Items->Add("Full-Time");
grpEmplStatus->Items->Add("Contractor");
grpEmplStatus->Items->Add("Consultant");
grpEmplStatus->ItemIndex = 2;
grpEmplStatus->Columns = 2;
}
//---------------------------------------------------------------------------

If you want to use various columns on a group of radio buttons created using a
GroupBox or a panel controls, you can visually position each radio button on the
container. Programmatically, you can also change the Left, and Top values of each
control as desired.

By default, a radio button is configured so that the label would be positioned on the right
side of the rounded box. This is controlled by the Alignment property. If you want the
label of the left side, set the radio button’s Alignment property according. The values are:
taRightJustify and taLeftJustify.

Practical Learning: Creating Radio Buttons

1. Click inside the Pizza Sizes group box to select it.


2. Click the Items field.

3. Click its ellipsis .


4. On the String List Editor dialog, type &Small and press Enter
5. Type &Medium and press Enter

331 © FunctionX, Inc.


Borland C++ Builder Lists

6. Type &Large

7. Click OK
8. Notice that a list of radio has been created.
9. On the Component Palette, click the Edit control and click on the form
10. Change the name of the Edit box to edtPizzaSize
11. Click and drag the Pizza Sizes to the top left section of the form.
12. Notice its dependent items move also.
13. Move the Pizza Price group. Notice that its children controls move also.
14. To save the project and create another, on the main menu, click File  New…
15. On the New Items dialog, make sure Application is selected and click OK.
16. When asked to save your project, click Yes.
17. Locate the folder where the exercises are installed.
18. Click the Create New Folder button, type Exo Pizza1 and press Enter twice.
19. After making sure that the Exo Pizza1 folder displays in the Save In combo box,
click Save twice.
20. Start a new project with the default form.
21. Once Bcb is opened with a new form, on the Component Palette, click the Panel
control.
22. On the form, click and drag from the top left section to the middle center
section.
23. Click Caption and press Delete to delete the caption of the panel.
24. On the Component Palette, double-click the RadioButton control
25. Click Caption and type &Addition
26. Click Name and type rdoAddition
27. Move the new radio button to the top section of and inside the panel.

332 © FunctionX, Inc.


Borland C++ Builder Lists

28. On the Component Palette, click the Radio Button


29. Click and drag inside the panel to draw a control of the size you like but keep
the mouse inside the panel.
30. Click Name and type rdoSubtraction
31. Click Caption and type &Subtraction

32. Move the panel to the right section of the form.


33. Notice that it moves with its “children”. You will redesign the form as follows:

34. Add another panel with four labels captioned Number &1:, Number &2:, and
Result:

35. Add three Edit controls inside the panel and on the right side of the
corresponding labels. These edit boxes will be named edtNumber1,
edtNumber2, and edtResult

36. Add another panel to an empty area of the form.


37. While the new and last panel is selected, click the Align field. Click its arrow
and select alBottom.
38. To save the project and open an existing one, on the main menu, click File 
Reopen  …\Exo Pizza 1\Project1.bpr
39. When asked whether to save the project, click Yes.
40. Locate the folder where your exercises are installed
41. Create a new folder called Operations then save Unit1 and the project in it.

333 © FunctionX, Inc.


Borland C++ Builder Lists

12.2.3 Radio Buttons Methods


The primary method you will use with a radio button is the TRadioButton constructor.
This function is mostly used to dynamically create a radio button. Since all objects in
C++ Builder must be called using pointers, to create a radio button, declare an instance of
a TRadioButton object and use the new operator to specify the control that owns the
radio button. A bad idea would be to assign it to the form. As we have reviewed, you
should never (or hardly) position a radio button or a group of radio buttons on a form.
Therefore, before creating a radio button, you should have a container on your form. You
can add such a host at design time or at run time.

The fastest and most convenient way to dynamically create a group of radio buttons
consists of using a RadioGroup control. If you don’t have this control already, either by
adding it at design time or by creating anyhow, you can use the new operator to assign an
instance of the TRadioGroup to the owner of this control. The compiler needs to know
the owner that would have the responsibility of cleaning the RadioGroup once it is not
needed anymore. This time, the owner should be the form, unless the RadioGroup control
will be hosted by another container. Also, specify the parent of the control. If you will
need the radio buttons in just one function or event, you can create the RadioGroup
control in that function. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCreateGroupClick(TObject *Sender)
{
TRadioGroup* Group = new TRadioGroup(Form1);
Group->Parent = Form1;
}
//---------------------------------------------------------------------------

If you are planning to use the control in more than one location, declare a TRadioGroup
object in the private or public sections of the form or unit that would use it:

private: // User declarations


TRadioGroup *grpMaritalStatus;
public: // User declarations
__fastcall TForm1(TComponent* Owner);

To create the list that represents the radio buttons, use the TStrings::Items property of the
RadioGroup control. You can do this in the function where you create the control locally:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCreateGroupClick(TObject *Sender)
{
TRadioGroup* Group = new TRadioGroup(Form1);
Group->Parent = Form1;

Group->Caption = "Membership";
Group->Items->Add("Senior");
Group->Items->Add("Adult");
Group->Items->Add("Tean");
Group->Items->Add("Child");
Group->Columns = 2;
Group->Left = 8;
Group->Top = 20;
}
//---------------------------------------------------------------------------

334 © FunctionX, Inc.


Borland C++ Builder Lists

If the RadioGroup was created globally, use the appropriate function or event to initialize
it:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
grpMaritalStatus = new TRadioGroup(Form1);
grpMaritalStatus->Parent = Form1;
grpMaritalStatus->Items->Add("Single");
grpMaritalStatus->Items->Add("Married");
grpMaritalStatus->Items->Add("Divorced");
grpMaritalStatus->Items->Add("Widow");
grpMaritalStatus->Left = 220;
grpMaritalStatus->Top = 20;
grpMaritalStatus->Height = 100;
grpMaritalStatus->Width = 124;
grpMaritalStatus->Caption = "Marital Status";
}
//---------------------------------------------------------------------------

If you want to create each button as its own object, you will once have to have a
container, designed or dynamically created. The bad news is that you will have to create
each button individually.

Practical Learning: Using Radio Buttons Events


1. Continuing with the operations project,
2. a

12.2.4 Radio Button Events


A radio button is just a special form of button. Its most used event is the OnClick. If you
create the radio buttons using a RadioGroup control, you can use the click event of their
container.

On the other hand, after creating each radio button as a control, you can use its OnClick
event to configure its functionality.

Practical Learning: Radio Buttons Events


1. On the form, double-click the Pizza Sizes RadioGroup control to access its
OnClick event
2. Implement it as follows:

void __fastcall TForm1::grpPizzaSizesClick(TObject *Sender)


{
if( grpPizzaSizes->ItemIndex == 0 )
edtPizzaPrice->Text = "$8.95";
else if( grpPizzaSizes->ItemIndex == 1 )
edtPizzaPrice->Text = "$12.75";

335 © FunctionX, Inc.


Borland C++ Builder Lists

else
edtPizzaPrice->Text = "$14.55";
}
3. To test the form, press F9.
4. Click different radio buttons and observe as the value in the edit box changes.
5. Close the form to return to Bcb.
6. To save the project, on the Standard toolbar, click Save All
7. Open the project of the Exo Pizza program.
8. If the form does not display, press F12.
Double-click the Addition radio button to access its OnClick event.
9. Implement it as follows:

void __fastcall TfrmOperations::rdoAdditionClick(TObject *Sender)


{
double Num1;
double Num2;
double Result;

if( edtNumber1->Text == "" )


Num1 = 0;
else
Num1 = StrToFloat(edtNumber1->Text);

if( edtNumber2->Text == "" )


Num2 = 0;
else
Num2 = StrToFloat(edtNumber2->Text);

Result = Num1 + Num2;


edtResult->Text = Result;
}
10. Click the arrow on the top section of the Object Inspector and select
rdoSubtraction.
11. Click the Events tab.
12. Double-click the empty box on the right side of OnClick.
13. Implement the function just like the Click event of the addition but change the
operation as follows:

Result = Num1 - Num2;


14. On the Object Inspector, select rdoMultiplication.
15. Double-click the box of the OnClick field.
16. Implement the Click event like the previous two but change the operation as
follows:

Result = Num1 * Num2;

336 © FunctionX, Inc.


Borland C++ Builder Lists

17. In the same way, access the OnClick event for the rdoDivision control and
implement it as follows:

void __fastcall TfrmOperations::rdoDivisionClick(TObject *Sender)


{
double Num1;
double Num2;
double Result;

if( edtNumber1->Text == "" )


Num1 = 0;
Else
Num1 = StrToFloat(edtNumber1->Text);

if( edtNumber2->Text == "" )


{
MessageBox(NULL, "The Number 2 Edit Box should not be empty",
"Algebraic Operations", MB_OK);
edtNumber2->SetFocus();
}
else if( edtNumber2->Text == 0 )
{
MessageBox(0, "Cannot divide by zero",
"Algebraic Operations", MB_OK);
edtNumber2->SetFocus();
}
else
{
Num2 = StrToFloat(edtNumber2->Text);
Result = Num1 / Num2;
edtResult->Text = Result;
}
}
18. To display the form, press F12.
19. Double-click the panel on the bottom section of the form to access its Click
event and implement it as follows:

void __fastcall TfrmOperations::Panel3Click(Tobject *Sender)


{
Close();
}
20. To test the form, press F9.

337 © FunctionX, Inc.


Borland C++ Builder Lists

ListView

procedure TForm1.btnLargeClick(Sender: TObject);


begin
ListView1.ViewStyle := vsIcon;
end;

procedure TForm1.btnSmallClick(Sender: TObject);


begin
ListView1.ViewStyle := vsSmallIcon;
end;

procedure TForm1.btnListClick(Sender: TObject);


begin
ListView1.ViewStyle := vsList;
end;

procedure TForm1.btnDetailsClick(Sender: TObject);


begin
ListView1.ViewStyle := vsReport;
end;

42. RadioGroup control . Operations then save Unit1 and the project in it.

12.3 Check Boxes

A check box is a Windows control that allows the user to set or change the value of an
item as true or false. Although it can appear by itself, a check box usually comes in a
group with others, allowing the user to select as many choices as are available.

338 © FunctionX, Inc.


Borland C++ Builder Lists

Depending on the application, a little square  appears with a check box and a label.
The user makes his or her selection by clicking in the square which toggles a check mark
. Toggling means that if the square were empty , after clicking it, a check mark
would appear in it ; otherwise, the check mark would be removed. Some environments
offer a different kind of check mark: .

From the user’s standpoint, a check box is selected when its check mark is set; and the
item is not selected when its square is empty.

From the developer standpoint, a check mark has two (Boolean) values: true or false (or
TRUE or FALSE, or True or False). When a check mark is selected, its value is true;
otherwise, its value is false.

A check mark is a special button and can be programmed as a regular button. Therefore,
depending on the application’s needs, you can display or hide it, enable or disable it as
necessary; you can adjust the control’s behavior depending on other controls on the same
form, the same application, or external factors.

Check boxes provide “non-exclusive” choice, which means each check box can behave
as independent as needed with regard to the other check boxes of the same group.
Therefore, although not recommended, you can create check boxes anywhere on the
form. It is recommended that you include them in rectangular container so their
belonging to the same group will be obvious to the user. The group can be hosted by a
GroupdBox (recommended) or a Panel controls. You can also design the group in a Bevel
control but, since the bevel is not a container, you will not be able to perform some of
moving and toggling operations you get with the first suggested controls.

12.3.1 Check Box Properties


If you are planning to have just one check box, from the Standard tab of the Component
Palette, click the CheckBox control and click on the desired section of the form or
container. If you are planning to use more than one check box, you should first position a
group control to your form, then add the desired CheckBox controls.

The most obvious property of the check box is its state as being checked or not. By
default, a check box is not checked (it is empty). At design time, you can make sure that a
check box appears checked or not by changing the Boolean value of the Checked
property in the Object Inspector. When you set this property, it would be updated
automatically on the form. You or the user can also control this property at runtime. To
change the Checked property programmatically, you could write:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
CheckBox1->Checked = True;
}
//---------------------------------------------------------------------------

When a check box is clicked, its Checked property has a value of true; otherwise, the
values is false. Since the Checked property is a Boolean value, you can toggle its state
based on an intermediary action from the program, the user, or the computer:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

339 © FunctionX, Inc.


Borland C++ Builder Lists

CheckBox1->Checked = !CheckBox1->Checked;
}
//---------------------------------------------------------------------------

Probably the most important property of a check box is its caption, which is controlled by
the Caption property. This can easily be set at design or runtime. The position of the
caption is controlled by the Alignment property. By default, the check box caption is
aligned to the right side of the check box:

Right-Aligned Caption Left-Aligned Caption

To change the caption alignment of a check box, use the Alignment property of the
Object Inspector. The values are taRightJustify for the right alignment and the
taLeftJustify.

Fundamentally, a check box can have only one of two states: checked or unchecked.
When a check box’ checked property is dependent of other controls or actions,
sometimes, you cannot categorically set it to Checked or not Checked. Imagine that, in a
certain company, for an employee to qualify for stock options, he or she must be have a
full-time status and must have been in the company for at least two years. If an
(important) employee fulfills one of these requirements bu not the other requirements,
you can gray out the Stock Options check box. since the control would not be completely
checked, you can show it as half checked:

This property is set using the AllowGrayed property. In the Object Inspector, change the
(Boolean) of the desired check box to true or false (the default). Programmatically, to set
this property, assign it a true value (because otherwise the false value is set by default).

At design time or when the user is interacting with your application, you can control the
display of a check box using one of three states. Unlike being checked or unchecked, like
the AllowGrayed property, you can set an intermediary that would help you and user
know that the control’s condition cannot be definitely decided. This is set using the State
property. This property, derived from the TCheckBoxState enumrator, allows you to set

340 © FunctionX, Inc.


Borland C++ Builder Lists

a check box as unchecked (the default) by assigning the cbUnchecked value; to


definitely check it, set this property to cbChecked. As a 3rd alternative, you can assign it
a cbGrayed value.

Practical Learning: Designing Check Boxes

1. Create a new project with the starting application.


2. Change its caption to Employment Application
3. On the Standard tab of the Component Palette, click Panel and click on the form.
4. Click Caption and type Operating Systems
5. On the Standard tab, click the Label control and click inside the panel on the top
section.
6. Type What operating systems have you used in the past? and press Enter
7. To add a check box, on the Component Palette, double-click the CheckBox
control to add it to the selected panel.
8. Type MS-DOS
9. Add the other check boxes to the existing panel.
10. From the Standard tab, click the Panel control and click to the right side f the
form and outside of the existing panel.
11. Add the other check boxes to complete the application.

12.3.2 Check Box Methods and Events


The check box control has only its constructor and its desturctor as methods. The
constructor allows you to dynamically create the control. To do this, use the new operator
to assign a TCheckBox object to the named instance of the control. You must also specify
what control, namely the form, owns the check box because the compiler wants to know
“who” would clean after the object when the object is not used anymore:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)

341 © FunctionX, Inc.


Borland C++ Builder Lists

{
TCheckBox* Checker = new TCheckBox(Form1);
Checker->Parent = Form1;
}
//---------------------------------------------------------------------------

If the check box will be hosted by a container other than the form, specify this as the parent:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TCheckBox* Checker = new TCheckBox(Form1);
Checker->Parent = GroupBox1;
}
//---------------------------------------------------------------------------

If you do not have or cannot get a container at designe time, you can also dynamically create one that
would host the dynamic check boxes. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TGroupBox* Group = new TGroupBox(Form1);
Group->Parent = Form1;
Group->Left = 16;
Group->Top = 32;
Group->Caption = "Preferred Sports";

TCheckBox* chkFootball = new TCheckBox(Form1);


chkFootball->Parent = Group;
chkFootball->Left = 16;
chkFootball->Top = 16;
chkFootball->Alignment = taRightJustify;
chkFootball->Caption = "Football";
chkFootball->Checked = True;

TCheckBox* chkHandball = new TCheckBox(Form1);


chkHandball->Parent = Group;
chkHandball->Left = 16;
chkHandball->Top = 36;
chkHandball->Caption = "Handball";
}
//---------------------------------------------------------------------------

To create this control globally, that is, to make it accessible by more than one function, method or event,
declare it in the private or public sections of the header file of the unit or object (control) that would “own”
it. We have seen various examples of doing this already.

12.3.3 Project: The Danilo Pizza Application

342 © FunctionX, Inc.


Borland C++ Builder Lists

1. Start a new project. Change the name of the form to Pizza.


2. Save the project as DaniloPizza in a new folder called DaniloPizza. Save the
unit as Pizza
3. Design the form with the following properties:

Form Name Pizza


BorderStyle bsDialog Height 330
Caption Danilo Pizza Width 412
RadioGroup Height 90
Caption Size Top 8
Left 8 Width 161
RadioButton Left 24
Caption Small
Name rdoSmall Top 24
RadioButton
Caption Medium Left 24
Name rdoMedium Top 46
RadioButton
Caption Large Left 24
Name rdoLarge Top 68
Edit Text 8.95
Left 120 Top 24
Name edtSmall Width 41
Edit Text 12.75
Left 120 Top 46
Name edtMedium Width 41
Edit Text 14.55
Left 120 Top 68
Name edtLarge Width 41

343 © FunctionX, Inc.


Borland C++ Builder Lists

RadioGroup Height 153


Caption Toppings Top 164
Left 8 Width 161
CheckBox
Caption P&epperoni ......$ Left 24
Top 128 Width 97
CheckBox
Caption S&ausage ........$ Left 24
Top 152 Width 97
CheckBox
Caption Ex&tra Cheese .$ Left 24
Top 128 Width 97
CheckBox
Caption On&ions ...........$ Left 24
Top 200 Width 97
CheckBox
Caption O&lives ............$ Left 24
Top 224 Width 97
GroupBox Height 90
Caption Extra Items Left 176
Top 8 Width 217
Label Left 104
Caption Qty Top 12
Label Left 136
Caption Price Top 12
Label Left 168
Caption Total Top 12
Label Left 16
Caption &Buffalo Wings ...... Top 34
Label Left 16
Caption B&read .................. Top 58
Edit Text 0
Left 104 Top 30
Name edtQtyBuffWings Width 25
Edit Text 0
Left 104 Top 54
Name edtQtyBread Width 25
Edit Text 3.25
Left 128 Top 30
Name edtBuffWings Width 41
Edit Text 2.15
Left 128 Top 54
Name edtBread Width 41
Edit Text 0.00
Left 168 Top 30
Name edtTotalBuffWings Width 41
Edit Text 0.00
Left 168 Top 54
Name edtTotalBread Width 41
GroupBox Height 153
Caption Drinks Left 176
Top 104 Width 217

344 © FunctionX, Inc.


Borland C++ Builder Lists

Label Left 104


Caption Qty Top 12
Label Left 136
Caption Price Top 12
Label Left 168
Caption Total Top 12
Label Left 16
Caption P&epsi ................... Top 34
Label Left 16
Caption &Diet Pepsi ............ Top 58
Label Left 16
Caption Sp&rite ................... Top 80
Label Left 16
Caption Orange &Juice ....... Top 104
Label Left 16
Caption Root &Beer ............ Top 128
Edit Text 0
Left 104 Top 30
Name edtQtyPepsi Width 25
Edit Text 0
Left 104 Top 54
Name edtQtyDietPepsi Width 25
Edit Text 0
Left 104 Top 78
Name edtQtySprite Width 41
Edit Text 0
Left 104 Top 102
Name edtQtyOJ Width 25
Edit Text 0
Left 104 Top 126
Name edtQtyRootBeer Width 25
Edit Text 1.45
Left 128 Top 30
Name edtPepsi Width 41
Edit Text 1.45
Left 128 Top 54
Name edtDietPepsi Width 41
Edit Text 1.45
Left 128 Top 78
Name edtSprite Width 41
Edit Text 2.25
Left 128 Top 102
Name edtOJ Width 41
Edit Text 1.25
Left 128 Top 126
Name edtRootBeer Width 25
Edit Text 0.00
Left 168 Top 30
Name edtTotalPepsi Width 41
Edit Text 0.00
Left 168 Top 54
Name edtTotalDietPepsi Width 41

345 © FunctionX, Inc.


Borland C++ Builder Lists

Edit Text 0.00


Left 168 Top 78
Name edtTotalSprite Width 41
Edit Text 0.00
Left 168 Top 102
Name edtTotalOJ Width 41
Edit Text 0.00
Left 168 Top 126
Name edtTotalRootBeer Width 41
Edit Text 0.00
Left 328 Top 264
Name edtTotalOrder Width 58
Label Caption Total Order:
Left 264 Top 270
Button
Caption Close Left 176
Name btnClose Top 264

4. To save the project, on the Standard toolbar, click the Save All button.

5. Double-click the Close button and implement its OnClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::btnCloseClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
6. We are going to write a function that will serve as the central point of the many
calculations involved. This function will take care of calculating the total and
displaying it in the Total edit box.
In the Class Explorer, if necessary, expand the Pizza – Classes
7. Right-click Tpizza and click New Method…
8. Set the name of the function as ShowTotal

346 © FunctionX, Inc.


Borland C++ Builder Lists

9. Set the Function Result as void and and make it __fastcall:

10. Click OK
11. When designing the form, we placed an edit box on the right side of a radio
control. The radio control specifies the pizza that the customer wants. The edit
box shows the price based on the selected size. To start, when the user clicks a
radio button, we will convert the content of its equivalent edit box to a float to
validate the price.
Start implementing the ShowTotal() function as follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::ShowTotal()
{
double PriceSize, TotalOrder;

if(rdoSmall->Checked == True)
PriceSize = StrToFloat(edtSmall->Text);
else if(rdoMedium->Checked == True)
PriceSize = StrToFloat(edtMedium->Text);
else if(rdoLarge->Checked == True)
PriceSize = StrToFloat(edtLarge->Text);

TotalOrder = PriceSize;
edtTotalOrder->Text = edtTotalOrder->Text.sprintf("%.2f",
TotalOrder);
}
//---------------------------------------------------------------------------
12. A radio button is like a regular button. It has an OnClick event that it inherits
from the TControl parent. Whenever the user clicks a certain radio button, we
need to let the ShowTotal() function know that a button has been clicked. This
allows the ShowTotal() function to recalculate the totalorder, thereby adding the
new price and subtracting the old one.

347 © FunctionX, Inc.


Borland C++ Builder Lists

Display the form. Double click each radio button and implement each OnClick
event as follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::rdoSmallClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::rdoMediumClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::rdoLargeClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
13. To test the program, on the main menu, click Run  Run.
14. Test the functionality of the buttons (do not test the other controls). After
making sure that the right price displays in the Total edit box, click the Close
button to return to Bcb.
15. Save the project.
16. When the user clicks one of the check box, we need to get the price of the
corresponding topping, add it to the current total, and display the new total to the
Total edit box. If the user unchecks a check box, we should subtract its value
from the total automatically. Therefore, change the ShowTotal function as
follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::ShowTotal()
{
double PriceSize, Pepperoni, Sausage,
ExtraCheese, Onions, Olives, TotalOrder;

if(rdoSmall->Checked == True)
PriceSize = StrToFloat(edtSmall->Text);
else if(rdoMedium->Checked == True)
PriceSize = StrToFloat(edtMedium->Text);
else if(rdoLarge->Checked == True)
PriceSize = StrToFloat(edtLarge->Text);

if(chkPepperoni->Checked == True)
Pepperoni = StrToFloat(edtPepperoni->Text);
else
Pepperoni = 0;
if(chkSausage->Checked == True)
Sausage = StrToFloat(edtSausage->Text);
else
Sausage = 0;
if(chkExtraCheese->Checked == True)
ExtraCheese = StrToFloat(edtExtraCheese->Text);
else
ExtraCheese = 0;

348 © FunctionX, Inc.


Borland C++ Builder Lists

if(chkOnions->Checked == True)
Onions = StrToFloat(edtOnions->Text);
else
Onions = 0;
if(chkOlives->Checked == True)
Olives = StrToFloat(edtOlives->Text);
else
Olives = 0;

TotalOrder = PriceSize
+ Pepperoni + Sausage + ExtraCheese + Onions + Olives;

edtTotalOrder->Text = edtTotalOrder->Text.sprintf("%.2f", TotalOrder);


}
//---------------------------------------------------------------------------
17. Like radio buttons, check boxes inherit the OnClick event from the TControl
class. When the user clicks a check box, whether to select a topping or to
deselect one, an OnClick event fires. We need to let the ShowTotal() function
know when this happen so it can re-evaluate the total Order.
In the form, double-click each check box to access its OnClick event and
implement them as follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::chkPepperoniClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::chkSausageClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::chkExtraCheeseClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::chkOnionsClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::chkOlivesClick(TObject *Sender)
{
ShowTotal();
}
//---------------------------------------------------------------------------
18. To test the program, run it. Test the check boxes and combine their selection
with the radio buttons to make sure that the order processing works.
19. Close the dialog box to return to Bcb.
20. Save the project.
21. To perform the total order, the compiler will retrieve the content of the total of
each item, because a customer can order more than one unit of an item; for
example the customer could want more than one piece of bread or many bottles

349 © FunctionX, Inc.


Borland C++ Builder Lists

of root beer. The compiler will need only the total price of each unit.
Change the ShowTotal() function as follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::ShowTotal()
{
double PriceSize, Pepperoni, Sausage,
ExtraCheese, Onions, Olives, BWings, Bread,
Pepsi, DietPepsi, Sprite, OJ, RootBeer, TotalOrder;

if(rdoSmall->Checked == True)
PriceSize = StrToFloat(edtSmall->Text);
else if(rdoMedium->Checked == True)
PriceSize = StrToFloat(edtMedium->Text);
else if(rdoLarge->Checked == True)
PriceSize = StrToFloat(edtLarge->Text);

if(chkPepperoni->Checked == True)
Pepperoni = StrToFloat(edtPepperoni->Text);
else
Pepperoni = 0;
if(chkSausage->Checked == True)
Sausage = StrToFloat(edtSausage->Text);
else
Sausage = 0;
if(chkExtraCheese->Checked == True)
ExtraCheese = StrToFloat(edtExtraCheese->Text);
else
ExtraCheese = 0;
if(chkOnions->Checked == True)
Onions = StrToFloat(edtOnions->Text);
else
Onions = 0;
if(chkOlives->Checked == True)
Olives = StrToFloat(edtOlives->Text);
else
Olives = 0;

BWings = StrToFloat(edtTotalBuffWings->Text);
Bread = StrToFloat(edtTotalBread->Text);
Pepsi = StrToFloat(edtTotalPepsi->Text);
DietPepsi = StrToFloat(edtTotalDietPepsi->Text);
Sprite = StrToFloat(edtTotalSprite->Text);
OJ = StrToFloat(edtTotalOJ->Text);
RootBeer = StrToFloat(edtTotalRootBeer->Text);

TotalOrder = PriceSize
+ Pepperoni + Sausage + ExtraCheese + Onions + Olives
+ BWings + Bread
+ Pepsi + DietPepsi + Sprite + OJ + RootBeer;
edtTotalOrder->Text = edtTotalOrder->Text.sprintf("%.2f", TotalOrder);
}
//---------------------------------------------------------------------------
22. (If you want to test the project, on the Debug toolbar, click the Run button. On
the form, type floating point numbers in the total edit boxes and continue testing
the order processing. When finished, close the form).
Save the application.

350 © FunctionX, Inc.


Borland C++ Builder Lists

23. Although the compiler relies on the total of each unit, we need to allow the user
(clerk) to change the quantity ordered on a particular unit. For example, one
customer could want more than one bottle of pepsi and another customer might
want almost anything on the menu.
Every item on the right side of the order form has a quantity and a unit price.
After the user has typed the quantity desired for an item, we will convert such a
quantity to an interger. We could write this conversion for each item but since
many items need this conversion, we will write a function that can validate this
number and pass it back to the method or function that needs it. Since the
quantity that the user types is text that is an AnsiString object, the function will
take a string and return an integer.
In the class Explorer, right-click TPizza and click New Method.
24. Set the name of the function to EvaluateQuantity and its argument to
AnsiString Sqty
25. Set the Function Result as int and make it a __fastcall.
26. Implement the EvaluateQuantity() function as follows:

//---------------------------------------------------------------------------
int __fastcall TPizza::EvaluateQuantity(AnsiString SQty)
{
int Qty;

if(SQty == "")
{
Qty = 0;
}
else
Qty = StrToInt(SQty);

return Qty;
}
//---------------------------------------------------------------------------
27. Now that we can rely on a function to evaluate the quantity of each item, we will
send the content of each Qty edit box when necessary.
To get the real total of each unit, we will multiply the quantity by the unit price.
To get the unit price, we will convert the content of each unit Price from
AnsiString to a floating number. Because the user will not usually change the
price of an item, we will perform both conversions (the conversion of the Qty
string to an integer and the conversion of the unit Price string to float) when the
user changes the Qty value. After multiplying the quantity by the price to get the
total, we will call the ShowTotal() function to ask it to update its price.
On the form, double-click each Qty edit box to access its OnChange event.
Implement them as follows:

//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtyBuffWingsChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtyBuffWings->Text);
Price = StrToFloat(edtBuffWings->Text);

Total = Qty * Price;

351 © FunctionX, Inc.


Borland C++ Builder Lists

edtTotalBuffWings->Text = edtTotalBuffWings->Text.sprintf("%.2f", Total);

ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtyBreadChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtyBread->Text);
Price = StrToFloat(edtBread->Text);

Total = Qty * Price;


edtTotalBread->Text = edtTotalBread->Text.sprintf("%.2f", Total);

ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtyPepsiChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtyPepsi->Text);
Price = StrToFloat(edtPepsi->Text);

Total = Qty * Price;


edtTotalPepsi->Text = edtTotalPepsi->Text.sprintf("%.2f", Total);

ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtyDietPepsiChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtyDietPepsi->Text);
Price = StrToFloat(edtDietPepsi->Text);

Total = Qty * Price;


edtTotalDietPepsi->Text = edtTotalDietPepsi->Text.sprintf("%.2f", Total);

ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtySpriteChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtySprite->Text);
Price = StrToFloat(edtSprite->Text);

Total = Qty * Price;


edtTotalSprite->Text = edtTotalSprite->Text.sprintf("%.2f", Total);

ShowTotal();

352 © FunctionX, Inc.


Borland C++ Builder Lists

}
//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtyOJChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtyOJ->Text);
Price = StrToFloat(edtOJ->Text);

Total = Qty * Price;


edtTotalOJ->Text = edtTotalOJ->Text.sprintf("%.2f", Total);

ShowTotal();
}
//---------------------------------------------------------------------------
void __fastcall TPizza::edtQtyRootBeerChange(TObject *Sender)
{
int Qty;
double Price, Total;

Qty = EvaluateQuantity(edtQtyRootBeer->Text);
Price = StrToFloat(edtRootBeer->Text);

Total = Qty * Price;


edtTotalRootBeer->Text = edtTotalRootBeer->Text.sprintf("%.2f", Total);

ShowTotal();
}
//---------------------------------------------------------------------------
28. Save the project.
29. To test the program, on the Debug toolbar, click the Run button.

12.4 Reviews

12.4.1 Exercises
1. The Zoom dialog box of StarOffice is equipped with 8 radio buttons on the left
section under a label marked Zoom factor.

353 © FunctionX, Inc.


Borland C++ Builder Lists

a. Although the radio buttons do not seem to be hosted by a group control, they
still provide mutual exclusiveness, which means only one radio button can be
checked at a time.
Implement this behavior by making sure that there is no physical border around
the radio buttons.
b. To set a value that is not part of the obvious values. The user must click the
Variable then either start clicking the arrow buttons of the spin control or simply
type an integer value in the spin button. The user can type anything before
clicking OK. If the user types a number between 20 and 400, that value applies
and the dialog box recognizes it. If the user types a floating number between 20
and 400, such as 72.15, the dialog box sets the value to either the floor or the
ceiling, depending on the value that is closer. If the user types any number that
is not in a valid decimal format, the dialog box closes as if the user have clicked
Cancel.
Create a form equipped with a button and an Edit control. Allow the user to type
a valid decimal number in the Edit control.
When the user clicks the button, the Zoom dialog box as on the picture above
would display. Make it so that the radio button whose value is closer to the value
of the Edit box would be selected. After using the Zoom dialog box, if the user
clicks OK, implement the behavior described above and display the valid
returned value in the Edit box. If the returned value is not value, keep the value
that was in the Edit box.
2. A

354 © FunctionX, Inc.


Borland C++ Builder Lists

Chapter 13: Lists Controls

355 © FunctionX, Inc.


Borland C++ Builder Lists

13.1 List Boxes

A list box presents a list of items to choose from.


By default, a list box is created to offer only one
choice to the user. The user is presented with
items each on a line. The user makes a selection
by clicking in the list. Once clicked, an item
becomes highlighted indicating that it is the
current choice. A list box can also be configured
to allow multiple selections.

One of the main reasons for using a list box is to


display a list of items to the user. Sometimes the
list would be very large. If the list is longer than
the available space on a form, the control would
provide a scroll bar that allows the user to
navigate up and down and then access all items of
the list. Therefore, you will have the option of
deciding how many items to display on the list.

13.1.1 Creating a ListBox Control


A list box is immediately derived from the TCustomListBox class and that is where its
properties are set. There are three main ways you add a list box to your form.

To create a list box, click the ListBox control from the Standard tab of the Component
Palette and click on the form. Once the list box is positioned on a container, you can
move it by clicking and dragging the control. You can also resize it using any of the
techniques we learned to add, position, move, and resize controls on a component. If the
list will cover many items, design it so its height can display 8 items at a time; otherwise,
for a list of 8 or less items, use only the necessary height that would accommodate all of
the items.

13.1.2 ListBox Properties


The most fundamental and the most obvious aspect of a list box is the list of items it
displays. The list of items of this control is a TStrings object. If you know the list of
items for the control, there are two easy ways you can create it. To create the list at
design time, on the Object Inspector, click the Items proerty name to reveal its ellipsis
button on the right field . To create the list, click this button to call the String List
Editor, type each item desired, on its own line by pressing Enter.

356 © FunctionX, Inc.


Borland C++ Builder Lists

After creating the list, click OK. To test the control, you can press F9.

To programmatically add the items to a list box, use the TStrings::Add() method. If the
list were empty, the new items would be added to the list. If the list already contained one
or more items, the new items would be added, by default, to the end of the existing
one(s). Here is an example of creating a list of items or adding new ones to a list:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
ListBox1->Items->Add("Chad");
ListBox1->Items->Add("Equatorial Guinea");
ListBox1->Items->Add("Egypt");
ListBox1->Items->Add("Madagascar");
}
//---------------------------------------------------------------------------

As mentioned already, the user mostly interacts with a list box by selecting an item. At
any time you can find out whether a particular item has been selected. This is done using
the TCustomListBox::Selected Boolean property.

When the Items of a list box appear in alphabetical order, the list is said to be sorted. By
default, the items of a list box are not sorted. To arrange the list to ascending order, set
the Sorted property’s value to true. As a Boolean data type, you can set the sorting
feature programmatically as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ListBox1->Sorted = True;
}
//---------------------------------------------------------------------------

If you create an unsorted list, then at one time get it sorted (for example, you can give the
user the ability to sort the list, by clicking a button), the list would be sorted. If an item is
added to the sorted list, the compiler would automatically insert to the right position
following the order. If at another time you allow the user to “unsort” the list, the list
would keep its current order. If another item is added when the list is not sorted, the item

357 © FunctionX, Inc.


Borland C++ Builder Lists

would be positioned at the end of the list. If you want the list to have its original state,
you would have to reset it through code.

If you change the Color property of the ListBox control, its whole background would
appear with that color. If you want each item to have its own color, you would have to
change the style of the list and properly configure it.

When you create a list of items, they appear in one range of columns. If the number of
items exceeds the height, a scrollbar would appear on the control. One alternative you can
use is to span the list on more than one column. This is set using the Columns property.
By default, the Columns value is set to 0, which means the items appear in one column.

If you position the control on a form whose DockSite property is set to true with the the
control has a DragKind property dkDock and the DragMode property set to
dmAutomatic, the user will be able to move the control and position it anywhere inside
the form.

By deafault, the user can select only one item in the list. This is controlled by both the
ExtendedSelect and the MultiSelect properties. If you want the user to be able to select
more than one item, you should set the MultiSelect property to true sinc the
ExtendedSelect property would already be set to true. After the user has selected more
than one item, you can use the TCustomList::SelCount to find out the number of items
that the user would have selected.

The list boxes are designed in three types of style. The default is the lbStandard in
which case each item in the list is an AnsiString object. On the other hand, if you want
each item of the list to display a graphic or a color, you must set the style to an owner
draw. The lbOwnerDrawFixed allows you to set a desired height by each item of the
list. This height is controlled through the ItemHeight property. You can set a different
height for each item if your set the list style to lbOwnerDrawVariable.

The ItemIndex is a property that identifies which item is selected in a list box. This is a
property of highly particular interest. If you try performing an operation thatn requires
that an item be selected and no item is selected, the program would throw an error (it
would crash). The items in a list box are counted from 0, then 1, etc. The first item, at
position 0, can be identified as ListBox1->ItemIndex = 0. If no item is selected in the list,
the TCustomListBox::ItemIndex has a value of –1;

The items of a list box are AnsiString objects created from the TStrings class. This allows
you to use the properties of the TStrings class.

13.1.3 ListBox Methods


The only methods a list box control has on its own are its constructor and its destructor.
The TListBox is typically used to dynamically create a list box. To create a list box inside
of an event or a function, use the new operator. To do this, declare a pointer to a
TListBox class. When declaring this object, the constructor of the TListBox needs to
know the component that owns the control; this is usually the host or container of the list
box. If the ListBox will be placed on a form called Form1, you can create the listbox as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::CreateTheList()
{
TListBox* Liste = new TListBox(this);
Liste->Parent = Form1;

358 © FunctionX, Inc.


Borland C++ Builder Lists

}
//---------------------------------------------------------------------------

If the list box will be positioned on another type of container, such as a panel called
Panel1, you can create it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::CreateTheList()
{
TListBox* Liste = new TListBox(this);
Liste->Parent = Panel1;
}
//---------------------------------------------------------------------------

If you create the list box in a function, a method, or an event, the list will exist only inside
Note of that function: you cannot manipulate it from another function, method, or event. If you
When creating a want the control to be accessed by many functions declare a TListBox object in the
control dynamically in header file of the form where the control will be hosted.. Here is an example:
the header file, You
should declare it in the
public or the private //---------------------------------------------------------------------------
sections of the header #ifndef Unit1H
file. If you declare it in #define Unit1H
the published section,
//---------------------------------------------------------------------------
you would get an
annoying warning #include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
TListBox *Listing;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

After declaring the control, you should initialize it in the form’s contructor. This allows
you to specify the contrainer that will host the control:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Listing = new TListBox(Form1);
Listing->Parent = Form1;
Listing->Left = 120;
Listing->Top = 80;
}
//---------------------------------------------------------------------------

When an application terminates, Borland C++ Builder takes care of destroying all of the
objects that are part of the application. If the objects were created at design time, they are
owned by the form. Since the form is owned by the application, the application would

359 © FunctionX, Inc.


Borland C++ Builder Lists

destroy the form including its hosted controls. If a control was placed on another
container such as a panel, the panel is owned by the form and the form by the application.
The destruction would still be smooth when the application executes. If you dynamically
create a control, you must specify the owner of the control; otherwise the program would
not compile. Since you will have specified the owner or container of the control, when
the application exits, the compiler would destroy the form and its control, which would
include the control you dynamically created. Therefore, you do not have to worry about
the state of the dynamic controls when your application exits. This does not mean that
your application would never produce a memory leak, but it would be highly unlikely.

If you want to explicitly destroy your dynamically created object, use its destructor. The
best place to destroy a global object is to use the delete operator on the OnDestroy event
of the form:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete Listing;
Listing = NULL;
}
//---------------------------------------------------------------------------

If the list box was dynamically created inside of a function, you cannot access it outside
of that function. If it were declared in the header file, you can use any appropriate
method, event, or function to fill the list or to manipulate the control. For example, you
can fill out the Listing control we declared earlier as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Listing->Items->Add("C++ Builder");
Listing->Items->Add("Delphi");
Listing->Items->Add("JBuilder");
Listing->Items->Add("Kylix");
}
//---------------------------------------------------------------------------

Since the items of a list box are derived from the TStrings class, you can use this class’
methods to perform the desired operations on the control. The strings in a list box are
counted starting at 0, then 1, and so on.

To add an item at the end of the list, you can write code such as:

void __fastcall TForm1::btnAddLesothoClick(TObject *Sender)


{
lstCountries->Items->Add("Lesotho");
}

To insert an item in the 2nd position you can write code such as:

void __fastcall TForm1::btnAddSecondClick(TObject *Sender)


{
lstCountries->Items->Insert(1, "Mauritania");
}

To delete the 4th item of the list, you could write:

360 © FunctionX, Inc.


Borland C++ Builder Lists

void __fastcall TForm1::btnDelete4Click(TObject *Sender)


{
lstCountries->Items->Delete(3);
}

If the list contains less than 4 items, the TStrings::Delete() method would ignore the
operation. If you have an Edit control called edtCountry, you can let the user add its
content to the list box when he or she double-clicks the edit box. The code could look as
follows:

void __fastcall TForm1::Edit1DblClick(TObject *Sender)


{
lstCountries->Items->Add(edtCountry->Text);
}

If the user is filling out a list box while typing additional items in an Edit control, the best
and fastest way to add a new item is when the user presses Enter after typing the item. To
implement this behavior, you should find out what key the user pressed. If the user
presses Enter when the edit box has focus, you should make sure the edit box contains a
string. The code could appear like this:

//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
if( Key == 13 ) // If the user presses the Enter key
{
if(Edit1->Text != "") // If Edit1 contains something
{
lstCountries->Items->Add(Edit1->Text); // Add the content of Edit1 to ListBox1
Edit1->Text = ""; // Reset Edit1 and make it empty
}
else // Since Edit1 is empty, display a message
Panel1->Caption = "There is nothing to add";
}
}
//---------------------------------------------------------------------------

The TCustomListBox::Clear() method is used to clear the control of its whole content:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
lstCountries->Clear();
}
//---------------------------------------------------------------------------

Practical Learning: Creating a ListBox Control

1. From the Standard of a list box, double-click Add Lesotho and implement it as
follows:

2. To test the form. Press F9.

361 © FunctionX, Inc.


Borland C++ Builder Lists

3. Click its event as follows:

4. To delete 4th button and implement it as follows:

5. To add the content of an, click the Events tab.

6. To test the form, press F9.


7. Notice the as follows:

8. To test the form, press F9

13.1.4 Operations on List Boxes


The most regular operation users perform on a list box is to select items. This selection is
performed by the user clicking one of the items. Using code, you can also select an item
in the list. To select the 6th item of the list, you could write the code as:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
lstCountries->ItemIndex = 6;
}
//---------------------------------------------------------------------------

When performing your operations, sometimes you will want to find out if a particular
item is selected. You can do this using the ordinal position of the item. For example, to
find out if the 3rd item is selected, you can write:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button7Click(TObject *Sender)
{
if( lstCountries->ItemIndex == 2)
Panel1->Caption = "The third item is selected";
}
//---------------------------------------------------------------------------

If an item is selected, you can allow the user to perform an operation on it. If a string
(that is, any string) is not selected, most operations would fail and the program would
crash. Therefore, usually you should make sure an item is selected. An item is selected
when the value of the TCustomListBox::ItemIndex is not –1. Operations include
displaying the selected item of the list box to an edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
// First find out whether an item is selected
if(lstCountries->ItemIndex != -1) // Put the selected item in the edit
Edit1->Text = lstCountries->Items->Strings[lstCountries->ItemIndex];
}
//---------------------------------------------------------------------------

362 © FunctionX, Inc.


Borland C++ Builder Lists

inserting a new string above the selected item:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
lstCountries->Items->Insert(lstCountries->ItemIndex, Edit1->Text);
}
//---------------------------------------------------------------------------

or under the selected string:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
lstCountries->Items->Insert(lstCountries->ItemIndex + 1, Edit1->Text);
}
//---------------------------------------------------------------------------

Many times during your design, you will allow users to add or delete items to or from a
list box. One way you will do this is to create a list of items originating from another list;
this allows you to control the items the user can select from a list before continuing with
the issue at hand. Borland C++ Builder ships with a dialog box completely configured to
handle this transaction.

To allow two list boxes to exchange data, you provide the appropriate buttons. If only
one list will be used as the source, provide one button that could allow the user to select
an item. It is also a good idea to allow the user to select and add all items at once. Also
important is the ability for the user to remove mistakenly selected items. Over all, these
kinds of list boxes handle their transactions through the use of four buttons: two are used
to exchange one item at a time from one list to another, two to exchange all items from
one list to another.

Practical Learning: Configuring List Boxes

1. To start a new project, on the Standard toolbar, click the New button
2. Make sure the Application icon is selected and click OK
3. To add Borland C++ Builder’s built-in list box dialog, on the Standard toolbar,
click the New button .
4. In the Object Repository, click the Forms property sheet.

363 © FunctionX, Inc.


Borland C++ Builder Lists

5. Click the Dual List Box icon:

6. Click OK.
7. To remove the starting form, press F12 to display the Code Editor.
8. Click the Unit1.cpp to select it.
9. Right-click the Unit1.cpp tab and click Close Page
10. When asked whether you want to save Unit1, click No.
11. To test the application, press F9.
12. Use the existing transfer buttons to exchange items between both list boxes.
13. Close the form using its Windows Close button.
14. On the form, click the Source List label.
15. On the Object Inspector, click Caption and type Cities to locate on a map:
16. Click Destination List and type Cities Selected:
17. To remove the items in the list, click the left list to select it.
18. On the Object Inspector, click the ellipsis button of the Items field.
19. Delete all items in the String List Editor dialog box and click OK.
20. To create our own list, double-click an unoccupied area of the form and
implement the OnCreate event as follows:

void __fastcall TDualListDlg::FormCreate(TObject *Sender)


{

364 © FunctionX, Inc.


Borland C++ Builder Lists

SrcList->Items->Add("Shangai");
SrcList->Items->Add("Melbourne");
SrcList->Items->Add("Kenitra");
SrcList->Items->Add("London");
SrcList->Items->Add("Valencia");
SrcList->Items->Add("Rio de Oro");
SrcList->Items->Add("Santiago");
SrcList->Items->Add("Dublin");
SrcList->Items->Add("Bamako");
SrcList->Items->Add("New Delhi");
SrcList->Items->Add("Tokyo");
SrcList->Items->Add("Alexandria");
SrcList->Items->Add("Boston");
SrcList->Items->Add("Quebec");
SrcList->Items->Add("Dar-Es-Salam");
SrcList->Items->Add("Munich");
}
21. Display the form.
22. Click the Cancel button and press Delete.
23. Also delete the Help button.
24. Double-click the OK button and implement its OnClick event as follows:

void __fastcall TDualListDlg::OKBtnClick(TObject *Sender)


{
Close();
}
25. To test the dialog box, press F9
26. After using the list boxes, click OK to close the form.
27. Press F12 to display the form.
Click the left list to select it.
28. To make sure that double-clicking an item in the left list has the same effect as
clicking the Include button, click the Events tab.
29. Double-click the event of the OnDblClick field and implement it as follows:

void __fastcall TDualListDlg::SrcListDblClick(TObject *Sender)


{
IncludeBtnClick(Sender);
}
30. Display the form and click the right list.
31. On the Object Inspector, double-click the event of the OnDblClick field and
implement it as follows:

void __fastcall TDualListDlg::DstListDblClick(TObject *Sender)


{
ExcludeBtnClick(Sender);
}
32. To test the application, press F9.

365 © FunctionX, Inc.


Borland C++ Builder Lists

13.2 Checked List Boxes

13.3 Combo Boxes

Like a radio button, a combo box allows the user to select one item from a group. Unlike
radio buttons, a combo box saves space by using just as much room as an edit control.
Like a list box, a combo box displays a list of items to the user. Unlike a list box, there is

366 © FunctionX, Inc.


Borland C++ Builder Lists

a version of a combo box that retracts once the user has made a selection; this is useful
when space saving is particularly important.

13.3.1 Combo Box Properties


To add a combo box to your application, from the Standard tab of the Component Palette,
click the ComBox button and click on the form. You can then resize or reposition the
control to the desired location.

Just like every control of your application, the name is the most important property of the
control, for you and the compiler. This name allows you and the compiler to refer to the
control. By default, the first combo box you add to your form at design time is called
ComBox1, the second would be ComboBox2, etc. To change the name of the control,
click the Name field, type a new name and press Enter (or click somewhere else).

Probably the first this the user sees on a combo box is the text it displays. Although the
text of an item is an AnsiString, the items are composed from the TStrings class. To
create this list, when the control is selected on the form, on the Object Inspector, click the
Items field to reveal an ellipsis button. Click the ellipsis button to display the String List
Editor. Type each string and press Enter:

Once you click OK, the control would be filled with the new items. You can also fill out
the control using the methods of the TStrings class. For example, to create a list of items,
you could write:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFillTheListClick(TObject *Sender)
{
cbxColors->Items->Add("Old Blue");
cbxColors->Items->Add("Light Blue");
cbxColors->Items->Add("Salmon");
cbxColors->Items->Add("Dark Violet");
}
//---------------------------------------------------------------------------

367 © FunctionX, Inc.


Borland C++ Builder Lists

By default, the items you add to the combo box will appear in the order they are supplied.
For example the TStrings::Add() method would add the new string at the end of the list.
If you want the list of items to be sorted, you can change the value of the Sorted property
in the Object Inspector from false (the default) to true. To sort a list programmatically,
you can write:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnSortTheListClick(TObject *Sender)
{
cbxColors->Sorted = True;
}
//---------------------------------------------------------------------------

You can unsort the list by changing the value of the Sorted property.
There are three styles of combo boxes, although all allow the user to make only one
selection. These styles are controlled by the TComboBoxStyle enumerator and the Style
property of the Object Inspector. A combo box can be configured to allow the user to add
items to the list. In this case, if the user does not find the desired item in the list, he or she
can type a new one values. To provide this ability, set the Style to csDropDown. If you
set the Style to csDropDownList, the user cannot enter a new item in the list but can still
select one from the control. A combo box with the csSimple Style permanently displays
a combination of an edit box and a list box. The user can scroll in the list box and select
an item; after the selection, the list would still display the list. The other two styles,
csOwnerDrawFixed and csOwnerDrawVariable, are typically used to display varying
objects such as pictures or colors }.

If the combo box has a style other than csSimple, there is typically a fixed number of
items that display when the user click the control’s arrow. You can control the number of
items that displays using the DropDownCount property. By default, this is set to 8. If the
list contains a number of items less than the DropdownCount integer value, all of the
items would display fine. If the list contains more than the DropDownCount number of
items, when the user clicks the arro, a scroll box would appear. The control would display
DropDownCount number of items; to reveal more, the user would have to scroll in the
list.

The text that displays on a non-drawn combo box is an AnsiString object. If you want the
combo box to display a certain string, use the Text property. At design time, you can set
this only if the control’s Style is csDropDown or csSimple. At run time, you can set the
text that would display in the combo box at startup using the ItemIndex property. This
property represents the ordinal integer item of the combo box. The items are counted
from 0, then 1, and si on. The ItemIndex of each item is set depending on the value ot
the Sorted property. If the list is not sorted, the first item entered in the list has an
ItemIndex value of 0. If the list gets sorted, the first item in ascending order has an
ItemIndex property set at 0. You can therefore use this property to control what item to
display in the list:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
cbxColors->ItemIndex = 0;
}
//---------------------------------------------------------------------------

You can also use the ItemIndex property to find out what item is selected at a given time.

368 © FunctionX, Inc.


Borland C++ Builder Lists

Practical Learning: Designing a Combo Box


1. Start a new project with the default form.

2. On the Standard toolbar, click the Save All button


3. Locate the Bcb Exercises folder and display it in the Save As combo box. Create
a folder called Time Sheet
4. Save the unit as Main and the project as TimeSheet
5. Change the caption of the form to Employment Application

6. Add a Panel control to the form: BevelInner = bvLowered; BevelOuter =


bvRaised. Add three labels captioned Employee:, Start Date:, and End Date:
7. Add an Edit control and two MaskEdit control whose EditMask is !99/99/00;1;_
8. Add two labels captioned Time In and Monday as on the picture.
9. Add a combo box under the Time In label as shown on the above picture
10. Set its Style to csDropDownList and make sure the Sorted property is set to
false.

11. Click the Items field and click its ellipsis button . Type 00:00 AM and press
Enter. Type 00:30 AM and press Enter. Type the hourly numbers to complete
the list with the following values: 00:00 AM, 00:30 AM, 01:00 AM, 01:30 AM,
02:00 AM, 02:30 AM, 03:00 AM, 03:30 AM, 04:00 AM, 04:30 AM, 05:00 AM, 05:30 AM,
06:00 AM, 06:30 AM, 07:00 AM, 07:30 AM, 08:00 AM, 08:30 AM, 09:00 AM, 09:30 AM,
10:00 AM, 10:30 AM, 11:00 AM, 11:30 AM, 12:00 PM, 12:30 PM, 01:00 PM, 01:30 PM,
02:00 PM, 02:30 PM, 03:00 PM, 03:30 PM, 04:00 PM, 04:30 PM, 05:00 PM, 05:30 PM,
06:00 PM, 06:30 PM, 07:00 PM, 07:30 PM, 08:00 PM, 08:30 PM, 09:00 PM, 09:30 PM,
10:00 PM, 10:30 PM, 11:00 PM, 11:30 PM

369 © FunctionX, Inc.


Borland C++ Builder Lists

12. Click OK.


13. On the form, make sure the combo box is selected. Press and hold Shift. Click
Time In to select both controls. Release Shift. On the main menu, click Edit 
Copy.
14. Click the panel on the form to select it.
15. On the main menu, click Edit  Paste. While the pasted controls are still
selected, move the selection to the right side of the others. Click somewhere else
to deselect the the pasted controls:

16. Change the 2nd Time In label to Time Out


17. On the form, click Time In
18. Press and hold Shift. Click each combo box and the Time Out label.
19. With the four controls selected, on the main menu, click Edit  Copy
20. On the form, click on the panel to deselect the other controls.
21. On the main menu, click Edit  Paste

370 © FunctionX, Inc.


Borland C++ Builder Lists

22. Move the selected controls to the right side:

23. On the right side of the right Time Out, add a label with a caption as Total
24. Under the Total label, add an Edit control that has a Text property as 8.00

25. On the form, click one of the combo boxes. Press and hold Shift. Click each of
the other combo boxes and the edit box under the Total label. Release Shift
26. On the main menu, click Edit  Copy
27. Click an empty area on the panel to select it.
28. On the menu, click Edit  Paste
29. While the new pasted controls are still selected, move the selection under the
other similar controls:

30. On the panel, select all the combo boxes and the edit boxes under the Total
label. Copy the selection. Click an empty area on the panel. Paste the selection.
Move the selected controls down:

371 © FunctionX, Inc.


Borland C++ Builder Lists

31. On the panel, select all the combo boxes of the top three rows and the top three
edit boxes under the Total label. Copy the selection. Click on the panel. Paste
the selection. Move the selected controls to create seven rows as follows:

32. To continue with the design of the form, add six labels under Monday. Set their
captions to Tuesday, Wednesday, Thursday, Friday, Saturday, and Sunday
respectively.
33. Add a label captioned Total Weekly Hours: and add an Edit control to the right
as in the following picture. Set the Text property of the new Edit control to
40.00

372 © FunctionX, Inc.


Borland C++ Builder Lists

34. Set the names of the ComboBox and Edit controls as in the following table:

cbxMondayIn1 cbxMondayOut1 cbxMondayIn2 cbxMondayOut2 edtMonday


cbxTuesdayIn1 cbxTuesdayOut1 cbxTuesdayIn2 cbxTuesdayOut2 edtTuesday
cbxWednesdayIn1 cbxWednesdayOut1 cbxWednesdayIn2 cbxWednesdayOut2 edtWednesday
cbxThursdayIn1 cbxThursdayOut1 cbxThursdayIn2 cbxThursdayOut2 edtThursday
cbxFridayIn1 cbxFridayOut1 cbxFridayIn2 cbxFridayOut2 edtFriday
cbxSaturdayIn1 cbxSaturdayOut1 cbxSaturdayIn2 cbxSaturdayOut2 edtSaturday
cbxSundayIn1 cbxSundayOut1 cbxSundayIn2 cbxSundayOut2 edtSunday
edtTotalHours
35. Change the Text properties of the edtSaturday and edtSunday Edit controls to
0.00
36. Add two Bevel controls above and under the Time In and Time Out labels. Set
their Shape properties to bsBottomLine. Add another bevel just above the
edtTotalHours Edit box. Here is the complete form:

373 © FunctionX, Inc.


Borland C++ Builder Lists

37. Save All.

13.3.2 ComboBox Methods


The TComboBox as a class has only its constructor and its destructor as methods; its
other methods are derived from the the parent TCustomComboBox class. The
TComboBox constructor is used to dynamically create an instance of the object. If you
cannot add the control at design time, declare an instance of the TComboBox, use the
new operator to assign the control’s owner for cleaning purposes:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCreateComboBoxClick(TObject *Sender)
{
TComboBox *CarMake = new TComboBox(this);
CarMake->Parent = this;
}
//---------------------------------------------------------------------------

If you want the object to be accessible from more than one function or event, declare an
instance of a TComboBox control in the public or private sections of the object, unit or
form that would use it:

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *btnCreateComboBox;
void __fastcall btnCreateComboBoxClick(TObject *Sender);
private: // User declarations
TComboBox *CarModel;
public: // User declarations

374 © FunctionX, Inc.


Borland C++ Builder Lists

__fastcall TForm1(TComponent* Owner);


};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------

In the source file, use the new operator to specify the control owner of the object. If you
want the control created when the form starts, you can do this in the form’s constructor:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CarModel = new TComboBox(this);
CarModel->Parent = this;
}
//---------------------------------------------------------------------------

After creating the object, you can manipulate its properties the change the defaults. If you
create a local list, you will manipulate it in the same function or event:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCreateComboBoxClick(TObject *Sender)
{
TComboBox *CarMake = new TComboBox(this);
CarMake->Parent = this;
CarMake->Left = 32;
CarMake->Top = 16;
CarMake->Items->Add("Ford");
CarMake->Items->Add("Renault");
CarMake->Items->Add("Fiat");
CarMake->Items->Add("Honda");
}
//---------------------------------------------------------------------------

If the object were created globally, you can access it anywhere to manipulate it:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CarModel = new TComboBox(this);
CarModel->Parent = this;
CarModel->Left = 200;
CarModel->Top = 16;
CarModel->Items->Add("Elantra");
CarModel->Items->Add("LeBaron");
CarModel->Items->Add("Corolla");
CarModel->Text = "Corolla";
}
//---------------------------------------------------------------------------

13.3.3 Operations on Combo Box Using Events


There are two mains operations a user will perform on a combox: selecting an item from
the list or changing the content of the list. Many of the events that occur during the use of

375 © FunctionX, Inc.


Borland C++ Builder Lists

a combo box are from other controls or actions that are not programmatically directly
related to a combo box. It is usually possible to fill out the list of a combo box at design
time; that is, if you know the list of items that will be used. Otherwise, you will use
another event or function to provide the items of the list. For example, the OnCreate
event of a form is a common place to fill out a list, especially if you want the list to owns
its items the first time it appears to the user. If you create a combo box named cbxSports
but do not provide its items at design time, you can use the OnCreate event of the hosting
form to fill it up as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
cbxMajor->Items->Add("Accounting");
cbxMajor->Items->Add("Medical Assistant");
cbxMajor->Items->Add("Fire Science");
cbxMajor->Items->Add("Computer Sciences");
cbxMajor->Items->Add("Business Administration");
cbxMajor->Items->Add("Hospitality Management");
cbxMajor->Items->Add("Criminal Justice");
cbxMajor->Items->Add("Computer Technician");
cbxMajor->Items->Add("Cartography");
cbxMajor->Items->Add("Music");

cbxMajor->ItemIndex = 3;
}
//---------------------------------------------------------------------------

The most regular operation a user performs on a combo box is to select an item from the
list. This happens when the user clicks the arrow to expand the list and then clicks one
item. Once the user clicks one of the items, the list disappears and the combo box
becomes a regular edit box, unless the style of the combo box is csSimple. Using this
event, you can find out what item the user would have selected and act accordingly. For
example, you can transfer the selected item to another control such as an edit box. Here is
an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::cbxMajorClick(TObject *Sender)
{
edtMajor->Text = cbxMajor->Items->Strings[cbxMajor->ItemIndex].c_str();
}
//---------------------------------------------------------------------------

Note The OnChange event occurs when the user changes the event that was displaying in the
The ListBox control does edit box of the combo box. Also this event occurs also in response to the user making a
not have an OnChange event selection, it is more appropriate if you allow the user to edit an item of the list or if you
because the user cannot edit allow the user to add items to the list by typing directly in the edit box. Like the Edit
an item in the list. This is
because a list box does not control, the OnChange event occurs immediately as the user types anything in the edit
have an edit portion. box portion of the combo box. The OnClick event cannot respond to these events. You
can use the OnChange event to deal with the user trying to modify the item on the edit
box. You can also use it to respond to other actions associated with the user making a
selection. For example, you can simply display the list the number of items in the list:

//---------------------------------------------------------------------------
void __fastcall TForm1::cbxMajorChange(TObject *Sender)
{
edtCount->Text = IntToStr(cbxMajor->Items->Count);
}

376 © FunctionX, Inc.


Borland C++ Builder Lists

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

Practical Learning: Using Combo Box Events


1. Continuing with our TimeSheet project, since the Style of each combo box is set
to csDropDownList, we could not set their Text property at design time. We will
use the OnCreate event of the form to make a selection for each combo box.
Our time sheet uses two shifts but this allows the user to still sign the time as if
it had happened only once. When the form opens, we will make sure that only
one shift applies. This will give the user the option to change it. To achieve that,
we will set the first time in to 9 o’clock and the last time out to 5 PM. In
between, we just have to make sure that the first time out and the second time in
do not conflict.
Double-click an empty are on the form to access its OnCreate event.
2. Implement the OnCreate event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
// These are the starting times set on each combobox.
// The ItemIndex property is used to set the combobox' selection
cbxMondayIn1->ItemIndex = 18;
cbxMondayOut1->ItemIndex = 24;
cbxMondayIn2->ItemIndex = 24;
cbxMondayOut2->ItemIndex = 34;

cbxTuesdayIn1->ItemIndex = 18;
cbxTuesdayOut1->ItemIndex = 24;
cbxTuesdayIn2->ItemIndex = 24;
cbxTuesdayOut2->ItemIndex = 34;

cbxWednesdayIn1->ItemIndex = 18;
cbxWednesdayOut1->ItemIndex = 24;
cbxWednesdayIn2->ItemIndex = 24;
cbxWednesdayOut2->ItemIndex = 34;

cbxThursdayIn1->ItemIndex = 18;
cbxThursdayOut1->ItemIndex = 24;
cbxThursdayIn2->ItemIndex = 24;
cbxThursdayOut2->ItemIndex = 34;

cbxFridayIn1->ItemIndex = 18;
cbxFridayOut1->ItemIndex = 24;
cbxFridayIn2->ItemIndex = 24;
cbxFridayOut2->ItemIndex = 34;

cbxSaturdayIn1->ItemIndex = 24;
cbxSaturdayOut1->ItemIndex = 24;
cbxSaturdayIn2->ItemIndex = 24;
cbxSaturdayOut2->ItemIndex = 24;

cbxSundayIn1->ItemIndex = 24;
cbxSundayOut1->ItemIndex = 24;
cbxSundayIn2->ItemIndex = 24;
cbxSundayOut2->ItemIndex = 24;
}

377 © FunctionX, Inc.


Borland C++ Builder Lists

//---------------------------------------------------------------------------
3. To test the new combo boxes, on the main menu, click Run  Run
4. The value of each time in or time out is recognized by three parts: the hour, the
minute, and the AM portions. We need a function that can receive these three
parts, decode them and return a time value in decimal format.
Right-click in the Class Explorer and click New Method…
5. Set the Method Name to CalcTime and in the Add To Class combo box, select
TForm1. In the Arguments edit box, type
AnsiString h, AnsiString m, AnsiString AMPM
6. Set the function Result to double and click the __fastcall check box and click
OK.
7. Implement the CalcTime() function as follows:

//---------------------------------------------------------------------------
double __fastcall TForm1::CalcTime(AnsiString h, AnsiString m, AnsiString AMPM)
{
double HourFraction; // This should be an integer, but so what?
double MinuteFraction;

if( AMPM == "PM" ) // Does the time occur in the afternoon?


{
if( h == "12" ) // Is the time at noon?
HourFraction = h.ToInt();
else
HourFraction = 12 + h.ToInt();
}
else // The time occurs in the morning
HourFraction = h.ToInt();

if( m == "00" ) // Does the time fall on exact hour?


MinuteFraction = 0.00; // Initialize the minutes accordingly
else
MinuteFraction = 0.50; // The time is at half of an hour

// Return the time in a 0.00 format, which is a decimal number


return HourFraction + MinuteFraction;
}
//---------------------------------------------------------------------------
8. To get the time portions of a selected time, we need an independent function that
will at all times evaluate the time differences between shifts, calculate and
display the right time in the Total edit box for each day.
Right-click in the Class Explorer and click New Method…
9. Set the Method Name to EvaluateTheTime and in the Add to Class combo box,
select TForm1. Set the Function Result to void. Click the __fastcall check box:

378 © FunctionX, Inc.


Borland C++ Builder Lists

10. Click OK
11. Implement the new function as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::EvaluateTheTime()
{
double MondayShift1, MondayShift2;
double TuesdayShift1, TuesdayShift2;
double WednesdayShift1, WednesdayShift2;
double ThursdayShift1, ThursdayShift2;
double FridayShift1, FridayShift2;
double SaturdayShift1, SaturdayShift2;
double SundayShift1, SundayShift2;
double Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday;
double TotalHours;

// These temporary values are used to segment the content


// of the Time Value in order to perform the desired calculations
AnsiString MondayHourIn1 = cbxMondayIn1->Text.SetLength(2); // Hour Range
AnsiString MondayTempMinuteIn1 = cbxMondayIn1->Text.Delete(1, 3);
AnsiString MondayMinuteIn1 = MondayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString MondayAMPMIn1 = cbxMondayIn1->Text.Delete(1, 6); // AMPM
double MondayIn1 = CalcTime(MondayHourIn1, MondayMinuteIn1, MondayAMPMIn1);

AnsiString MondayHourOut1 = cbxMondayOut1->Text.SetLength(2); // Hour Range


AnsiString MondayTempMinuteOut1 = cbxMondayOut1->Text.Delete(1, 3);
AnsiString MondayMinuteOut1 = MondayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString MondayAMPMOut1 = cbxMondayOut1->Text.Delete(1, 6); // AMPM
double MondayOut1 = CalcTime(MondayHourOut1, MondayMinuteOut1, MondayAMPMOut1);

AnsiString MondayHourIn2 = cbxMondayIn2->Text.SetLength(2); // Hour Range


AnsiString MondayTempMinuteIn2 = cbxMondayIn2->Text.Delete(1, 3);

379 © FunctionX, Inc.


Borland C++ Builder Lists

AnsiString MondayMinuteIn2 = MondayTempMinuteIn2.SetLength(2); // Minute Range


AnsiString MondayAMPMIn2 = cbxMondayIn2->Text.Delete(1, 6); // AMPM
double MondayIn2 = CalcTime(MondayHourIn2, MondayMinuteIn2, MondayAMPMIn2);

AnsiString MondayHourOut2 = cbxMondayOut2->Text.SetLength(2); // Hour Range


AnsiString MondayTempMinuteOut2 = cbxMondayOut2->Text.Delete(1, 3);
AnsiString MondayMinuteOut2 = MondayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString MondayAMPMOut2 = cbxMondayOut2->Text.Delete(1, 6); // AMPM
double MondayOut2 = CalcTime(MondayHourOut2, MondayMinuteOut2, MondayAMPMOut2);

AnsiString TuesdayHourIn1 = cbxTuesdayIn1->Text.SetLength(2); // Hour Range


AnsiString TuesdayTempMinuteIn1 = cbxTuesdayIn1->Text.Delete(1, 3);
AnsiString TuesdayMinuteIn1 = TuesdayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString TuesdayAMPMIn1 = cbxTuesdayIn1->Text.Delete(1, 6); // AMPM
double TuesdayIn1 = CalcTime(TuesdayHourIn1, TuesdayMinuteIn1, TuesdayAMPMIn1);

AnsiString TuesdayHourOut1 = cbxTuesdayOut1->Text.SetLength(2); // Hour Range


AnsiString TuesdayTempMinuteOut1 = cbxTuesdayOut1->Text.Delete(1, 3);
AnsiString TuesdayMinuteOut1 = TuesdayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString TuesdayAMPMOut1 = cbxTuesdayOut1->Text.Delete(1, 6); // AMPM
double TuesdayOut1 = CalcTime(TuesdayHourOut1, TuesdayMinuteOut1, TuesdayAMPMOut1);

AnsiString TuesdayHourIn2 = cbxTuesdayIn2->Text.SetLength(2); // Hour Range


AnsiString TuesdayTempMinuteIn2 = cbxTuesdayIn2->Text.Delete(1, 3);
AnsiString TuesdayMinuteIn2 = TuesdayTempMinuteIn2.SetLength(2); // Minute Range
AnsiString TuesdayAMPMIn2 = cbxTuesdayIn2->Text.Delete(1, 6); // AMPM
double TuesdayIn2 = CalcTime(TuesdayHourIn2, TuesdayMinuteIn2, TuesdayAMPMIn2);

AnsiString TuesdayHourOut2 = cbxTuesdayOut2->Text.SetLength(2); // Hour Range


AnsiString TuesdayTempMinuteOut2 = cbxTuesdayOut2->Text.Delete(1, 3);
AnsiString TuesdayMinuteOut2 = TuesdayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString TuesdayAMPMOut2 = cbxTuesdayOut2->Text.Delete(1, 6); // AMPM
double TuesdayOut2 = CalcTime(TuesdayHourOut2, TuesdayMinuteOut2, TuesdayAMPMOut2);

AnsiString WednesdayHourIn1 = cbxWednesdayIn1->Text.SetLength(2); // Hour Range


AnsiString WednesdayTempMinuteIn1 = cbxWednesdayIn1->Text.Delete(1, 3);
AnsiString WednesdayMinuteIn1 = WednesdayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString WednesdayAMPMIn1 = cbxWednesdayIn1->Text.Delete(1, 6); // AMPM
double WednesdayIn1 = CalcTime(WednesdayHourIn1, WednesdayMinuteIn1, WednesdayAMPMIn1);

AnsiString WednesdayHourOut1 = cbxWednesdayOut1->Text.SetLength(2); // Hour Range


AnsiString WednesdayTempMinuteOut1 = cbxWednesdayOut1->Text.Delete(1, 3);
AnsiString WednesdayMinuteOut1 = WednesdayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString WednesdayAMPMOut1 = cbxWednesdayOut1->Text.Delete(1, 6); // AMPM
double WednesdayOut1 = CalcTime(WednesdayHourOut1, WednesdayMinuteOut1, WednesdayAMPMOut1);

AnsiString WednesdayHourIn2 = cbxWednesdayIn2->Text.SetLength(2); // Hour Range


AnsiString WednesdayTempMinuteIn2 = cbxWednesdayIn2->Text.Delete(1, 3);
AnsiString WednesdayMinuteIn2 = WednesdayTempMinuteIn2.SetLength(2); // Minute Range
AnsiString WednesdayAMPMIn2 = cbxWednesdayIn2->Text.Delete(1, 6); // AMPM
double WednesdayIn2 = CalcTime(WednesdayHourIn2, WednesdayMinuteIn2, WednesdayAMPMIn2);

AnsiString WednesdayHourOut2 = cbxWednesdayOut2->Text.SetLength(2); // Hour Range


AnsiString WednesdayTempMinuteOut2 = cbxWednesdayOut2->Text.Delete(1, 3);
AnsiString WednesdayMinuteOut2 = WednesdayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString WednesdayAMPMOut2 = cbxWednesdayOut2->Text.Delete(1, 6); // AMPM
double WednesdayOut2 = CalcTime(WednesdayHourOut2, WednesdayMinuteOut2, WednesdayAMPMOut2);

AnsiString ThursdayHourIn1 = cbxThursdayIn1->Text.SetLength(2); // Hour Range

380 © FunctionX, Inc.


Borland C++ Builder Lists

AnsiString ThursdayTempMinuteIn1 = cbxThursdayIn1->Text.Delete(1, 3);


AnsiString ThursdayMinuteIn1 = ThursdayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString ThursdayAMPMIn1 = cbxThursdayIn1->Text.Delete(1, 6); // AMPM
double ThursdayIn1 = CalcTime(ThursdayHourIn1, ThursdayMinuteIn1, ThursdayAMPMIn1);

AnsiString ThursdayHourOut1 = cbxThursdayOut1->Text.SetLength(2); // Hour Range


AnsiString ThursdayTempMinuteOut1 = cbxThursdayOut1->Text.Delete(1, 3);
AnsiString ThursdayMinuteOut1 = ThursdayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString ThursdayAMPMOut1 = cbxThursdayOut1->Text.Delete(1, 6); // AMPM
double ThursdayOut1 = CalcTime(ThursdayHourOut1, ThursdayMinuteOut1, ThursdayAMPMOut1);

AnsiString ThursdayHourIn2 = cbxThursdayIn2->Text.SetLength(2); // Hour Range


AnsiString ThursdayTempMinuteIn2 = cbxThursdayIn2->Text.Delete(1, 3);
AnsiString ThursdayMinuteIn2 = ThursdayTempMinuteIn2.SetLength(2); // Minute Range
AnsiString ThursdayAMPMIn2 = cbxThursdayIn2->Text.Delete(1, 6); // AMPM
double ThursdayIn2 = CalcTime(ThursdayHourIn2, ThursdayMinuteIn2, ThursdayAMPMIn2);

AnsiString ThursdayHourOut2 = cbxThursdayOut2->Text.SetLength(2); // Hour Range


AnsiString ThursdayTempMinuteOut2 = cbxThursdayOut2->Text.Delete(1, 3);
AnsiString ThursdayMinuteOut2 = ThursdayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString ThursdayAMPMOut2 = cbxThursdayOut2->Text.Delete(1, 6); // AMPM
double ThursdayOut2 = CalcTime(ThursdayHourOut2, ThursdayMinuteOut2, ThursdayAMPMOut2);

AnsiString FridayHourIn1 = cbxFridayIn1->Text.SetLength(2); // Hour Range


AnsiString FridayTempMinuteIn1 = cbxFridayIn1->Text.Delete(1, 3);
AnsiString FridayMinuteIn1 = FridayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString FridayAMPMIn1 = cbxFridayIn1->Text.Delete(1, 6); // AMPM
double FridayIn1 = CalcTime(FridayHourIn1, FridayMinuteIn1, FridayAMPMIn1);

AnsiString FridayHourOut1 = cbxFridayOut1->Text.SetLength(2); // Hour Range


AnsiString FridayTempMinuteOut1 = cbxFridayOut1->Text.Delete(1, 3);
AnsiString FridayMinuteOut1 = FridayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString FridayAMPMOut1 = cbxFridayOut1->Text.Delete(1, 6); // AMPM
double FridayOut1 = CalcTime(FridayHourOut1, FridayMinuteOut1, FridayAMPMOut1);

AnsiString FridayHourIn2 = cbxFridayIn2->Text.SetLength(2); // Hour Range


AnsiString FridayTempMinuteIn2 = cbxFridayIn2->Text.Delete(1, 3);
AnsiString FridayMinuteIn2 = FridayTempMinuteIn2.SetLength(2); // Minute Range
AnsiString FridayAMPMIn2 = cbxFridayIn2->Text.Delete(1, 6); // AMPM
double FridayIn2 = CalcTime(FridayHourIn2, FridayMinuteIn2, FridayAMPMIn2);

AnsiString FridayHourOut2 = cbxFridayOut2->Text.SetLength(2); // Hour Range


AnsiString FridayTempMinuteOut2 = cbxFridayOut2->Text.Delete(1, 3);
AnsiString FridayMinuteOut2 = FridayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString FridayAMPMOut2 = cbxFridayOut2->Text.Delete(1, 6); // AMPM
double FridayOut2 = CalcTime(FridayHourOut2, FridayMinuteOut2, FridayAMPMOut2);

AnsiString SaturdayHourIn1 = cbxSaturdayIn1->Text.SetLength(2); // Hour Range


AnsiString SaturdayTempMinuteIn1 = cbxSaturdayIn1->Text.Delete(1, 3);
AnsiString SaturdayMinuteIn1 = SaturdayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString SaturdayAMPMIn1 = cbxSaturdayIn1->Text.Delete(1, 6); // AMPM
double SaturdayIn1 = CalcTime(SaturdayHourIn1, SaturdayMinuteIn1, SaturdayAMPMIn1);

AnsiString SaturdayHourOut1 = cbxSaturdayOut1->Text.SetLength(2); // Hour Range


AnsiString SaturdayTempMinuteOut1 = cbxSaturdayOut1->Text.Delete(1, 3);
AnsiString SaturdayMinuteOut1 = SaturdayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString SaturdayAMPMOut1 = cbxSaturdayOut1->Text.Delete(1, 6); // AMPM
double SaturdayOut1 = CalcTime(SaturdayHourOut1, SaturdayMinuteOut1, SaturdayAMPMOut1);

381 © FunctionX, Inc.


Borland C++ Builder Lists

AnsiString SaturdayHourIn2 = cbxSaturdayIn2->Text.SetLength(2); // Hour Range


AnsiString SaturdayTempMinuteIn2 = cbxSaturdayIn2->Text.Delete(1, 3);
AnsiString SaturdayMinuteIn2 = SaturdayTempMinuteIn2.SetLength(2); // Minute Range
AnsiString SaturdayAMPMIn2 = cbxSaturdayIn2->Text.Delete(1, 6); // AMPM
double SaturdayIn2 = CalcTime(SaturdayHourIn2, SaturdayMinuteIn2, SaturdayAMPMIn2);

AnsiString SaturdayHourOut2 = cbxSaturdayOut2->Text.SetLength(2); // Hour Range


AnsiString SaturdayTempMinuteOut2 = cbxSaturdayOut2->Text.Delete(1, 3);
AnsiString SaturdayMinuteOut2 = SaturdayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString SaturdayAMPMOut2 = cbxSaturdayIn2->Text.Delete(1, 6); // AMPM
double SaturdayOut2 = CalcTime(SaturdayHourOut2, SaturdayMinuteOut2, SaturdayAMPMOut2);

AnsiString SundayHourIn1 = cbxSundayIn1->Text.SetLength(2); // Hour Range


AnsiString SundayTempMinuteIn1 = cbxSundayIn1->Text.Delete(1, 3);
AnsiString SundayMinuteIn1 = SundayTempMinuteIn1.SetLength(2); // Minute Range
AnsiString SundayAMPMIn1 = cbxSundayIn1->Text.Delete(1, 6); // AMPM
double SundayIn1 = CalcTime(SundayHourIn1, SundayMinuteIn1, SundayAMPMIn1);

AnsiString SundayHourOut1 = cbxSundayOut1->Text.SetLength(2); // Hour Range


AnsiString SundayTempMinuteOut1 = cbxSundayOut1->Text.Delete(1, 3);
AnsiString SundayMinuteOut1 = SundayTempMinuteOut1.SetLength(2); // Minute Range
AnsiString SundayAMPMOut1 = cbxSundayOut1->Text.Delete(1, 6); // AMPM
double SundayOut1 = CalcTime(SundayHourOut1, SundayMinuteOut1, SundayAMPMOut1);

AnsiString SundayHourIn2 = cbxSundayIn2->Text.SetLength(2); // Hour Range


AnsiString SundayTempMinuteIn2 = cbxSundayIn2->Text.Delete(1, 3);
AnsiString SundayMinuteIn2 = SundayTempMinuteIn2.SetLength(2); // Minute Range
AnsiString SundayAMPMIn2 = cbxSundayIn2->Text.Delete(1, 6); // AMPM
double SundayIn2 = CalcTime(SundayHourIn2, SundayMinuteIn2, SundayAMPMIn2);

AnsiString SundayHourOut2 = cbxSundayOut2->Text.SetLength(2); // Hour Range


AnsiString SundayTempMinuteOut2 = cbxSundayOut2->Text.Delete(1, 3);
AnsiString SundayMinuteOut2 = SundayTempMinuteOut2.SetLength(2); // Minute Range
AnsiString SundayAMPMOut2 = cbxSundayOut2->Text.Delete(1, 6); // AMPM
double SundayOut2 = CalcTime(SundayHourOut2, SundayMinuteOut2, SundayAMPMOut2);

MondayShift1 = MondayOut1 - MondayIn1;


MondayShift2 = MondayOut2 - MondayIn2;
Monday = MondayShift1 + MondayShift2;
edtMonday->Text = edtMonday->Text.sprintf("%0.2f", Monday);

TuesdayShift1 = TuesdayOut1 - TuesdayIn1;


TuesdayShift2 = TuesdayOut2 - TuesdayIn2;
Tuesday = TuesdayShift1 + TuesdayShift2;
edtTuesday->Text = edtTuesday->Text.sprintf("%0.2f", Tuesday);

WednesdayShift1 = WednesdayOut1 - WednesdayIn1;


WednesdayShift2 = WednesdayOut2 - WednesdayIn2;
Wednesday = WednesdayShift1 + WednesdayShift2;
edtWednesday->Text = edtWednesday->Text.sprintf("%0.2f", Wednesday);

ThursdayShift1 = ThursdayOut1 - ThursdayIn1;


ThursdayShift2 = ThursdayOut2 - ThursdayIn2;
Thursday = ThursdayShift1 + ThursdayShift2;
edtThursday->Text = edtThursday->Text.sprintf("%0.2f", Thursday);

FridayShift1 = FridayOut1 - FridayIn1;


FridayShift2 = FridayOut2 - FridayIn2;
Friday = FridayShift1 + FridayShift2;

382 © FunctionX, Inc.


Borland C++ Builder Lists

edtFriday->Text = edtFriday->Text.sprintf("%0.2f", Friday);

SaturdayShift1 = SaturdayOut1 - SaturdayIn1;


SaturdayShift2 = SaturdayOut2 - SaturdayIn2;
Saturday = SaturdayShift1 + SaturdayShift2;
edtSaturday->Text = edtSaturday->Text.sprintf("%0.2f", Saturday);

SundayShift1 = SundayOut1 - SundayIn1;


SundayShift2 = SundayOut2 - SundayIn2;
Sunday = SundayShift1 + SundayShift2;
edtSunday->Text = edtSunday->Text.sprintf("%0.2f", Sunday);

TotalHours = Monday + Tuesday + Wednesday + Thursday + Friday + Saturday + Sunday;


edtTotalHours->Text = edtTotalHours->Text.sprintf("%0.2f", TotalHours);
}
//---------------------------------------------------------------------------
12. Press F12 to display the form. On the form, click the first Time In for Monday.
That is, the cbxMondayIn1 combo box.
13. On the Object Inspector, click the Events tab. Double-click the empty field on
the right of OnClick.
Whenever the user selects a value of a combo box, we need to avoid any conflict
with the previous combo box or he next, if any. For example, when the user
selects a value for the first time in, we need to make sure that the time selected
does not occur AFTER the first time out. After all, somebody can work from
6AM to 10AM in the same day but not from 9AM to 6:30AM.
Implement the event as follows (self-explanatory):

//---------------------------------------------------------------------------
// The TComboBox::OnClick() event is used (instead of the OnChange
// because it occurs AFTER the selection has been made on a combobox.
void __fastcall TForm1::cbxMondayIn1Click(TObject *Sender)
{
// Using the TComboBox::ItemIndex property to find out
// what is the current selection of each combobox
// that is involved when this combobox' selection has changed
int In1Selection = cbxMondayIn1->ItemIndex;
int Out1Selection = cbxMondayOut1->ItemIndex;

// Make sure that the time out of the first shift


// is NOT less than the starting time.
if( Out1Selection < In1Selection )
cbxMondayIn1->ItemIndex = 18;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
14. Following the same algorithm, implement the OnClick event of all the other
combo boxes as as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::cbxMondayOut1Click(TObject *Sender)
{
int In1Selection = cbxMondayIn1->ItemIndex;
int Out1Selection = cbxMondayOut1->ItemIndex;
int In2Selection = cbxMondayIn2->ItemIndex;

383 © FunctionX, Inc.


Borland C++ Builder Lists

if( Out1Selection < In1Selection )


cbxMondayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxMondayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxMondayIn2Click(TObject *Sender)
{
int In2Selection = cbxMondayIn2->ItemIndex;
int Out1Selection = cbxMondayOut1->ItemIndex;
int Out2Selection = cbxMondayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxMondayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxMondayIn2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxMondayOut2Click(TObject *Sender)
{
int Out2Selection = cbxMondayOut2->ItemIndex;
int In2Selection = cbxMondayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxMondayOut2->ItemIndex = 34;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxTuesdayIn1Click(TObject *Sender)
{
int In1Selection = cbxTuesdayIn1->ItemIndex;
int Out1Selection = cbxTuesdayOut1->ItemIndex;
if( Out1Selection < In1Selection )
cbxTuesdayIn1->ItemIndex = 18;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxTuesdayOut1Click(TObject *Sender)
{
int In1Selection = cbxTuesdayIn1->ItemIndex;
int Out1Selection = cbxTuesdayOut1->ItemIndex;
int In2Selection = cbxTuesdayIn2->ItemIndex;

if( Out1Selection < In1Selection )


cbxTuesdayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxTuesdayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxTuesdayIn2Click(TObject *Sender)
{

384 © FunctionX, Inc.


Borland C++ Builder Lists

int In2Selection = cbxTuesdayIn2->ItemIndex;


int Out1Selection = cbxTuesdayOut1->ItemIndex;
int Out2Selection = cbxTuesdayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxTuesdayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxTuesdayIn2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxTuesdayOut2Click(TObject *Sender)
{
int Out2Selection = cbxTuesdayOut2->ItemIndex;
int In2Selection = cbxTuesdayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxTuesdayOut2->ItemIndex = 34;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxWednesdayIn1Click(TObject *Sender)
{
int In1Selection = cbxWednesdayIn1->ItemIndex;
int Out1Selection = cbxWednesdayOut1->ItemIndex;
if( Out1Selection < In1Selection )
cbxWednesdayIn1->ItemIndex = 18;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxWednesdayOut1Click(TObject *Sender)
{
int In1Selection = cbxWednesdayIn1->ItemIndex;
int Out1Selection = cbxWednesdayOut1->ItemIndex;
int In2Selection = cbxWednesdayIn2->ItemIndex;

if( Out1Selection < In1Selection )


cbxWednesdayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxWednesdayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxWednesdayIn2Click(TObject *Sender)
{
int In2Selection = cbxWednesdayIn2->ItemIndex;
int Out1Selection = cbxWednesdayOut1->ItemIndex;
int Out2Selection = cbxWednesdayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxWednesdayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxWednesdayIn2->ItemIndex = 24;

EvaluateTheTime();

385 © FunctionX, Inc.


Borland C++ Builder Lists

}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxWednesdayOut2Click(TObject *Sender)
{
int Out2Selection = cbxWednesdayOut2->ItemIndex;
int In2Selection = cbxWednesdayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxWednesdayOut2->ItemIndex = 34;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxThursdayIn1Click(TObject *Sender)
{
int In1Selection = cbxThursdayIn1->ItemIndex;
int Out1Selection = cbxThursdayOut1->ItemIndex;
if( Out1Selection < In1Selection )
cbxThursdayIn1->ItemIndex = 18;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxThursdayOut1Click(TObject *Sender)
{
int In1Selection = cbxThursdayIn1->ItemIndex;
int Out1Selection = cbxThursdayOut1->ItemIndex;
int In2Selection = cbxThursdayIn2->ItemIndex;

if( Out1Selection < In1Selection )


cbxThursdayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxThursdayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxThursdayIn2Click(TObject *Sender)
{
int In2Selection = cbxThursdayIn2->ItemIndex;
int Out1Selection = cbxThursdayOut1->ItemIndex;
int Out2Selection = cbxThursdayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxThursdayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxThursdayIn2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxThursdayOut2Click(TObject *Sender)
{
int Out2Selection = cbxThursdayOut2->ItemIndex;
int In2Selection = cbxThursdayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxThursdayOut2->ItemIndex = 34;

386 © FunctionX, Inc.


Borland C++ Builder Lists

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxFridayIn1Click(TObject *Sender)
{
int In1Selection = cbxFridayIn1->ItemIndex;
int Out1Selection = cbxFridayOut1->ItemIndex;
if( Out1Selection < In1Selection )
cbxFridayIn1->ItemIndex = 18;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxFridayOut1Click(TObject *Sender)
{
int In1Selection = cbxFridayIn1->ItemIndex;
int Out1Selection = cbxFridayOut1->ItemIndex;
int In2Selection = cbxFridayIn2->ItemIndex;

if( Out1Selection < In1Selection )


cbxFridayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxFridayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxFridayIn2Click(TObject *Sender)
{
int In2Selection = cbxFridayIn2->ItemIndex;
int Out1Selection = cbxFridayOut1->ItemIndex;
int Out2Selection = cbxFridayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxFridayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxFridayIn2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxFridayOut2Click(TObject *Sender)
{
int Out2Selection = cbxFridayOut2->ItemIndex;
int In2Selection = cbxFridayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxFridayOut2->ItemIndex = 34;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSaturdayIn1Click(TObject *Sender)
{
int In1Selection = cbxSaturdayIn1->ItemIndex;
int Out1Selection = cbxSaturdayOut1->ItemIndex;
if( Out1Selection < In1Selection )
cbxSaturdayIn1->ItemIndex = 18;

387 © FunctionX, Inc.


Borland C++ Builder Lists

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSaturdayOut1Click(TObject *Sender)
{
int In1Selection = cbxSaturdayIn1->ItemIndex;
int Out1Selection = cbxSaturdayOut1->ItemIndex;
int In2Selection = cbxSaturdayIn2->ItemIndex;

if( Out1Selection < In1Selection )


cbxSaturdayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxSaturdayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSaturdayIn2Click(TObject *Sender)
{
int In2Selection = cbxSaturdayIn2->ItemIndex;
int Out1Selection = cbxSaturdayOut1->ItemIndex;
int Out2Selection = cbxSaturdayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxSaturdayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxSaturdayIn2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSaturdayOut2Click(TObject *Sender)
{
int Out2Selection = cbxSaturdayOut2->ItemIndex;
int In2Selection = cbxSaturdayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxSaturdayOut2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSundayIn1Click(TObject *Sender)
{
int In1Selection = cbxSundayIn1->ItemIndex;
int Out1Selection = cbxSundayOut1->ItemIndex;
if( Out1Selection < In1Selection )
cbxSundayIn1->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSundayOut1Click(TObject *Sender)
{
int In1Selection = cbxSundayIn1->ItemIndex;
int Out1Selection = cbxSundayOut1->ItemIndex;
int In2Selection = cbxSundayIn2->ItemIndex;

if( Out1Selection < In1Selection )

388 © FunctionX, Inc.


Borland C++ Builder Lists

cbxSundayOut1->ItemIndex = 24;
if( Out1Selection > In2Selection )
cbxSundayOut1->ItemIndex = In2Selection;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSundayIn2Click(TObject *Sender)
{
int In2Selection = cbxSundayIn2->ItemIndex;
int Out1Selection = cbxSundayOut1->ItemIndex;
int Out2Selection = cbxSundayOut2->ItemIndex;

if( In2Selection < Out1Selection )


cbxSundayIn2->ItemIndex = 24;
if( In2Selection > Out2Selection )
cbxSundayIn2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxSundayOut2Click(TObject *Sender)
{
int Out2Selection = cbxSundayOut2->ItemIndex;
int In2Selection = cbxSundayIn2->ItemIndex;

if( Out2Selection < In2Selection )


cbxSundayOut2->ItemIndex = 24;

EvaluateTheTime();
}
//---------------------------------------------------------------------------
15. Add a Button control to the right side of the Countries combo box and under the
Count label.
16. To test the new setting, press F9

389 © FunctionX, Inc.


Borland C++ Builder Lists

Chapter 14:
Managing Views

390 © FunctionX, Inc.


Borland C++ Builder Lists

1.1 Tree Views

A treeview consists of displaying a hierarchical view of items arranged in a parent-child


format. It is typically used to show items that belong to interrelated categories, such as
parent to child and child to grandchild, etc; or folder to subfolder to file.

The starting item of the tree is called the Root and illustrates the beginning of the tree.
Each item, including the root, that belongs to the tree is referred to as a node.

In the following charts, the arrow means, “has the following child or children”.

Root Parent

Node Category Child

Node Category Grand-child

A treeview is not limited to a one-to-one correspondence. Not only can an item have
more than one dependency, but also a child can make the tree stop at any category.
Categories of a treeview are organized by levels of organization. The most used trees
have one parent called the root; then under the root start the dependents.

Here is an example representing the world and some countries:

Root
391 © FunctionX, Inc.
Borland C++ Builder Lists

World

Continent Asia

Country Thailand Afghanistan

The children of a parent are recognized by their belonging to the same level but can have different
behaviors; for example, while one child might have another child (or other children), an item on the same
level does not necessarily abide by a set rule. Everything usually depends on the tree designer.

Consider the following tree:

Root World

Continent Europe America Africa

Greece Uruguay USA Senegal Botswana Country

State ME PA

14.1.1 Tree View Design


C++ Builder provides an exceptional way of creating a tree view at design time; in other
words, you can create a complete tree view without writing a single line of code, as long
as you are not planning some customized operations on the tree’s items.

To create a tree view, use the TreeView control from the Win32 tab. After placing the
control on the form, create its children using the Items property. To include pictures on
your tree, use an ImageList control.

1. Create a new project with the starting form.


2. Change the caption of the form to Countries
3. Set the dimensions to Height = 218 and Width = 210
4. On the Component Palette, click the Win32 tab and click the TreeView control
5. Click on the form to add the treeview control.
6. Change the treeview’s position and dimensions as follows: Height = 155,
Left=16, Top = 16, and Width = 145

392 © FunctionX, Inc.


Borland C++ Builder Lists

7. While the treeview control is still selected, on the Object Inspector, click the
Items field and click its ellipsis button
8. On the TreeView Items Editor dialog box, click the New Item button
9. Type World and press Enter
10. Type Universe
11. On the dialog box, click Universe and click Delete
12. Click World and click the New Subitem button.
13. Type America and press Enter
14. Type Africana and press Enter
15. Type Europe and press Enter
16. Click Africana and using the Text edit box, edit it to display Africa and press
Enter
17. Type Asia
18. Click America and click New Subitem
19. Type Chile and press Enter.
20. Type Canada
21. Click Asia and click New Subitem
22. Type Thailand and press Enter
23. Type Afghanistan

24. Click OK.


25. To test the treeview, press F9
26. Notice the + sign on the World item.
27. Click + and notice the – sign.

393 © FunctionX, Inc.


Borland C++ Builder Lists

28. Click the other + signs to expand the tree items and click the – signs

29. After using the form, close it.


30. To use some images, make sure the Component Palette displays the Win32 tab.
Click the ImageList control.
31. Click anywhere on the form.
32. On the form, double-click the ImageList button.

33. On the Form1->ImageList1 ImageList dialog box, click the Add button.
34. Locate the folder where the exercises are located and display the Bitmaps folder.
35. Click World1 and click Open
36. Click Add again. This time, click Bell1 and click Open.

394 © FunctionX, Inc.


Borland C++ Builder Lists

37. Repeat the same process to add Plus, Face1, Losange1, and Band:

38. Click OK.


39. On the form, click the listview to select it.
40. On the Object Inspector, set the Images property to ImageList1.
41. While the list view is still selected, click the Items field and click its ellipsis
button.
42. On the TreeView Items Editor dialog box, click World to select it. Set its Image
Index to 0 and its Selected Index to 1
43. Click the + on World to expand it.
44. Click America to select it.
45. Set its Image Index to 2 and its Selected Index to 3
46. Set the other images according to the following table:

Image Selected
Item – Text
Index Index
World 0 1
America / Africa/ Europe / Asia 2 3
Chile / Canada / Thailand / Afghanistan 4 5
47. Click OK
48. To test the treeview, press F9
49. Click the various + to expand and click items to select them. Notice the change
of graphics.
50. After using the form, close it.

395 © FunctionX, Inc.


Borland C++ Builder Lists

14.1.2 Code Creating a TreeView


A member of a treeview is called a node. Visually, a node on a treeview displays its text
in one of two states: selected or not selected. On another visual front, a node has a child
or it is standing alone. When a node has a child, it displays a + (collapsed) or –
(expanded). These last two details will be important because at times you will need to
know whether a node is selected or not, whether a node has a child or not. The first issue
is to know how to create a treeview and how to assign a child or children to a node.

C++ Builder provides three classes equipped with various properties and functions to
deal with a treeview. The basic class that manages the treeview control is the TTreeView.
This class controls the visual settings such as background color, borders, borders,
dimensions, etc. Each node is managed by the TTreeNode class. The class is used as a
descriptor of the control. For example, it can be used to find out what node is selected,
whether the node is expanded or collapsed, whether a node has children. The
TTreeNodes class is used to manage a treeview; it combines vaious operations such as
creating the treeview, adding, inseting or deleting nodes, or updating the list of items.

To create a treeview, position a TreeView control on the form (although you can still
create it completely with code). Once the control is placed, you can customize its window
settings derived from the TControl class. The nodes are usually created from the
OnCreate event of the host form.

1. Create a new project with its starting form.


2. To save the project, on the Standard toolbar, click Save All
3. Locate the folder where the exercises are selected.
4. Click the Create New Folder button, type Countries and press Enter twice to
display the new folder in the Save In combo box.
5. Click Save twice to save the unit and the project names.
6. Change the caption of the form to Countries Statistics
7. From the Standard tab of the Component Palette, double-click the Panel control.
8. Set the following properties: Align = alTop, Alignment = taLeftJustify,
BevelInner = bvRaised, bvOuter = bvLowered, BorderWidth = 2, Height=28
9. To type the caption, click the Caption field, press Delete, press Space, and type
Countries
10. Click an unoccupied area of the form to deselect the panel
11. From the Standard tab, double-click the Panel control again.
12. Set its Align property to alBottom, its BevelOuter to bvLowered, delete its
caption, and set its Height to 20
13. Click the Win32 tab and double-click the TreeView control
14. While the new TreeView control is still selected, set its Align property to alLeft
and its width to 140
15. To create the treeview, double-click an unoccupied area of the form to access
the form’s OnCreate event.

396 © FunctionX, Inc.


Borland C++ Builder Lists

16. Implement the event as follows:

void __fastcall TForm1::FormCreate(TObject *Sender)


{
// The root node
TreeView1->Items->Add(NULL, "World");
// First child and its children
TreeView1->Items->AddChild(TreeView1->Items->Item[0], "Africa");
TreeView1->Items->AddChild(TreeView1->Items->Item[1], "Botswana");
TreeView1->Items->AddChild(TreeView1->Items->Item[1], "Benin");
// Second child and its child
TreeView1->Items->AddChild(TreeView1->Items->Item[0], "Europe");
TreeView1->Items->AddChild(TreeView1->Items->Item[4], "Begium");
TreeView1->Items->AddChild(TreeView1->Items->Item[4], "Danemark");
TreeView1->Items->AddChild(TreeView1->Items->Item[4], "Poland");
// Third child and its children
TreeView1->Items->AddChild(TreeView1->Items->Item[0], "America");
TreeView1->Items->AddChild(TreeView1->Items->Item[8], "Panama");
TreeView1->Items->AddChild(TreeView1->Items->Item[8], "Colombia");
// Fourth child and its children
TreeView1->Items->AddChild(TreeView1->Items->Item[0], "Asia");
TreeView1->Items->AddChild(TreeView1->Items->Item[11], "Bangladesh");
}
17. To test the treeview, press F9.
18. Expand the various nodes to display their children
19. Close the form.
20. To implement a more professional treeview creation, change the listing of the
OnCreate event as follows:

void __fastcall TForm1::FormCreate(TObject *Sender)


{
TTreeNode *Continent, *Africa, *Europe, *America, *Asia;

// The root node


TreeView1->Items->Add(NULL, "World");

// First children level


Continent = TreeView1->Items->Item[0];

// First child and its children


TreeView1->Items->AddChild(Continent, "Africa");
Africa = TreeView1->Items->Item[1];
TreeView1->Items->AddChild(Africa, "Botswana");
TreeView1->Items->AddChild(Africa, "Benin");

// Second child and its child


TreeView1->Items->AddChild(Continent, "Europe");
Europe = TreeView1->Items->Item[4];
TreeView1->Items->AddChild(Europe, "Begium");
TreeView1->Items->AddChild(Europe, "Danemark");
TreeView1->Items->AddChild(Europe, "Poland");

// Third child and its children


TreeView1->Items->AddChild(Continent, "America");
America = TreeView1->Items->Item[8];

397 © FunctionX, Inc.


Borland C++ Builder Lists

TreeView1->Items->AddChild(America, "Panama");
TreeView1->Items->AddChild(America, "Colombia");

// Fourth child and its children


TreeView1->Items->AddChild(Continent, "Asia");
Asia = TreeView1->Items->Item[11];
TreeView1->Items->AddChild(Asia, "Bangladesh");
}
21. To display the form, press F12.

14.1.3 Adding Images to Nodes


We have seen than a treeview’s nodes are created from a combination of the TTreeNode
and the TTreeNodes classes, the images associated with nodes are handled by the Images
property derived from the TCustomTreeView class.

To use images on a treeview, first include an ImageList control to the form. Using the
Form ImageList dialog box, add the desired images to the list of images. Note the
position of each image in the list; you will need to know the position of each image.

To associate an image to a node, first declare a TTreeNode object and set or assign it a
position. The TTreeNode object needs to know the position of the node for almost any
operation that node will be involved in. The most important property related to an image
is the ImageIndex; this is the position of the image on the list created previously. The
other image you might be interested in is the Selected Index; this informs the TreeNode
object about the position of the image the node will display when selected.

1. To add some pictures to the treeview, from the Win32 tab, double-click the
ImageList to add it to the form.
2. Change the name of the ImageList to imgTree
3. On the form, double-click the ImageList icon
4. Click Add.
5. From the Bitmaps16 folder, include the following pictures: World1, Plus,
Losange1, Bell, Face, and Whole.
6. Click OK
7. On the form, click the listview.
8. On the Object Inspector, set the Images field to imgTree.
9. To assign the images to the appropriate nodes, change the listing of the event as
follows:

void __fastcall TForm1::FormCreate(TObject *Sender)


{
TTreeNode *World,
*Continent, *Africa, *Europe, *America, *Asia,
*Country;
TreeView1->Images = imgTree;

// The root of the tree

398 © FunctionX, Inc.


Borland C++ Builder Lists

TreeView1->Items->Add(NULL, "World");
// Assign a position to the node
World = TreeView1->Items->Item[NULL];
// Set the image states for the node
World->ImageIndex = 0;
World->ImageIndex = 1;

// First children level


Continent = TreeView1->Items->Item[0];

// First child and its children


TreeView1->Items->AddChild(Continent, "Africa");
Africa = TreeView1->Items->Item[1];
Africa->ImageIndex = 2;
Africa->SelectedIndex = 3;
TreeView1->Items->AddChild(Africa, "Botswana");
Country = TreeView1->Items->Item[2];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;
TreeView1->Items->AddChild(Africa, "Benin");
Country = TreeView1->Items->Item[3];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;

// Second child and its child


TreeView1->Items->AddChild(Continent, "Europe");
Europe = TreeView1->Items->Item[4];
Europe->ImageIndex = 2;
Europe->SelectedIndex = 3;
TreeView1->Items->AddChild(Europe, "Begium");
Country = TreeView1->Items->Item[5];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;
TreeView1->Items->AddChild(Europe, "Danemark");
Country = TreeView1->Items->Item[6];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;
TreeView1->Items->AddChild(Europe, "Poland");
Country = TreeView1->Items->Item[7];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;

// Third child and its children


TreeView1->Items->AddChild(Continent, "America");
America = TreeView1->Items->Item[8];
America->ImageIndex = 2;
America->SelectedIndex = 3;
TreeView1->Items->AddChild(America, "Panama");
Country = TreeView1->Items->Item[9];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;
TreeView1->Items->AddChild(America, "Colombia");
Country = TreeView1->Items->Item[10];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;

// Fourth child and its children


TreeView1->Items->AddChild(Continent, "Asia");
Asia = TreeView1->Items->Item[11];

399 © FunctionX, Inc.


Borland C++ Builder Lists

Asia->ImageIndex = 2;
Asia->SelectedIndex = 3;
TreeView1->Items->AddChild(Asia, "Bangladesh");
Country = TreeView1->Items->Item[12];
Country->ImageIndex = 4;
Country->SelectedIndex = 5;
}
10. To test the treeview, press F9.

11. After viewing and using the form, close it.


12. To save and close the project, on the main menu, click File ➞ Close All.
13. A message box will ask you whether you want to save the changes. Click Yes.

1.2 List Views

A list view consists of using one of four views to display a list of items. The list is
typically equipped with icons that allow the user to verify what view is displaying. There
are four views used to display items:
Large Icons: The view displays a list of items using icons with a 32x32 pixels size of
icons. This is the preferred view when the main idea consists of giving a grand overview
of the items
Small Icons: Like the other two views, it uses 16x16 pixel icons to display a simplified
list of the items. Once more, no detail is provided about the items of this list. The list is
organized in disparate columns with some on top of others. If the list is supposed to be
sorted, the alphabetical arrangement is organized from left to right.
List: This list, using small icons, is also organized in columns; this time, the columns are
arranged so that the first column gets filled before starting the second. If the list is sorted,
the sorting is arranged in a top-down manner.
Details: This view displays arranged columns of items and provides as many details as
the list developer had arranged it.

400 © FunctionX, Inc.


Borland C++ Builder Lists

14.1.4 List View Design

C++ Builder provides a means of creating a list without much concern with coding, as
long as you need just one view to display the list.

To create a listview, use the ListView control from the Win32 tab. If you plan to display
a list without columns, you can create the list in a major one-step process. If the list will
display or need a column, its creation will involve a major two-step process. Once the
listview control is placed on the form, create its items using the Items field. The columns
are created using the Columns field.

1. Create a new project with its starting form.


2. Change the caption of the form to Statistics
3. Change its dimensions to Height = 195 and Width = 445
4. To create our listview, on the Component Palette, click the Win32 tab.
5. Click the ListView control
6. Click on the form.
7. Change the position and the dimensions to Height = 114, Left = 16, Top = 16,
and Width = 410
8. While the listview control is still selected on the form, on the Object Inspector,
click the Items field and click its ellipsis button.
9. On the ListView Items Editor dialog, click New Item
10. Type Yemen and press Enter.
11. Type Botswana and press Enter
12. Type Belgium and press Enter
13. Type Colombia and press Enter
14. Type Denmark and press Enter
15. Type Benin

16. Click OK.


17. To test the list view, press F9.

401 © FunctionX, Inc.


Borland C++ Builder Lists

18. After viewing the listview, close the form


19. On the form, click the listview. On the Object Inspector, click the Columns field
and click its ellipsis button.
20. From the Editing ListView1->Columns window, click Add New Item.
21. While the 0 – TListColumn line is still selected, type Countries to change the
Caption of the column header.
22. Click the Width field and type 80
23. Click Add New Item, type Area and change its width to 100
24. Click Add New Item, type Population and change its width to 100
25. Click Add New Item, type Budget and change its width to 50
26. Click Add New Item, type Capital and change its width to 60

27. Close the Editing ListView1->Columns window.


28. On the Object Inspector, change the ViewStyle property to vsReport
29. To add the images to the listview, on the Win32 tab, double-click the ImageList
control.
30. With the ImageList1 selected, change its name to imgLarge
31. On the form, double-click the imgLarge control to add the images:

402 © FunctionX, Inc.


Borland C++ Builder Lists

32. Click Add


33. Locate the folder where the exercises are located. Access the Flags folder.
34. Click Yemen and click Open. If you receive a message warning that the bitmap
is too large…, click No to All
35. Add the other following flags: Botswana, Belgium, Colombia, Danemark, and
Benin:

36. Click the list as follows:

Item Image Index New SubItem


Yemen 0 527,970
17,479,206
17B
Sanaa
Botswana 1 600,370
1,576,470
1.6B
Gaborone
Belgium 2 30,510
10,241,506
116.5B
Brussels
Colombia 3 1,138,910
39,685,655
22B
Bogota
Danemark 4 43,094
5,336,394
59.7B
Copenhagen
Benin 5 112,620
6,395,919
299M
Cotonou

403 © FunctionX, Inc.


Borland C++ Builder Lists

37. Click OK.


38. On the Win32 tab, double-click the ImageList control again.
39. Change its name to imgSmall
40. Double-click the imgSmall icon
41. Using the Add button, add the following bitmaps: smYemen, smBotswana,
smBelgium, smColombia, smDanemark, and smBenin:

42. Click OK
43. On the form, click the listview.
44. On the Object Inspector, set the SmallImages property to imgSmall
45. Change the ViewStyle to vsReport.
46. To test the listview, press F9.
47. After viewing the listview, close the form.
48. On the Component Palette, click the Standard tab.
49. Add four buttons to the form positioned under the list box.

404 © FunctionX, Inc.


Borland C++ Builder Lists

50. Change their captions to &Large Icons, &Small Icons, &List, and &Details
respectively:

51. Double-click the Large Icons button to access its OnClick event.
52. Double-click the other buttons and implement their events as follows:

void __fastcall TForm1::Button1Click(TObject *Sender)


{
ListView1->ViewStyle = vsIcon;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)


{
ListView1->ViewStyle = vsSmallIcon;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)


{
ListView1->ViewStyle = vsList;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)


{
ListView1->ViewStyle = vsReport;
}
//---------------------------------------------------------------------------

53. To test the listview, press F9.


54. After viewing the listview, close the form.

14.1.5 Code Creating a ListView

Creating a listview fom code provides the same flexibility as a listview created at design-
time, minus the ability to visualize live the list being created. To create a listview, place a
ListView control on the form.

405 © FunctionX, Inc.


Borland C++ Builder Lists

The columns and the items of the list are created separately. A column is created using
the TListColumn class. This allows you to add and format columns. An item of the list is
created using the TListItem class.

1. On the main menu, click File ➞ Reopen ➞ ..\Countries\Project1.bpr. If the


project is not on the list, open it.
2. Display the form and click an unoccupied area of the form
3. From the Standard tab of the Component Palette, double-click the Panel control
4. Delete its caption and set its Align property to alClient
5. Make sure the latest panel is still selected.
From the Standard tab, double-click the Panel control again.
6. Set its Align property to alTop. Set its BevelOuter to bvLowered. Delete its
caption and set its Height to 38
7. On the form, click the biggest section of the form, it is occupied by the biggest
panel (this should be Panel3).
8. From the Win32 tab of the Component Palette, double-click the ListView
control.
9. With the listview still selected, change its Align property to alClient
10. From the combo box on the top section of the Object Inspector, select Form1
11. Click the Events tab
12. Double-click FormCreate.
13. At the end of the existing content of the event but before the closing bracket,
type:

TListColumn *ListCol;
TListItem *ListIt;

ListCol = ListView1->Columns->Add();
ListCol->Caption = "Country";
ListCol->Width = 95;
ListCol = ListView1->Columns->Add();
ListCol->Caption = "Area (Km2)";
ListCol->Width = 70;
ListCol->Alignment = taRightJustify;
ListCol = ListView1->Columns->Add();
ListCol->Caption = "Population (M)";
ListCol->Width = 90;
ListCol->Alignment = taRightJustify;
ListCol = ListView1->Columns->Add();
ListCol->Caption = "Budget";
ListCol->Width = 50;
ListCol->Alignment = taRightJustify;
ListCol = ListView1->Columns->Add();
ListCol->Caption = "Capital";
ListCol->Width = 85;
ListCol = ListView1->Columns->Add();
ListCol->Caption = "@";
ListCol->Width = 30;

406 © FunctionX, Inc.


Borland C++ Builder Lists

ListIt = ListView1->Items->Add();
ListIt->Caption = "Belgium";
ListIt->SubItems->Add("30,510");
ListIt->SubItems->Add("10,241,506");
ListIt->SubItems->Add("116.5B");
ListIt->SubItems->Add("Gaborone");
ListIt->SubItems->Add("BC");

ListIt = ListView1->Items->Add();
ListIt->Caption = "Colombia";
ListIt->SubItems->Add("1,138,910");
ListIt->SubItems->Add("39,685,655");
ListIt->SubItems->Add("22B");
ListIt->SubItems->Add("Bogota");
ListIt->SubItems->Add("CO");

ListIt = ListView1->Items->Add();
ListIt->Caption = "Botswana";
ListIt->SubItems->Add("600,370");
ListIt->SubItems->Add("1,576,470");
ListIt->SubItems->Add("1.6B");
ListIt->SubItems->Add("Gaborone");
ListIt->SubItems->Add("BC");

ListIt = ListView1->Items->Add();
ListIt->Caption = "Danemark";
ListIt->SubItems->Add("43,094");
ListIt->SubItems->Add("5,336,394");
ListIt->SubItems->Add("59.7B");
ListIt->SubItems->Add("Copenhagen");
ListIt->SubItems->Add("DA");

ListIt = ListView1->Items->Add();
ListIt->Caption = "Bangladesh";
ListIt->SubItems->Add("144,000");
ListIt->SubItems->Add("129,194,224");
ListIt->SubItems->Add("4.3B");
ListIt->SubItems->Add("Dhaka");
ListIt->SubItems->Add("BG");

ListIt = ListView1->Items->Add();
ListIt->Caption = "Benin";
ListIt->SubItems->Add("112,620");
ListIt->SubItems->Add("6,395,919");
ListIt->SubItems->Add("299M");
ListIt->SubItems->Add("Cotonou");
ListIt->SubItems->Add("BN");

ListView1->ViewStyle = vsReport;
}
14. To test the form, press F9.
15. Since there is a line in the midddle of the form, try to drag the line left and right
to resize the form’s sections.
16. After viewing the form, close it.

407 © FunctionX, Inc.


Borland C++ Builder Lists

17. Press F12 to display the form. To add images, from the Win32 tab, double-click
the ImageList control.
18. Double-click the ImageList icon on the form.
19. Click Add and add the following images (click No to All if you receive a
warning message): Belgium, Columbia, Botswana, Danemark, Bangladesh, and
Benin
20. Open the FormCreate event again.
21. After the TListItem line, add the following:

ListView1->LargeImages = ImageList1;
ListView1->SmallImages = ImageList1;
22. After the first ListIt->Caption line, add the following:

ListIt->Caption = "Belgium";
ListIt->ImageIndex = 0;
23. In the same way, assign an image to each item list:

ListIt->Caption = "Colombia";
ListIt->ImageIndex = 1;
ListIt->Caption = "Botswana";
ListIt->ImageIndex = 2;
ListIt->Caption = "Danemark";
ListIt->ImageIndex = 3;
ListIt->Caption = "Bangladesh";
ListIt->ImageIndex = 4;
ListIt->Caption = "Benin";
ListIt->ImageIndex = 5;
24. To test the form, press F9.
25. After using the form, close it.

1.3 Splitter Bars

A splitter is a bar that divides a window area in two sections. These sections are referred
to as panes or frames.. The splitter bar is used to create independent sections holding
various controls. The splitter can divide the sections horizontally or vertically, depending
on how you create it Among other things, the design and implementation allows to
display related data.

To create a splitter bar, click the Splitter control from the Additional tab of the
Component Palette. The Splitter must be added to a control that has the Align property
set to a value other than alNone. If the splitter is embedded to a control that has the alLeft
or alRight Align property, it will create two vertical ssections. If the Align of a control is
set to alTop or alBottom when receiving the splitter, this creates two horizontal sections.
By using a combination of panels and other controls, you can divide the window in as
many sections as necessary and in any way.

1. Display the form. Click the TreeView control on the left side of the form to
select it. Make sure its Align property is set to alLeft.

408 © FunctionX, Inc.


Borland C++ Builder Lists

2. From the Additional tab of the Component Palette, click the Splitter control.
3. Click the treeview on the left side of the form. Notice that the splitter aligns
vertically with the treeview.
4. That’s it. To test the form, press F9.
5. Drag the splitting line in the middle of the form to resize the sections.
6. After using the form, close it.

1.4 Speed Buttons

The SpeedButton control provides the ability to create click buttons that behave either
like check boxes or radio buttons. As a check boxes, you can create a group of speed
buttons so that, out of the group, the selected one will display and keep a clicked state. To
implement a radio button effect, you can create speed buttons in a group so that only one
in the group would display a clicked state when chosen. Speed Buttons can also display
as regular buttons. In fact, a speed button’s behavior is configured as that of a regular
button. The design of the speed button provides the most different aspect of the control.

To create a speed button, use the SpeedButton control from the Additional tab. The best
way to implement the behavior of a group of speed buttons is to place then on a toolbar or
a panel control

14.1.6 Creating and Designing Speed Buttons

1. Make sure the Additional tab is still displaying. Click the SpeedButton control
and click on the panel above the ListView control

Click here

2. Change the new button’s properties as Top = 8 and Left = 16


3. While the button is still selected, on the Object Inspector, click Glyph and click
its ellipsis button.
4. Click Load. Locate the folder that contains the exercises. Click LargeIcons
5. Add another SpeedButton to the form. Change Left property field to 48 and
Top= 8
6. Set its Glyph to SmallIcons
7. Add another SpeedButon with a Glyph of List
8. Add another SpeedButton with a Glyph of Details

409 © FunctionX, Inc.


Borland C++ Builder Lists

9. Click one of the speedbuttons, press Shift and click each one of the other
speedbuttons
10. Set their Flat property to True. Set their GroupIndex to 1
11. Click anywhere on the form to deselect.
12. Double-click the LargeIcons button to access its OnClick event:
13. Double-click the other buttons and implement the OnClick events as follows:

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)


{
ListView1->ViewStyle = vsIcon
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton2Click(TObject *Sender)


{
ListView1->ViewStyle = vsSmallIcon;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton3Click(TObject *Sender)


{
ListView1->ViewStyle = List;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton4Click(TObject *Sender)


{
ListView1->ViewStyle = vsReport;
}
14. To test the form, press F9.

410 © FunctionX, Inc.


Borland C++ Builder Lists

Chapter 15: Lists Classes

411 © FunctionX, Inc.


Windows Events Borland C++ Builder

15.1 Lists
A string, as we have studied and used a few of theem, is a group of characters. A list is a
suite of items of the same category. By default, a list is made of a single type of items
easily identified, but an advanced list is made of objects that are of the same type
although each object can be made of its sub-objects.

The first concern of a list is the composition of its members.

1.1.1 Categories of Lists


The members of a list could be simple text fields, such is the case of the Animation list of
MS Word Font dialog box:

A simple list
whose items
are text-based

A list could also be structured as a tree made of words or groups of words. An example is
the list of fonts in WordPerfect 2002:

412 © FunctionX, Inc.


Windows Events Borland C++ Builder

A Tree View
as a list

Another list could be made of graphics or pictures only:

A list can also combine graphics and text. The Area dialog box of StarOffice features
such a list:

413 © FunctionX, Inc.


Windows Events Borland C++ Builder

A list that
combines
graphics
and text.

A list does not have to be made of items uniformly aligned. For example, the list of
colors of MS Excel’s Format Cells dialog box is made of square boxes representing
colors:

A list does not necessarily display its items all at once. For example, the items of a
listview are usually configured to change their display mode. Such is the case for the
right pane of Windows Explorer. Another category of list of this kind is implemented for
a multiple-choice question exam or text where only one question as a member of the list
of questions would display:

414 © FunctionX, Inc.


Windows Events Borland C++ Builder

Strings are used everywhere and for various circumstances. To start, you should be
familiar with what is available in the VCL before creating your own lists.

1.1.2 Using Lists


There are various reasons for using lists. They provide a uniform way of providing a
group of similar items to the user. Depending on how it is configured, a certain list could
be used to display a simple list of items to the user; this could be serve to provide static
information to the user. An example is the list of Fonts of MS Windows:

The Fonts window


provides a static
list that allows the
user to view and
examine the list of
fonts installed on
the local computer.
Although the user
can be provide with
limited interaction
with the list, the list
cannot be modified
or receive input
from the user.

Another type of list also provide a static list


but allows the user to select or retrieve an
item from the list without either any item or
the list itself.

A popular type of list is available on database applications. These lists allow the user to
select items from one list to create a new one. An example is the Form Expert from Corel
Paradox:

415 © FunctionX, Inc.


Windows Events Borland C++ Builder

When creating a list, you will decide how you would like users to interact with that part
of your application, how they can interact with the list, what can do and what they should
be prevented from doing. The less interaction users have with a list, the least difficult it is
to create. Depending on your intentions, you will need to provide just as much usefulness
as possible to the user. Although lists can appear difficult to create and implement, user
will not care how much work you put into; you will still need to be at least enough
creative.

Many controls use lists as their main components. Such controls are list views, combo
boxes, rich texts, tree views, list boxes, color fields, radio button groups, text memos,
checked list boxes, etc. There are various classes C++ Builder provides to create such
lists.

The primary class used to create a list is the TStrings class.

15.2 The TStrings Class

The TStrings class is used to provides most of the list-based controls with the properties
and methods they need for their functionality. Because of this, such controls are equipped
to take advantage of all (or most) properties of this class. Such controls need to be filled
out with their main items, usually strings.

Since the TStrings class does not lead to a specific Windows control, the control that
needs it has to call it. Put it in reverse order, the TStrings class is declared in each class
that needs to create a list based on a TStrings class. For this reason, it is free to be named
anyway a class wants it. For example, in the TMemo class, the TStrings variable is
declared as Lines whereas it is called Items in the TListBox and the TComboBox
classes.

To implement a list based on the TStrings class from any of these objects, call the
TStrings property which in turn would give access to its properties and methods.

416 © FunctionX, Inc.


Windows Events Borland C++ Builder

15.2.1 Working With Individual Strings


The operations performed using the TStrings class consist of creating a list of items,
inserting new ones or deleting others, counting the items, changing their positions, or
switching the items to another list.

The primary operation you as the programmer will perform on a new list is to fill it with
the items the user can use. At design time, this is usually easy to do because most list-
based controls provide a dialog box used to create an initial list (this is Rapid Application
Development in its truest form). If you have to programmatically create the list,
depending on the control, you would be interested to know not only whether the item was
added to the list but also what position the item is occupying in the list. To create such a
list, call the TStrings::Add() method. Its syntax is:

int __fastcall Add(const AnsiString Source);

This function takes one argument as an AnsiString object and add it to the end of the
target list. If the list is empty, the Add() method would intiate the list with the new item.
The Source argument could be a locally defined string. For example, the following would
add the Borland C++ Builder is Fun!!! string to a Memo control when the user clicks
Button1:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Lines->Add("Borland C++ Builder is fun!!!");
}
//---------------------------------------------------------------------------

You can also use a string held by another control. In this case you would call the control
field that holds the string. For example, the following would add the content of the Edit1
edit box, or the Text property of the Edit control, to a Memo control when the user clicks
Button1:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Lines->Add(Edit1->Text);
}
//---------------------------------------------------------------------------

You could also use the name of a string variable to add its value to a TStrings variable:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String Address = "4812 Lockwood Drive #D12";
Memo1->Lines->Add(Address);
}
//---------------------------------------------------------------------------

If the addition of the Source string to the TStrings variable was successful, Add() returns
the position where the Source string was added. The position is zero-based. If Source was
set as the first item of the list, its position would be 0. If it were added as the 2nd item of
the list, it would assume position 1, etc. If you need to, you can find out the position the
argument is occupying after being added. Here is an example:

417 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String Address = "4812 Lockwood Drive #D12";
int Success = Memo1->Lines->Add(Address);

if( Success != -1)


ShowMessage(Address + " was added at position " + String(Success + 1));
}
//---------------------------------------------------------------------------

If you are not interested in the position that Source occupied once it was added, you can
use use the Append() method. Its syntax is:

void __fastcall Append(const AnsiString Source);

For a text-based control such as Memo or Rich Edit, the only thing you want to know is
whether the item was added to the sequence. This makes the Append() method useful.
This method also takes one argument as the AnsiString object to be added. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Lines->Append("The magazine is on the table");
}
//---------------------------------------------------------------------------

Practical Learning: TStrings Individual Strings

1. Start a new project with the default form

2. To save the project, on the Standard toolbar, click the Save All button
3. By clicking the Create new Folder button, create a new folder called List Filler
and display it in the Save combo box
4. Save the unit as Main and the project as ListFiller
5. Change the form’s caption to Travel Plans
6. Add a label on the top left section of the form. Set the caption to
Select a Continent:

418 © FunctionX, Inc.


Windows Events Borland C++ Builder

7. Add a ComboBox control under the exisiting label. Change its name to
cbxCountries

8. To create a list of continents, double-click in the middle of the form to access its
OnCreate event.
9. Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
cbxContinents->Items->Append("Asia");
cbxContinents->Items->Append("Europe");
cbxContinents->Items->Append("America");
cbxContinents->Text = "Asia";
}
//---------------------------------------------------------------------------
10. To test the project, on the main menu, click Run  Run
11. Test the combobox by selecting different items. Close the form
12. If the form is not displaying, press F12. Add a label under the combo box with a
caption of Select a Country:
13. Add a listbox under the new label. Change its name to lstCountries

419 © FunctionX, Inc.


Windows Events Borland C++ Builder

14. To fill out the new control, we will do this depending on the item selected on the
top combobox. Therefore, double-click the Select A Continent combox to
access its OnChange event.
15. Set the default list for the Countries combo box in the OnCreate event of the
form to synchronize with the default selection of the Continent combobox. Then
implement the OnChange event of the Countries combobox as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
cbxContinents->Items->Append("Asia");
cbxContinents->Items->Append("Europe");
cbxContinents->Items->Append("America");
cbxContinents->Text = "Asia";

lstCountries->Items->Append("Sri Lanka");
lstCountries->Items->Append("Indonesia");
lstCountries->Items->Append("Yemen");
lstCountries->Items->Append("Iraq");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cbxContinentsChange(TObject *Sender)
{
if(cbxContinents->Text == "Asia")
{
lstCountries->Clear();
lstCountries->Items->Append("Sri Lanka");
lstCountries->Items->Append("Indonesia");
lstCountries->Items->Append("Yemen");
lstCountries->Items->Append("Iraq");
}
else if(cbxContinents->Text == "Europe")
{
lstCountries->Clear();
lstCountries->Items->Clear();
lstCountries->Items->Append("Sweden");
lstCountries->Items->Append("Greece");
lstCountries->Items->Append("Portugal");
lstCountries->Items->Append("Spain");
}
else
lstCountries->Clear();
}
//---------------------------------------------------------------------------
16. To test the project, on the Debug toolbar, click the Run button
17. On the Select A Continent combobox, select different continents and make sure
the list of countries changes accordingly. After testing the combobox, close the
form.

15.2.2 Working With Strings Positions


While the Add() and the Append() methods are used to add a string to the end of a list,
the Insert() method allows you to add a string to a position of your choice in the target
list. The syntax of the Insert() method is:

void __fastcall Insert(int Index, const AnsiString Source)

420 © FunctionX, Inc.


Windows Events Borland C++ Builder

This function needs two pieces of information. The Index argument specifies the intended
position to insert the item. The positions are zero-based. If you want to add the new item
on top of the list, set the Index to 0, for the second place, set the Index to 1, etc. The
string to be added is the Source argument. In the following example, the Easy Listening
string is added to the 3rd position on a list:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ListBox1->Items->Insert(2, "Easy Listening");
}
//---------------------------------------------------------------------------

The Index value applies whether the list is sorted or not. If you would like to add a new
string to a sorted list and insert it to the right alphabetical sequence, use the Add() or the
Append() methods.

Besides adding, appending, or inserting, you can delete an item from a list. This is
performed using the Delete() method whose syntax is:

void __fastcall Delete(int Index)

To delete an item, the Delete() method needs


to know its position. Once again, the list is
zero-based: the 1st item is at position 0, the 2nd
at 1, etc. If the Index argument points to an
item that does not exist, for example either
you set it to a value greater than the number
of items or all items have been deleted,
nothing would happen (no error would be
thrown). In the following example, the 3rd
item of a combo box is deleted:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDeleteClick(TObject *Sender)
{
cbxNetwork->Items->Delete(2);
}
//---------------------------------------------------------------------------

To (effectively) use the Delete() method, you should supply the position of the item you
want to delete. Sometimes such a position would be invalid. The best thing to do is to
first inquire whether the item you want to delete exists in the list. For this and many other
reasons, you can ask the compiler to check the existence of a certain item in a list. This
operation is performed using the IndexOf() method. Its syntax is:

int __fastcall IndexOf(const AnsiString Source);

To use this function, provide the string you are looking for. This string is an AnsiString
object. If the string exists in the list, the IndexOf() method returns its position in the list.
The following event is used to examine the items of a combo box looking for a Printer
string:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFindClick(TObject *Sender)

421 © FunctionX, Inc.


Windows Events Borland C++ Builder

{
cbxNetwork->Items->IndexOf("Printer");
}
//---------------------------------------------------------------------------

If the IndexOf() method finds that the Source string exists in the target list, it returns the
position of Source. You can then use this information as you see fit. For example you can
insert a new string on top of the found string. Here is example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnInsertClick(TObject *Sender)
{
int Found = cbxNetwork->Items->IndexOf("Printer");

if( Found )
cbxNetwork->Items->Insert(Found, "Digital Camera");
}
//---------------------------------------------------------------------------

You could also look for Source in a target list and delete it if it exists. Here is an
example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDeleteClick(TObject *Sender)
{
int Found = cbxNetwork->Items->IndexOf("Printer");

if( Found )
cbxNetwork->Items->Delete(Found);
}
//---------------------------------------------------------------------------

Another type of operation you will perform in a list is to retrieve the text of a particular
string in the group; this usually happens when you want to transfer an item to another
control or display a message about the item. The Strings property allows you to get an
item based on its position in the list. This property is an array that represents the items of
the list. To locate a string, use the square brackets to specify its position. Because the list
is zero-based, the first item is 0 and would be represented by Strings[0], the second is 1
and would be called with Strings[1], etc. For the following example, when the user clicks
the list box, regarless of the item selected, a label on the form would retrieve the third
item of the list:

//---------------------------------------------------------------------------
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
Label1->Caption = ListBox1->Items->Strings[2];
}
//---------------------------------------------------------------------------

One of the most effective ways to use the Strings property is to find out the item that the
user would have selected in a list and act accordingly. In the following example, when
the user selects a radio button from a RadioGtroup control, the caption of the button
selected displays on a label:

//---------------------------------------------------------------------------
void __fastcall TForm1::RadioGroup1Click(TObject *Sender)
{

422 © FunctionX, Inc.


Windows Events Borland C++ Builder

// Find the position of the item selected


int ItemPos = RadioGroup1->ItemIndex;
// Get the text of the item selected
String strSelected = RadioGroup1->Items->Strings[ItemPos];

// Using a label, display a message associated with the item selected


Label1->Caption = "You selected " + strSelected;
}
//---------------------------------------------------------------------------

One of the most regular reasons for this operation is to make sure that a string is not
duplicately added to a list that already has the Source argument. In the following
example, when the user types a string in an edit box and clicks soemewhere else (that is,
when the Edit control looses focus), the compiler checks to see if the string in the edit
box already exists in the list. If the list of the combo box does not have the string in the
edit box, then this string is added to the list:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtLaptopExit(TObject *Sender)
{
String Laptop = edtLaptop->Text;
int Exists = cbxNetwork->Items->IndexOf(Laptop);

if( Exists == -1 )
cbxNetwork->Items->Append(Laptop);
}
//---------------------------------------------------------------------------

Some operating system configuration files contain lines with the = symbol as part of a
string. There is no strict rule on what those files are or what they do. The person who
creates such a file also decides what the file is used for and when. For example, a music
program would use such a file to configure the keyboard keys as related to the associated
software. A communication program could use another type of those files as a list or table
of ports. Programmers have to deal with those files for various reasons. Some of those
files have strings made of three parts: Left=Right. The value called Right has to be
assigned to the value on the left. Sometimes the Left value is called a Key; sometimes it
is called a Name. The value on the right of equal is also called a Value. Therefore, a
string on this file would have the form Name=Value. Some of these files have the .INI
extension but can perfectly have any extension the programmer wanted.

Depending on how the file is structured, the programmers have to find a certain key or
name in the list. The TStrings class is equipped with a function that helps with this
operation. The method is the IndexOfName() and its syntax is:

int __fastcall IndexOfName(const AnsiString Name);

This method takes an AnsiString object as argument. The compiler scans the list looking
for a string that has the form Name=Value. If the left part of a string matches the Name
argument, the IndexOfName() method returns the first position where such a string was
found. The following dialog box is equipped with an edit box and a memo. To add a new
key to the list of keys in the memo, the user types the key in the edit box and clicks the
Add Key button (the Edit control is named edtNewKey, the Memo control is named
mmoConfigure, the button is named is btnAddKey, the bottom Edit control is named
edtFound):

423 © FunctionX, Inc.


Windows Events Borland C++ Builder

Here is an example of implementing the IndexOfName() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAddKeyClick(TObject *Sender)
{
String NewKey = edtNewKey->Text;

int LookFor = mmoConfigure->Lines->IndexOfName("HelpDir");

if(LookFor == -1)
mmoConfigure->Lines->Append(NewKey);
else
edtFound->Text = LookFor;
}
//---------------------------------------------------------------------------

When the user clicks the Add Key button, the Name part, which is the string on the left of
the = symbol of the edit box, is checked for each string in the memo. If no name matches
the Name part of the edit box, the new key is added to the memo. If that Name part is
already in the list, the bottom edit box displays the position of the first string that contains
Name.

Probably the best way to do this, “Live”, is to retrieve the Name part from the string that
the user has typed in the top edit box. The following commented code would accomplish
that:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAddKeyClick(TObject *Sender)
{
// Get the content of the edit box
String NewKey = edtNewKey->Text;
// Find the position of the first occurence in the edit box
int EqualPos = NewKey.AnsiPos("=");
// Create a string from the beginning to the first occurence of =
String NamePart = NewKey.Delete(EqualPos, NewKey.Length());

// Find out if the Name part of the key is already in the list
int LookFor = mmoConfigure->Lines->IndexOfName(NamePart);

424 © FunctionX, Inc.


Windows Events Borland C++ Builder

// if it is not, add the new key to the file


if(LookFor == -1)
mmoConfigure->Lines->Append(edtNewKey->Text);
}
//---------------------------------------------------------------------------

Again, depending on how the list is structured, you can ask the compiler to retrieve the
name part of a string provided its position. This operation is performed using the Names
property. This property is an array of the strings of this type of file. When needed, you
can ask the compiler to give you the name part of a certain line. For example, to retrieve
the name part of the 5th line, you could write Names[4]. If the item at that position does
not have = as part of the string, the compiler would consider that the line is not a valid
IndexOfName string and would void it. In the following example, the 2nd line of
mmoConfigure is examined. If that line is a valid IndexOfName, its Name part displays
in the Found At edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetNameClick(TObject *Sender)
{
edtFound->Text = mmoConfigure->Lines->Names[1];
}
//---------------------------------------------------------------------------

By constrast, to retrieve the Value part of an IndexOfName string, use the Values
property. This also is an array of the valid = strings of the list. It uses the following
syntax:

AnsiString Values[AnsiString NamePart];

This time, you must (or should) provide the string you are looking for as if it were the
position of the string. This string, which is an AnsiString object, should be the Name part
of a string you are looking for. The compiler would scan the list of strings looking for
valid IndexOfName strings. If it finds a string that encloses an = symbol, then the
compiler would check its Name part. If this Name matches the NamePart of the Values
property, then it would return the Value. This is useful if you want to know whether a
certain key has already been defined in the file. Here is an example:
Note //---------------------------------------------------------------------------
When providing the
void __fastcall TForm1::btnGetValueClick(TObject *Sender)
NamePart as the string
to look for, make sure {
you do not include = as edtFound->Text = mmoConfigure->Lines->Values["Directory"];
part of the string }
//---------------------------------------------------------------------------

Another usefulness of items of a list is to switch their positions as related to each other.
The primary method used to swap items is the Move method. Its syntax is:

void __fastcall Move(int CurrentPos, int NewPos);

This function takes two strings. The first string is considered for its position. When
executing, the function moves the first item from the CurrentPos position to the position
specified by NewPos. The following event would move the 2nd item of a CheckListBox
control to the 5th position:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnMoveClick(TObject *Sender)
{

425 © FunctionX, Inc.


Windows Events Borland C++ Builder

CheckListBox1->Items->Move(1, 4);
}
//---------------------------------------------------------------------------

After the move, the item at CurrentPos is moved to NewPos. If the item is not move just
one position, all of the items whose positions are between CurrentPos and NewPos are
affected. If the item moved up, the items that were above it would be moved down. The
opposite occurs if the item has move down.

While the Move() method is used to move an item from one position to another, the
Exchange() method is used to switch two items. Its syntax is:

void __fastcall Exchange(int Index1, int Index2);

The compiler takes the item at Index1, moves it to Index2, takes the item at that was at
Index2 and moves it to Index one. In the following example, the items at the 4th and the
1st positions are switched:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnExchangeClick(TObject *Sender)
{
CheckListBox1->Items->Exchange(3, 0);
}
//---------------------------------------------------------------------------

Practical Learning: Using Strings by Their Position


1. To continue with our list project, add a label to the right side of the Select a
Continent label. Set its caption to Countries Selected
2. Add a ListBox control under the Countries Selected label. Change its name to
lstCities

426 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::lstCountriesClick(TObject *Sender)
{
// When a new country is selected, empty the list of cities
lstCities->Clear();

// If a country is selected, get its name, instead of its position


int i = lstCountries->ItemIndex;
AnsiString Selected =
lstCountries->Items->Strings[i].c_str();

if(Selected == "Portugal")
{
lstCities->Clear();
lstCities->Items->Append("Braga");
lstCities->Items->Append("Coimbra");
lstCities->Items->Append("Viana do Castelo");
lstCities->Items->Append("Aveiro");
}
else if(Selected == "Indonesia")
{
lstCities->Clear();
lstCities->Items->Append("Makassar");
lstCities->Items->Append("Ambon");
lstCities->Items->Append("Kupang");
lstCities->Items->Append("Jakarta");
lstCities->Items->Append("Surabaya");
}
else if(Selected == "Sweden")
{
lstCities->Clear();
lstCities->Items->Append("Upsala");
lstCities->Items->Append("Kalmar");
lstCities->Items->Append("Sundsvall");
lstCities->Items->Append("Tärnaby");
lstCities->Items->Append("Kiruna");
lstCities->Items->Append("Göteborg");
}
else
lstCities->Clear();
}
//---------------------------------------------------------------------------
3. To test the project, on the Debug button, click the Run button.
4. Save your project

15.2.3 Working With a Group of Strings


Instead of adding one item at a time to a string, there are various techniques available for
filling out a list with all of the needed items. If you want to fill out a Memo or a RichEdit
controls with a file, which is just a list of strings, use the TStrings::LoadFromFile()
method. Its syntax is:

void __fastcall LoadFromFile(const AnsiString FileName);

427 © FunctionX, Inc.


Windows Events Borland C++ Builder

This function takes an AnsiString object as argument, which is the FileName. If you want
to open a file whose path you know, you can provide this path as the argument. Here is an
example that fills out a Memo control of a form with the content of a text file:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Lines->LoadFromFile("C:\\Windows\\WINHELP.INI");
}
//---------------------------------------------------------------------------

If you provide the path of a file but the file does not exist, when the user clicks the
button, the application would throw an uncomfortable error. The best alternative is to let
the user select a file using an appropriate dialog box such the Open dialog box. In this
case, the FileName argument would be matched to the content of the dialog box.
Following this code, a Memo control named Memo1 would be filled with the content of a
file opened from an OpenDialog1 and a Button1 controls placed on the form:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnOpenFileClick(TObject *Sender)
{
if(OpenDialog1->Execute())
Memo1->Lines->LoadFromFile(OpenDialog1->FileName);
}
//---------------------------------------------------------------------------

On the other hand, the TStrings class is also equipped with a special method that can be
used to save a file from a Memo or a RichEdit controls. Its syntax is:

void __fastcall SaveToFile(const AnsiString FileName);

This method takes an AnsiString object as the argument, called FileName. This argument
specifies the default name of the file being saved by the user. Here is an example;

//---------------------------------------------------------------------------
void __fastcall TForm1::btnSaveClick(TObject *Sender)
{
if(SaveDialog1->Execute())
Memo1->Lines->SaveToFile(SaveDialog1->FileName);
}
//---------------------------------------------------------------------------

Besides the Memo and RichEdit controls, you can also fill out a list of a control from the
strings of another list. This is mainly performed using the AddStrings() method whose
syntax is:

void __fastcall AddStrings(TStrings* Strings);

The argument provided to this string must be a valid string object. Therefore, you should
make sure that the list originates from another list-based control or from another valid
source. The Strings argument could come from a known control. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTransferFileClick(TObject *Sender)
{
Memo2->Lines->AddStrings(Memo1->Lines);
}

428 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

Since the TStrings class is a descendent of the TPersistent class, you can also use the
Assign() method. Its syntax is:

void __fastcall Assign(TPersistent* Source);

The above event could also be written as:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTransferFileClick(TObject *Sender)
{
Memo2->Lines->Assign(Memo1->Lines);
}
//---------------------------------------------------------------------------

At any time you can find out how many items compose a list using the Count property.
Not only this property provides an integral count of the members of the list but you can
also use it when scanning the list using a for loop. The fundamental way of using the
Count property is to get the number of items of a list. In the following example, when the
user clicks the Count button, the number of strings in the RadioGroup1 control displays
in the Count edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCountClick(TObject *Sender)
{
edtCount->Text = RadioGroup1->Items->Count;
}
//---------------------------------------------------------------------------

An alternative is to use the Capacity property which fundamentally also provides the
number of items of a list. Its main role is to deal with memory allocation especially when
writing a component that uses a list of items.

If you have two lists and want to compare them, use the Equals() method whose syntax
is:

bool __fastcall Equals(TStrings* Strings);

This function requires a TStrings list of strings. The


conversion is performed on two fronts. First, both lists
should have the same number of strings. If both lists
have different number of items, the function returns
false. If they have the same number of strings, then the
compiler examines the strings one line at a time, for
each list. If two strings of the same position are not the
same, the function returns false. This means that even
if both lists have the same strings, the comparison can
still render negative.

Here is an example of implementing this method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareListsClick(TObject *Sender)
{

429 © FunctionX, Inc.


Windows Events Borland C++ Builder

if( !ListBox1->Items->Equals(ListBox2->Items) )
ShowMessage("Both lists are not the same\n"
"You should synchronize them before exiting");
}
//---------------------------------------------------------------------------

The items of a TStrings list are usually text based although they can also be of different
kinds of objects. When the items are made of strings, sometimes you will need to convert
them to a single text. Such is the case when transferring the items of a listbox or a combo
box to a text document or a rich text file. To convert a TStrings list of strings to text, you
should translate the list to a C-based string of objects. This can be done using the
GetText() method whose syntax is:

char * __fastcall GetText(void);

When this method is called by a TStrings variable, it returns a null-terminated string that
represents all of the items of the text.

To assign a C-based string to a TStrings list of strings, use the SetText() method. Its
syntax is:

void __fastcall SetText(char * Text);

This method takes one argument as a C string and converts it to TStrings.

You can use these two methods to perform the same transfer or transaction we used to
pass a list of strings from one list to another. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetTextClick(TObject *Sender)
{
char *WholeList = Memo1->Lines->GetText();
Memo3->Lines->SetText(WholeList);
}
//---------------------------------------------------------------------------

Even if the controls are different kind, you can use the same transaction. For example, the
following event transfers the content of a listbox to a memo.:

430 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTransToLBXClick(TObject *Sender)
{
char *WholeList = ListBox1->Items->GetText();
Memo3->Lines->SetText(WholeList);
}
//---------------------------------------------------------------------------

This transfer of a list of strings from a listbox, a combo box, a CheckListBox or a


RadioGroup controls to a text-based control such as a memo, a RichEdit or a label can
also effectively be accomplished using the Text property. When you ask it to use the Text
property to perform a transfer, the compiler scans the list of items. At the end of each
item, the compiler adds a carriage return (this is equivalent to the Enter key) and add the
next string to the next line. This allows the compiler to create an AnsiString object made
of all of the strings. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm2::btnTransferClick(TObject *Sender)
{
Memo1->Lines->Add(ListBox1->Items->Text);
Edit1->Text = ListBox1->Items->Text;
Label1->Caption = ListBox1->Items->Text;
}
//---------------------------------------------------------------------------

As you can see, this transfer is not properly interpreted by the Edit control because this
control does not have a multiple line capability while the WordWrap property helps to
manage the Label control.

Another technique used to most effectively transfer a list from strictly list-based control,
such as a listbox, a combobox or a RadioGroup control to a text based such as a memo or
a RichText control is to use the CommaText property. When called to use this property,
the compiler would scan the list of items. If an item is a one-word string, the compiler
would write a comma “,” on its right and start adding the next item. If the item is a string
made of more than one word, to delimit it, the compiler would enclose it with double-
quotes. This is done until the last string.

431 © FunctionX, Inc.


Windows Events Borland C++ Builder

In the following example, when the user clicks the Transfer button, the list of items from
the listbox is transferred to both a memo and an edit box using the CommaText property:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTransferClick(TObject *Sender)
{
Memo1->Lines->Add(ListBox1->Items->CommaText);
Edit1->Text = ListBox1->Items->CommaText;
}
//---------------------------------------------------------------------------

If you decide to dismiss a whole list, use the Clear() method. Its syntax is:

void __fastcall Clear();

Unlike the Delete() method, the Clear function completely empties the list of items. Here
is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEmptyTheListClick(TObject *Sender)
{
Memo1->Lines->Clear();
}
//---------------------------------------------------------------------------

15.3 The TStringList Class


The TStrings class appears to provide enough methods to perform any operation on any
list of strings. Unfortunately, because TStrings is an abstract class, you cannot declare a
TStrings variable, which means that you cannot create a dynamic list using the TStrings
class. That is one of the reasons you will use alternate classes to accomplish such a task.

The TStringList is derived from the TStrings class and adds new properties and
methods for operations not possible on its parent. This is because the TStrings class can
only fill out a list. It cannot independently manage the items of its own list; it relies on
the control that uses it.

One of the strengths of the TStringList class is that, unlike the TStrings class, it is not
associated with any control, not even a control that creates a list. Therefore, you are in
charge of using it as you see fit. This also allows a TStringList object to accommodate
almost any control that uses a list. It also provides the primary means of exchanging
items among controls of almost various kinds.

432 © FunctionX, Inc.


Windows Events Borland C++ Builder

15.3.1 Creating a TStringList Object


Because the TStringlist class is not a property of any control, whenever you need it, you
must create it dynamically. And because it is not a control, you only need the new
operator to declare an instance of a TStringList class. The compiler does not need to
know the parent or owner of the list. For the same reason, you have the responsibility of
deleting the list when you do not need it anymore. Although lists are usually difficult to
create and maintain, Borland did a lot of work behind the scenes so that the compiler can
tremendously help you with your list.

To dynamically create a list, you must declare an instance of a TStringList class using
the new operator. If you are planning to use the list inside of only one function or event,
you can initiate the object as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::CreateAlist()
{
TStringList *Categories = new TStringList;
}
//---------------------------------------------------------------------------

Such a list cannot be accessed outside of the event or function in which you created it. If
you want the list to be available to more than one event or function, create it globally.
This could be done on top of the source file. Here is an example:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

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

This time, the list would be available to any event or function of the same source file.
Other objects, events, or fundtions that are part other units (for example if you call this
form from another form) other than this one cannot access the list. The alternative,
sometimes the best one, is to declare the list variable in the header file of the primary unit
that would manipulate or use it. This is done in the private, public or protected sections
of the unit. If only one unit will use this list, declare the variable in the private section.
By contrast, if more than one unit will need it, then declare it in the public section. This
time, since you cannot initialize a variable in a class, only declare a pointer to a
TStringList class. Here is an example:

//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>

433 © FunctionX, Inc.


Windows Events Borland C++ Builder

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

After declaring such a variable, you should initialize it in a function or event that would
be called prior to any other event or function using the list. Although this can be done in
the OnCreate() event of a form, probably the safest place to initialize the list is the
constructor of the form. You will use the new operator to initialize the variable. Here is
an example:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Categories = new TStringList;
}
//---------------------------------------------------------------------------

Once you have created the list locally or globally, you can call any of its properties or
methods to manipulate it.

15.3.2 Using a TStringList Object


The first biggest difference between a TStrings and a TStringList is that, besides the
first being the parent of the second, you cannot create an instance of a TStrings class.
Using the properties of inheritance, you can perform any operation on a TStringList
variable that you would perform on a TStrings object. In fact, some of the properties are
simple duplicate (the duplications were purposely done because some properties and
methods need to deal with the dynamic creation of list, which is possible only with the
TStringList class).

Like a TStrings list, the primary means of filling out a TStringList list is by using either
the Add() or the Append() method. The Append() method is only inherited. The syntax
of the TStringList::Add() method is:

int __fastcall Add(const AnsiString Source);

Once again, each item is added to the list as an AnsiString object. If the addition is
successful, the method returns the position occupied by the Source argument in the list. If
the list was empty, Source would occupy the first position, which is 0 because the list is
zero-based. If the list already had at least one item, the Source argument would be added
to the end of the existing items.

434 © FunctionX, Inc.


Windows Events Borland C++ Builder

Practical Learning: Creating a Dynamic List

1. Start a new project with the default form


2. Change the caption of the form to Date and Time and its name to Main

3. To save the project, on the Standard toolbar, click the Save All button
4. Create a new folder called DateAndTime
5. Save the unit as Main
6. Save the project as DateTimeDlg
7. Change the caption of the form to Date and Time and set its BorderStyle
property to bsDialog
8. Change the name of the form to DateAndTime
9. Set the Height property of the form to approximately 266 and its Width to 306
10. Add a Bevel control to the form. Set its Height to approximately 217 and set its
Width to approximately 201
11. Add another Bevel control inside the first one. Set its Style to bsRaised
12. Add a label inside the interior bevel and set its caption to Available Formats:
13. Add a ListBox control under the label but completely inside the interior bevel.
Change the name of the listbox to lstFormats
14. Add a button to the top right section of the form. Set its name to btnOK and its
Default property to true. Change its Caption to OK
15. Add another button under the OK buton. Change its name to btnCancel and set
its Cancel property to true. Change its Caption to Cancel

435 © FunctionX, Inc.


Windows Events Borland C++ Builder

16. Because the date and time values must be set by the computer at the exact time
the user needs a date or time value for a document, the list of dates and times of
our dialog must be created dynamically.
Double-click an unoccupied area on the form tro access its OnCreate event..
17. Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TDateAndTime::FormCreate(TObject *Sender)
{
TDateTime TodayDate = Date();
TDateTime RightNow = Time();

TStringList* DateList = new TStringList;

DateList->Add(TodayDate);
ShortDateFormat = "m/d/yy";
DateList->Add(TodayDate);
ShortDateFormat = "m/dd/yy";
DateList->Add(TodayDate);
ShortDateFormat = "m/dd/yyyy";
DateList->Add(TodayDate);
ShortDateFormat = "yy/m/dd";
DateList->Add(TodayDate);
DateSeparator = '-';
ShortDateFormat = "yyyy/m/dd";
DateList->Add(TodayDate);
ShortDateFormat = "dd/mmm/yy";
DateList->Add(TodayDate);
LongDateFormat = "dddd";
DateSeparator = ',';
ShortDateFormat = "dddd/ mmmm dd/ yyyy";
DateList->Add(TodayDate);
ShortDateFormat = "mmmm dd/ yyyy";
DateList->Add(TodayDate);
ShortDateFormat = "dddd/ dd mmmm/ yyyy";
DateList->Add(TodayDate);
ShortDateFormat = "dd mmmm/ yyyy";

436 © FunctionX, Inc.


Windows Events Borland C++ Builder

DateList->Add(TodayDate);

ShortTimeFormat = "h:n:s";
DateList->Add(RightNow);
ShortTimeFormat = "hh:nn:ss";
DateList->Add(RightNow);
LongTimeFormat = "HH:nn:ss";
DateList->Add(RightNow);

lstFormats->Items->AddStrings(DateList);

delete DateList;
DateList = NULL;
}
//---------------------------------------------------------------------------
18. Save your project.

19. To test the dialog box, on the Debug toolbar, click the Run button

15.4 Creating a List


When it comes to creating a list, everything depends on what the list would be used, what
you want the list to accomplish, how much, and what kind of interaction the users would
have with the list. As we saw already, there are three main categories of lists. The easiest
lists tend to be those that only display items; the only options to the user could be to
change how the list displays. The 2nd categories in difficulty are those the user would use
to perform selections; these types are common in (desktop) database applications.
Probably the most difficult of the lists are those that, either the users would create or the
user would be allowed to edit the items or the list itself. When considered fairly with the
capabilities of VCL, the configuration of a list tend to depend only on its length, not
necessarily on the difficulty. The same advice would be given here: only provide the
necessary tools to the user, not more not less.

15.4.1 TStrings and TStringList Based Lists


As you know already, the VCL provides various classes for creating lists. It is very likely
that one class would not be enough to handle all of the functionality you expect from
your application. Therefore, you should know how and when to combine classes to assign
the needed actions the user would need to perform.

The TStrings and the TStringList classes tend to exchange information fairly easily. It is
likely that you will have to use the TStringList class whenever you need a dynamic list.
Then use the TStrings to actually fill a list on a control.

Practical Learning: Combining a TStrings and a TStringList Classes to Create Lists


1. Start a new project with the default form
2. To save the project, on the main menu, click File  Save All
3. Create a new folder named Travel Planning
4. Save the unit as Main and the save the project as TravelPlaning
5. Change the caption of the form to Travel Planning and its name to frmMain

437 © FunctionX, Inc.


Windows Events Borland C++ Builder

6. To create a list of continents, add a GroupBox control to the top left section of
the form. Change its caption to Continents
7. Add six RadioButton controls named rdoAfrica, rdoAmerica, rdoPacific,
rdoAsia, rdoEurope, and rdoNowhere as follows:

8. Set each radio buttons caption by removing rdo from its name
9. Save the project and test the functionality of the radio buttons by running the
project. Return to Bcb
10. To add our first list control, add a ListBox control under the GroupBox control.
11. Change its name to lstCountries

12. To create five lists variables, on the Class Explorer, expand the Classes folder.
Double-click TfrmMain to access its header file.

438 © FunctionX, Inc.


Windows Events Borland C++ Builder

13. Declare the following TStringList variables:

//---------------------------------------------------------------------------
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TfrmMain : public TForm
{
__published: // IDE-managed Components
TGroupBox *GroupBox1;
TRadioButton *rdoAfrica;
TRadioButton *rdoAmerica;
TRadioButton *rdoAsia;
TRadioButton *rdoEurope;
TRadioButton *rdoPacific;
TRadioButton *rdoNowhere;
TListBox *lstCountries;
private: // User declarations
public:
TStringList* Africa;
TStringList* America;
TStringList* Asia;
TStringList* Europe;
TStringList* Pacific; // User declarations
__fastcall TfrmMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TfrmMain *frmMain;
//---------------------------------------------------------------------------
#endif
14. On the Code Editor, click the Main.cpp tab. In the form’s constructor, initialize
the variables as follows:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
//---------------------------------------------------------------------------
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{
Africa = new TStringList;
America = new TStringList;
Asia = new TStringList;
Europe = new TStringList;
Pacific = new TStringList;
}
//---------------------------------------------------------------------------

439 © FunctionX, Inc.


Windows Events Borland C++ Builder

15. Press F12 to access the form. Double-click an empty area on the form to access
its OnCreate event. Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormCreate(TObject *Sender)
{
// Create a list of countries for each continent
Africa->Add("Cameroon");
Africa->Add("Lybia");
Africa->Add("Senegal");
Africa->Add("Botswana");
Africa->Add("Morocco");

America->Add("Argentina");
America->Add("Haiti");
America->Add("USA");
America->Add("Uruguay");

Asia->Add("Thailand");
Asia->Add("Sri Lanka");
Asia->Add("Iraq");
Asia->Add("Japan");
Asia->Add("Bangla Desh");

Europe->Add("Denmark");
Europe->Add("Italy");
Europe->Add("Greece");

Pacific->Add("New Zealand");
Pacific->Add("Australia");

// Select or at least make sure that one radio button is selected


rdoAfrica->Checked = True;
}
//---------------------------------------------------------------------------
16. With each continent filled with a few countries, we need to fill out the list of
countries depending on the continent that is selected in the GroupBox.
Press F12 to display the form. On the form, double-click the Africa radio button
to access its OnClick event.
17. Access the form again. Double-click each one of the other radio buttons and
implement them as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoAfricaClick(TObject *Sender)
{
lstCountries->Items->AddStrings(Africa);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoAmericaClick(TObject *Sender)
{
lstCountries->Items->AddStrings(America);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoPacificClick(TObject *Sender)
{
lstCountries->Items->AddStrings(Pacific);
lstCountries->ItemIndex = 0;
}

440 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoAsiaClick(TObject *Sender)
{
lstCountries->Items->AddStrings(Asia);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoEuropeClick(TObject *Sender)
{
lstCountries->Items->AddStrings(Europe);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
18. Save your project.
19. To test the project, on the main menu, click Run  Run.
20. Click various radio buttons and verify that the list of countries changes
everytime a new continent is selected. Actually, we have a small problem. When
a continent is selected, we need to display only the countries that are part of that
continent. Close the form to return to Bcb
21. In the Code Editor, add the highlighted line on top of the OnClick event for each
radio button:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoAfricaClick(TObject *Sender)
{
// When a new continent is selected, empty the list of countries
// to make sure that countries are not mixed
lstCountries->Clear();

lstCountries->Items->AddStrings(Africa);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
22. On the form, double-click the Nowhere radio button to access its OnClick event
and implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoNowhereClick(TObject *Sender)
{
lstCountries->Clear();
}
//---------------------------------------------------------------------------
23. Save your project.
24. Test the project. This time, each radio button controls its list of countries. Close
the form.
25. Now we need to display the countries associated with each continent.
Add a label on the right side of the GroupBox. Set its caption to Cities

441 © FunctionX, Inc.


Windows Events Borland C++ Builder

26. Add ListBox control to the form. Change its name to lstCities

27. To fill out the list of cities, we will rely on the country that was selected in the
Countries listbox.
On the form, double-click the Countries listbox to access its OnClick event.
Implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::lstCountriesClick(TObject *Sender)
{
// Since a new country has been selected, empty the list of cities
lstCities->Clear();

// If a country is selected, get its name, instead of its position


AnsiString Selected =
lstCountries->Items->Strings[lstCountries->ItemIndex].c_str();

// Create a list of cities for each country


// and fill out the Cities list with this list
if(Selected == "Cameroon")
{
lstCities->Items->Add("Ebolowa");
lstCities->Items->Add("Ngaoundere");
lstCities->Items->Add("Batouri");
lstCities->Items->Add("Bamenda");
}
else if(Selected == "Senegal")
{
lstCities->Items->Add("Thiès");
lstCities->Items->Add("Kaolack");
lstCities->Items->Add("Dakar");
}
else if(Selected == "USA")
{

442 © FunctionX, Inc.


Windows Events Borland C++ Builder

lstCities->Items->Add("Atlanta");
lstCities->Items->Add("Boston");
lstCities->Items->Add("Miami");
lstCities->Items->Add("San Diego");
lstCities->Items->Add("Chicago");
}
else if(Selected == "Haiti")
{
lstCities->Items->Add("Port-de-Paix");
lstCities->Items->Add("Les Cayes");
lstCities->Items->Add("Jérémie");
lstCities->Items->Add("Port-Au-Prince");
lstCities->Items->Add("Jacmel");
}

// Select the first city in the list of cities


// This reduces the possibility of an error due to no selected city
lstCities->ItemIndex = 0;
}
//---------------------------------------------------------------------------
28. Test the project. Select different radio buttons and different countries. Make sure
that the lists change correcty. The problem we have at this time is that, although
we have configured the list of Cities to display Cameroonian cities when that
country is selected, When the form opens, even though Cameroon is selected, its
cities are not displaying in the Cities list.
29. Close the form.
30. If the form is not displaying, press F12. Click an unoccupied area of the form to
select the form. On the Object inspector, click the Events tab. Double-click the
empty area on the right side of OnActivate and implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::FormActivate(TObject *Sender)
{
// Behave as if the Countries list had been clicked
lstCountriesClick(Sender);
}
//---------------------------------------------------------------------------
31. Test the program again. This time, the cities of the country selected always
display in the Cities listbox. Click different countries.
32. Close the form and return to Bcb.
33. Now, we will allow the user to select cities from the Cities listbox and create a
list of cities to visit.
Add a new label to the right side of the Cities label. Set its caption to Selected
34. Add a new ListBox control under the Selected: label. Change its name to
lstSelected

443 © FunctionX, Inc.


Windows Events Borland C++ Builder

35. Fundamentally, the user can use a button to select a city and put it in a new list.
If the list is empty, the item will be the first in the list. If the list already contains
a city, the new city will be added to the end of the existing one(s). To make our
application more useful, we will let the user decide whether to add the new item
on top or under a selected item already in the list.
Add a new button between the right listboxes. Change its name to
btnAddAbove and set its Caption to >
36. Double-click the new button and implement its OnClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnAddAboveClick(TObject *Sender)
{
// Since a city was selected, get its string (its name)
AnsiString NewCity =
lstCities->Items->Strings[lstCities->ItemIndex];

// add the new item to the end of the list


lstSelected->Items->Add(NewCity);
}
//---------------------------------------------------------------------------
37. To make our program more user friendly, besides clicking an item from the
Cities list, we will also allow the user to double-click an item to add it to the
Selected list. Instead of writing code to implement this, we can just use code that
has already been written.
Press F12 to access the form. On the form, click the Cities listbox to select it. On
the Object Inspector, click the Events tab.
38. Click the OnDblClick field to reveal its combobox. Click the arrow of the
combobox and select btnAddAboveClick:

444 © FunctionX, Inc.


Windows Events Borland C++ Builder

39. Test the program. Select different continents, different countries, and different
cities. Also, click the button just added. Observe that, although the button can
create a list of cities effectively, the problem is that it duplicates them. The
application we are creating allows the user to select cities to travel. There is no
reason a city should be added twice: we need to prevent a city from being added
if it exists in the Selected list already.
40. Close the form and return to Bcb.
41. To check whether a city exists already in the Selected list, we will call the
TStrings::IndexOf() by providing the name of the city we are looking for. If
IndexOf() does not find the string, then we will add it.
Change the OnClick event of the AddAbove button as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnAddAboveClick(TObject *Sender)
{
// Since a city was selected, get its string (its name)
AnsiString NewCity =
lstCities->Items->Strings[lstCities->ItemIndex].c_str();
// find out whether the new string already exists in the Selected list
// If if does, we will not add it
if(lstSelected->Items->IndexOf(NewCity) == -1)
{
// add the new item to the end of the list
lstSelected->Items->Add(NewCity);
}
}
//---------------------------------------------------------------------------
42. Test the project again. After making sure that no city gets duplicated in the
Selected list, close the form and return to Bcb.
43. By the way, we had decided to let the user add a city above another city in the
Selected list. This allows the user to prioritize the places to travel. In order to
control this order, the user should first select a city. Using the AddAbove button,
we will insert the new city above the selected one, of course provided the new
city is not already in the Selected list.
Change the OnClick event of the AddAbove button as follows:

445 © FunctionX, Inc.


Windows Events Borland C++ Builder

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnAddAboveClick(TObject *Sender)
{
// Find out if a city is selected in the Cities list
if(lstCities->ItemIndex != -1)
{
// Since a city was selected, get its string (its name)
AnsiString NewCity =
lstCities->Items->Strings[lstCities->ItemIndex].c_str();
// find out whether the new string already exists in the Selected list
// If if does, we will not add it
if(lstSelected->Items->IndexOf(NewCity) == -1)
{
// Now find out if a city was chosen in the Selected list,
if(lstSelected->ItemIndex != -1)
{
// then, allow the user to insert the new item
// on top of the selected one
lstSelected->Items->Insert(lstSelected->ItemIndex, NewCity);
// Select the newly added city
lstSelected->ItemIndex = lstSelected->ItemIndex - 1;
}
else // Since no city was selected, add the new one at the end
{
// add the new item to the end of the list
lstSelected->Items->Add(NewCity);
}
}
}
}
//---------------------------------------------------------------------------
44. Test the project to make sure it works fine. Test that the user can select an
already added city in the Selected list and then insert a city above it. Close the
form to Bcb.
45. Save your project.
46. In the same way, we will allow the user to insert a city under a selected one in
the Selected listbox.
Add a new button under the AddAbove button. Change its name to
btnAddBelow and set its caption to _

446 © FunctionX, Inc.


Windows Events Borland C++ Builder

47. Double-click the new button and implement it as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnAddBelowClick(TObject *Sender)
{
if(lstCities->ItemIndex != -1) // find out if a city is selected
{
// Since a city was selected, get its string (its name)
AnsiString NewCity =
lstCities->Items->Strings[lstCities->ItemIndex].c_str();
// find out whether the new string already exists in the Selected list
// If if does, we will not add it
if(lstSelected->Items->IndexOf(NewCity) == -1)
{
if(lstSelected->ItemIndex != -1)
{
// If a city was chosen in the Selected list,
// allow the user to insert the new item on top of the selected one
lstSelected->Items->Insert(lstSelected->ItemIndex + 1, NewCity);
// Select the newly added city
lstSelected->ItemIndex = lstSelected->ItemIndex + 1;
}
else
{
// add the new item to the end of the list
lstSelected->Items->Add(NewCity);
}
}
}
}
//---------------------------------------------------------------------------
48. Since we have allowed the user to add one item at a time, if the user wants to
visit all cities of a certain country, we will let the user select all cities and add
them to the Selected list.
Add a new button under the AddBelow button. Change its name to btnSelectAll
and its caption to >>
49. When the user decides to add all cities to the Selected listbox, although we can
just call the TStrings::AddStrings() method to perform this job, it is possible that

447 © FunctionX, Inc.


Windows Events Borland C++ Builder

the Selected listbox already contains a certain city the user wants to add. For
example, if a user selects a city X from a country A, then selects another city
from country B, and then comes back to country A, since country A would
display all of its cities, the user would have selected city A already. Once again,
we need to prevent a certain city from being added twice to the Selected list.
Double-click the new button and implement its OnClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnSelectAllClick(TObject *Sender)
{
// We need to prevent the same city from being added twice
// to the Selected list.
// Initiate a scanning of all items of the Cities list
for(int i = 0; i < lstCities->Items->Count; i++)
{
// Give the name City to each item of the Cities list
AnsiString City = lstCities->Items->Strings[i].c_str();
// Find out if the Selected list is empty
if(lstSelected->Items->Count == 0) // then fill it with the cities
lstSelected->Items->AddStrings(lstCities->Items);
else // Since there is at least one item in the Selected list,
{
// Initiate the process of scanning each item of the Selected list
for(int j = 0; j < lstSelected->Items->Count; j++)
{
// If an item of the Cities list is not in the Selected list,
if(lstSelected->Items->IndexOf(City) == -1 )
{
// then add it to the Selected list, ignoring any match
lstSelected->Items->Add(City);
}
}
}
}

// Select the last item of the Selected list


lstSelected->ItemIndex = lstSelected->Items->Count - 1;
}
//---------------------------------------------------------------------------
50. The buttons we just added are used to add items to the Selected listbox. For
example, the AddBelow button is used to insert a city under a selected one in the
Selected listbox. If no item exists or no city is selected in the Selected listbox,
we do not need this button. Therefore, we are going to disable it whenever we
do not need this button. While we are at it, we will also disable the AddAbove
and SelectAll buttons whenever we do not need them. This makes our program
more professional and lets the user know what actions are available at a certain
time.
On the form, click the AddBelow button to select it. In the Object Inspector, set
its Enabled property to false.
51. Here is the current situation with our buttons. We our list system to display no
countries when the Nowhere button is selected. When a new continent is
selected using its radio button, if we do not have cities for the selected country
in the Countries listbox, we empty the Cities listbox; otherwise, we fill it out
with the cities of the selected country. To avoid exception errors from the Cities
listbox, we need to disable the unneeded buttons. Finally, whenver a new
country is selected, before displaying its cities, we should empty the Cities
listbox. Since every radio button needs to check these values, we will just create

448 © FunctionX, Inc.


Windows Events Borland C++ Builder

a function that the needed controls can call to check what they want.
On the Class Explorer, right-click the TfrmMain class and click New Method…
52. Set the name to ControlTheLists and make sure the Class Name is TfrmMain.
Set the Function Result to void and click the __fastcall check box. Click OK.
53. Implement the function as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::ControlTheLists()
{
// When a new continent is selected, empty the list of countries
// to make sure that countries are not mixed
lstCountries->Clear();

// Since a new item country has been selected, empty the list of cities
lstCities->Clear();

// If a city is selected, whose prerequisite is that


// the Cities list not be empty in the first place
if(lstCities->ItemIndex != -1)
{
// enable the selection buttons
btnAddAbove->Enabled = True;
btnSelectAll->Enabled = True;
}
else // Otherwise, either no city is selected or the list is empty
{
// disable the selection buttons
btnAddAbove->Enabled = False;
btnSelectAll->Enabled = False;
}
}
//---------------------------------------------------------------------------
54. To make this function available to needing events, call it on top of the OnClick
event of each radio as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoAfricaClick(TObject *Sender)
{
ControlTheLists();
lstCountries->Items->AddStrings(Africa);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoAmericaClick(TObject *Sender)
{
ControlTheLists();
lstCountries->Items->AddStrings(America);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoPacificClick(TObject *Sender)
{
ControlTheLists();
lstCountries->Items->AddStrings(Pacific);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------

449 © FunctionX, Inc.


Windows Events Borland C++ Builder

void __fastcall TfrmMain::rdoAsiaClick(TObject *Sender)


{
ControlTheLists();
lstCountries->Items->AddStrings(Asia);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoEuropeClick(TObject *Sender)
{
ControlTheLists();
lstCountries->Items->AddStrings(Europe);
lstCountries->ItemIndex = 0;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::rdoNowhereClick(TObject *Sender)
{
ControlTheLists();
lstCountries->Clear();

// When the user clicks this button, both the Countries and the Cities
// lists are emptied. Therefore, we don't need the AddBelow button
btnAddBelow->Enabled = False;
}
//---------------------------------------------------------------------------
55. At this time, the buttons have been disabled, we need to find out when and
where they should be enabled and disabled.
At the bottom of the OnCreate event of the form, add the following commented
code:

// Select or at least make sure that one radio button is selected


rdoAfrica->Checked = True;

// Since the list of cities is empty at this time,


// disable the selection buttons
btnAddAbove->Enabled = False;
btnSelectAll->Enabled = False;
}
//---------------------------------------------------------------------------
56. At the bottom of the OnClick event of the Countries listbox, add the following
self-explanatory code:

// Select the first city in the list of cities


// This reduces the possibility of an error due to no selected city
lstCities->ItemIndex = 0;

// If there is something in the list of cities,


// which is equivalent to the list not being empty
if(lstCities->Items->Count > 0)
{
// enable the selection buttons
btnAddAbove->Enabled = True;
btnSelectAll->Enabled = True;
}
else // When the list of cities is empty
{
// disable the add and selection buttons
btnAddAbove->Enabled = False;
btnAddBelow->Enabled = False;

450 © FunctionX, Inc.


Windows Events Borland C++ Builder

btnSelectAll->Enabled = False;
}
}
//---------------------------------------------------------------------------
57. On the form, double-click the Selected list to access its OnClick event.
Implement it as follows (the comments have been added to explain why):

//---------------------------------------------------------------------------
void __fastcall TfrmMain::lstSelectedClick(TObject *Sender)
{
// Apparently the user has made a selection in the Selected list
// Maybe the user did not select anything. Well, find out
if(lstSelected->ItemIndex != -1)
{
// Since the user made a selection,
// change the caption of the AddAbove button
btnAddAbove->Caption = "^";
// Enable the AddBelow button
btnAddBelow->Enabled = True;
}
}
//---------------------------------------------------------------------------
58. Save your project and test it. Make sure you can add cities. Also make sure that
the selection button are enabled and disabled when necessary. Close the form
59. just as we had allowed the user to add cities to the Selected list, we need to let
the user removed the unneeded cities to create a better list.
Add a new button under the SelectAll button. Change its name to btnRemove
and its caption to R

60. In order to remove a city, the user must have selected one. Therefore, this would
be the first condition to check. Then, since a selected item will have been
removed, we need to select another, just in case the user would like to remove
more than one.
Double-click the R button to access its OnClick event and implement it as
follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnRemoveClick(TObject *Sender)

451 © FunctionX, Inc.


Windows Events Borland C++ Builder

{
// Get the position of the currently selected item
int Selected = lstSelected->ItemIndex;

// Since an item is selected already due to previous code


// remove it from the list
lstSelected->Items->Delete(lstSelected->ItemIndex);

// After an item has been removed, get the position of


// the item that was under it
int Sel = Selected - 1;

// Whenever an item has been removed from the Selected list,


// select the item that was under it
// Before making this selection, make sure that there is at least
// one item in the Selected list
if(Selected == lstSelected->Items->Count)
{
lstSelected->ItemIndex = Sel;
}
else
{
// Since the top item was selected, select the first item now
lstSelected->ItemIndex = 0;
}
// If there are no more items in the Selected list,
// then disable the Remove button
if(lstSelected->Items->Count == 0)
{
btnRemove->Enabled = False;
}
}
//---------------------------------------------------------------------------
61. To allow the user to remove all selected cities, add another button under the R
button. Change its name to btnRemoveAll and its caption to R-A
62. Double-click the R-A button to access its OnClick event and implement it as
follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnRemoveAllClick(TObject *Sender)
{
// Remove everything from the Selected list
lstSelected->Clear();

// Since the Selected listbox has become empty,


// we don't need the removing buttons anymore
btnRemove->Enabled = False;
btnRemoveAll->Enabled = False;
}
//---------------------------------------------------------------------------
63. Once again, we need to know when the new buttons should be available or not.
To start, when the form loads, the Selected list is empty. Since there is nothing
to remove, we do not need these buttons. Therefore, change the bottom section
of the form’s OnCreate event as follows:

// Select or at least make sure that one radio button is selected


rdoAfrica->Checked = True;

452 © FunctionX, Inc.


Windows Events Borland C++ Builder

// Since the list of cities is empty at this time,


// disable the selection buttons
btnAddAbove->Enabled = False;
btnSelectAll->Enabled = False;
btnRemove->Enabled = False;
btnRemoveAll->Enabled = False;
}
//---------------------------------------------------------------------------
64. When using the AddAbove button, whenever an item is added to the Selected
list, we can enable the remove buttons in case the user wants to remove the
selected city.

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnAddAboveClick(TObject *Sender)
{

// Find out if a city is selected in the Cities list


if(lstCities->ItemIndex != -1)
{
// Since a city was selected, get its string (its name)
AnsiString NewCity =
lstCities->Items->Strings[lstCities->ItemIndex].c_str();
// find out whether the new string already exists in the Selected list
// If if does, we will not add it
if(lstSelected->Items->IndexOf(NewCity) == -1)
{
// Now find out if a city was chosen in the Selected list,
if(lstSelected->ItemIndex != -1)
{
// then, allow the user to insert the new item
// on top of the selected one
lstSelected->Items->Insert(lstSelected->ItemIndex, NewCity);
// Select the newly added city
lstSelected->ItemIndex = lstSelected->ItemIndex - 1;
}
else // Since no city was selected, add the new one at the end
{
// add the new item to the end of the list
lstSelected->Items->Add(NewCity);
}
// Since at least one item has been added to the Selected list,
// enable the buttons used to remove items from the Selected list
btnRemove->Enabled = True;
btnRemoveAll->Enabled = True;
}
}
}
//---------------------------------------------------------------------------
65. In the same way, when the SelectAll button has been used to add items to the
Selected clist, we can enable the remove button. At the bottom section of the
OnClick event of the SelectAll button, add the following:

// Select the last item of the Selected list


lstSelected->ItemIndex = lstSelected->Items->Count - 1;

// Since some items have been added to the Selected list,


// enable the buttons used to remove items from the Selected list

453 © FunctionX, Inc.


Windows Events Borland C++ Builder

btnRemove->Enabled = True;
btnRemoveAll->Enabled = True;
}
//---------------------------------------------------------------------------
66. We know that the user keeps removing items one by one using the R button,
after all items have been removed, we do not need the R-A button. Therefore,
we can disable it as follows:

// If there are no more items in the Selected list,


// then disable the Remove buttons
if(lstSelected->Items->Count == 0)
{
btnRemove->Enabled = False;
btnRemoveAll->Enabled = False;
}
}
//---------------------------------------------------------------------------
67. Test your project. Perform a few selections and removals. Close the form.
68. Save your project.
69. This time, we will allow the user to move cities and down in the Selected
listbox, event the user could do it indirectly by playing with the add and remove
buttons.
Add a new button on the right side of the Selected button. Change its name to
btnMoveUp and its caption to /\
70. Add one more button to the form, this time position it below the /\ button.
Change its name to btnMoveDown and its caption to \/
71. Set the Enabled property of both buttons to false (when the form opens, we
cannot move items; which means we do not need them).
72. Double-click the MoveUp button and implement its OnClick event as follows
(the comments give necessary explanations):

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnMoveUpClick(TObject *Sender)
{

// Get the position of the currently selected item


int CurItem = lstSelected->ItemIndex;

// To make sure the application does not throw a nasty error,


// alsways make sure that, either the moveUp button is disabled
// Or an item under the first one is selected
if(CurItem == 1)
{
btnMoveUp->Enabled = False;
lstSelected->ItemIndex = 0;
}
else
{
// Swap the selected item to tye one above it
lstSelected->Items->Move(CurItem, CurItem - 1);
// Follow the item that was selected
lstSelected->ItemIndex = CurItem - 1;
}

454 © FunctionX, Inc.


Windows Events Borland C++ Builder

// Just in case the MoveDown button was disabled, if the selected item
// is not at the bottom of the list, then enable the MoveDown button
if(CurItem < lstSelected->Items->Count)
btnMoveDown->Enabled = True;
}
//---------------------------------------------------------------------------
73. Access the form and double-click the MoveDown button. Implement its
OnClick event as follows:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnMoveDownClick(TObject *Sender)
{
// Get the position of the currently selected item
int CurItem = lstSelected->ItemIndex;

// If the user successfully clicked this button, this means the


// MoveUp button can work. Still, if the selected item is not
// the most top item, then enable the MoveUp button
if(CurItem >= 0)
btnMoveUp->Enabled = True;

int HowMany = lstSelected->Items->Count - 1;

if(CurItem == HowMany - 1)
{
btnMoveDown->Enabled = False;
lstSelected->ItemIndex = HowMany;
}
else
{
// Swap the selected item to tye one above it
lstSelected->Items->Move(CurItem, CurItem + 1);
// Follow the item that was selected
lstSelected->ItemIndex = CurItem + 1;
}
}
//---------------------------------------------------------------------------
74. Again, we need to decide when and where these buttons should be enabled or
not. Remember that when the user has selected all cities and added them to the
Selected list, a city should be selected. Therefore, it becomes time to enable the
move buttons.
At the bottom of the OnClick event of the SelectAll button, add the following:

// Since some items have been added to the Selected list,


// enable the buttons used to remove items from the Selected list
btnRemove->Enabled = True;
btnRemoveAll->Enabled = True;
// Also enable the buttons used to move items of the Selected list
btnMoveUp->Enabled = True;
btnMoveDown->Enabled = True;
}
//---------------------------------------------------------------------------
75. Save your project and test it.

455 © FunctionX, Inc.


Windows Events Borland C++ Builder

15.5 Reviews

15.5.1 Exercises
1. The Table Wizard in Microsoft Access provides two lists of sample tables. Each list is
accessed through a radio button: Business or Personal:

a. To create a new table, the user selects items from the Sample Fields to add them to
the Fields In My New Table list box. If an item gets selected twice, instead of
denying the addition of a duplicate item, the new item is add with an incrementing
integer value. That way, the user can select Address many times and display
Address, Address1, Address2, and so on. Implement such a behavior.
b. If the user selects the same item from the Sample Fields more than once the items are
have the same incrementing name, such as FirstName, FirstName1, FirstName2, and
so on. The Table Wizard provides a Rename Field… button that allows the user to
select a field, that is any field, click this button to call a dialog box to rename the
field. When the dialog box displays, the field that was selected to rename already
fills the edit box on the dialog:

If the user clicks Cancel, nothing would happen and the Rename Field dialog box
would be closed. If the user clicks OK, the new name from the Rename Field would
replace the name that was selected for renaming except... If the name that the user
typed already exists in the Fields In My New Table listbox, a message box would let
the user know:

456 © FunctionX, Inc.


Windows Events Borland C++ Builder

After the user clicks OK, the Rename Field dialog box display again (with the new
string that the user had typed).
Implement this behavior.
c. To select a field from the Sample Fields, the user can click the > button or double-
click a field in the Sample Fields. Either action adds the selected field to the right
list.
To deselect a field, the user can click the < button or double-click the unwanted field
in the Fields In My New Table.
Implement this behavior.

457 © FunctionX, Inc.


Variables and Data Types Borland C++ Builder

Index
Button1Click .................................................... 54
A Buttons
Abbreviation .................................................... 11 New Form ................................................... 26
access key ........................................................ 15 Run .............................................................. 79
ActiveX............................................................ 18 C
add ................................................................. 121
alClient........................................................... 408 c_str() ............................................................. 117
Align ................................................................ 35 C++ Builder ................................................... 143
alLeft.............................................................. 410 C++ Builder 5 ................................................. 14
alNone.............................................................. 81 Cancel .............................................................. 66
alphabetical .................................................... 118 categories ......................................................... 27
AnsiCompare ................................................. 126 Classes
AnsiCompare()............................................... 125 AnsiString ................................................. 112
AnsiExtractQuotedStr .................................... 132 TBevel......................................................... 79
AnsiLastChar()............................................... 130 TButton ...................................................... 76
AnsiLowerCase.............................................. 120 TForm.......................................................... 60
AnsiQuotedStr ............................................... 131 TLabel ........................................................ 91
AnsiSameCaption()........................................ 128 TScrollingWinControl................................. 62
AnsiString ........................................................ 87 TSizeConstraits ........................................... 45
AnsiCompare .................................... 125, 126 TUpDown.................................................. 307
Declaring an .............................................. 112 clBlue ............................................................... 44
Delete ........................................................ 130 Click................................................................. 10
LowerCase ................................................ 120 Close .......................................................... 14, 42
Methods Close All .......................................................... 15
AnsiCompareIC ..................................... 126 Code Editor ...................................................... 52
AnsiCompareStr() .................................. 126 combination ................................................... 287
AnsiLastChar ......................................... 130 Command Button ............................................. 66
Pos.......................................................... 133 commitment ..................................................... 28
SubString ............................................... 132 CompareStr().................................................. 126
UpperCase................................................. 120 comparison..................................................... 126
Appending...................................................... 122 compiler ........................................................... 54
AppendStr() ................................................... 122 Component Palette ............................... 18, 25, 66
application........................................................ 25 Additional............................................ 77, 410
application icon................................................ 14 Standard .............................................. 78, 406
Tabs
B Standard ................................................... 27
Bcb............................................................. 11, 50 Win32................................................ 305, 394
behavior ........................................................... 29 computer .......................................................... 25
bevel................................................................. 77 container........................................................... 25
biMaximize .............................................. 42, 287 controls............................................................. 25
Boolean ............................................................ 69 Controls
BorderIcons.................................................... 287 ActionList.................................................... 31
Borland .......................................................... 143 Bevel ........................................................... 78
C++ ............................................................. 25 BorderIcons ................................................. 42
C++ Builder ................................................ 26 Button.................................................... 27, 66
bsDialog........................................................... 43 ColorDialog................................................. 28
bsSizeable ........................................................ 42 Edit ........................................................ 27, 93
btNext ............................................................ 309 Form ............................................................ 26

458 © FunctionX, Inc.


Variables and Data Types Borland C++ Builder

Memo .................................................... 28, 30 Invalid property value ................................. 39


Panel............................................................ 31 Not a valid component name....................... 40
RadioGroup............................................... 337 Esc.................................................................... 17
Resizing....................................................... 37 Events
Selection...................................................... 32 Button
SpeedButton .............................................. 411 OnClick .................................................... 96
UpDown.................................................... 305 Categories.................................................... 49
Create New Folder ........................................... 22 Definition .................................................... 49
customized ....................................................... 29 Edit
OnChange .......................................... 95, 98
D OnEnter .................................................... 98
Default ........................................................... 142 OnExit ...................................................... 98
Definitions OnKeyDown ............................................ 97
Design Time................................................ 25 OnKeyPress.............................................. 96
Run Time .................................................... 25 OnKeyUp ................................................. 97
Delete() .......................................................... 130 Form
design time............................................... 40, 394 OnClick .................................................... 83
Dialog box OnDblClick .............................................. 84
Creating..................................................... 142 OnResize .................................................. 84
Definition .................................................. 142 Label
Dialog Boxes OnClick .................................................... 93
Color ................................................... 44, 144 OnChange............................................ 95, 317
Edit Tab Order ............................................ 49 OnChanging .............................................. 309
Imagelist.................................................... 396 OnChangingEx.......................................... 309
ListView Items Editor ............................... 403 OnClick ................................... 57, 75, 78, 308
Opject Repository ....................................... 25 OnClose....................................................... 58
TreeView Items Editor.............................. 395 OnDblClick ................................................. 56
Dialogs OnEnter ....................................................... 95
Align ........................................................... 37 OnExit ......................................................... 95
Alignment ................................................... 36 Radio Buttons
frmChange................................................. 288 OnClick .................................................. 338
Load Picture ................................................ 45 RadioGroup
Picture Editor .............................................. 45 OnClick .................................................. 337
Save Unit As ............................................. 288 TrackBar
Size.............................................................. 37 OnChange .............................................. 317
TreeView Items Editor.............................. 395 OnKeyUp ............................................... 318
View Form .................................................. 33 UpDown
dimensions ........................................... 30, 41, 67 OnMouseUp ................................... 309, 315
DOS ............................................................... 133 expand .............................................................. 39
Double-click .................................................... 10 F
Drag ........................................................... 10, 30
F12 ................................................................... 19
E field .................................................................. 38
ecUpperCase .................................................... 94 Files
edit boxes ......................................................... 30 .cpp............................................................ 286
ellipsis .............................................................. 45 Header ....................................................... 286
Enter................................................................. 52 Flip Children .................................................... 15
Enumerators floating ............................................................. 57
TAlignment ................................................ 82 Form
TAnchors..................................................... 69 Definition .................................................... 18
TBevelShape ............................................... 77 Description .................................................. 26
TEditCharCase ............................................ 93 Design ......................................................... 27
TFormBorderStyle ...................................... 42 dynamically creating ................................... 58
TUDBtnType ............................................ 309 Events
Errors OnDblClick .............................................. 84

459 © FunctionX, Inc.


Variables and Data Types Borland C++ Builder

OnResize.................................................. 84 Load Picture ..................................................... 45


Floating ....................................................... 57 logic ................................................................. 28
Navigation................................................... 47 LowerCase ..................................................... 120
TForm ........................................................ 60 LowerCase()................................................... 120
FormClick ........................................................ 83
FormCreate .................................................... 408 M
frmMain ........................................................... 53 Main Menu....................................................... 14
Functions Maximize ................................................... 14, 42
AnsiExtractQuotedStr ............................... 132 mbLeft.............................................................. 51
AnsiLowerCase......................................... 120 mbMiddle........................................................ 51
AnsiQuotedStr........................................... 131 mbRight ........................................................... 51
AnsiSameCaption...................................... 128 menu................................................................. 15
AnsiSameStr ............................................. 127 Menu
AnsiSameText........................................... 128 access key.................................................... 15
AppendStr ................................................. 122 dismiss......................................................... 15
c_str........................................................... 123 Edit .............................................................. 15
CompareStr ............................................... 126 Project ......................................................... 15
LowerCase ................................................ 120 Methods
QuotedStr .................................................. 131 AnsiString
SameText .................................................. 124 IsEmpty .................................................. 113
StringReplace ............................................ 134 TrimLeft................................................. 114
strlen.......................................................... 123 BeginDrag ................................................... 83
UpperCase................................................. 119 Execute...................................................... 144
G SetFocus ...................................................... 76
ShowModal ................................................. 60
gets() .............................................................. 117 Microsoft Windows ................................... 13, 25
goals................................................................. 25 Minimize .................................................... 14, 42
graphical .......................................................... 25 mouse ............................................................... 30
grids ................................................................. 18 Mouse
grippers ............................................................ 16 Definition .................................................... 50
Mouse Events................................................... 50
H mrNone ............................................................ 68
header file ........................................................ 28 MSVC .............................................................. 11
header files....................................................... 26 N
Height ............................................................ 394
hint ................................................................... 17 Names
HorzScrollBar .................................................. 78 Karyne ....................................................... 287
New Subitem.................................................. 395
I NULL......................................................... 61, 92
IDE............................................................. 16, 26 O
improvements .................................................. 13
include.............................................................. 26 Object Inspector ......................................... 38, 53
incrementally ................................................. 126 Caption ........................................................ 54
Integrated Development Environment (IDE)... 14 Object Oriented Programming (OOP) ............. 49
Object Repopsitory .......................................... 26
K Object Repository .......................................... 288
keyboard ........................................ 16, 45, 50, 96 OK.................................................................... 66
Keyboard Events.............................................. 52 OnChange ........................................................ 52
OnClick ............................................................ 52
L OnKeyDown ............................................. 52, 97
OnKeyPress .................................................... 52
language........................................................... 13 OnMouseDown ................................................ 50
left arrow key ................................................... 35 OnMouseMove ................................................ 50
length ............................................................. 123 OnMouseUp............................................. 50, 309
Load ............................................................... 411 OnMouseWheel ............................................... 51

460 © FunctionX, Inc.


Variables and Data Types Borland C++ Builder

OnMouseWheelDown ..................................... 51 Min ............................................................ 305


OnMouseWheelUp......................................... 51 ModalResult ................................................ 68
operating system .............................................. 49 Name ..................................................... 41, 67
Operators Orientation ................................................ 306
!= 129 Position...................................................... 306
+ 121, 129 Shape........................................................... 77
< 129 ShowHint .................................................... 94
== 128 Style ............................................................ 80
Opject Repository ............................................ 25 Thousands ................................................. 306
orders ............................................................. 287 Top ...................................................... 41, 394
Transparent.................................................. 87
P ViewStyle.................................................. 404
personal information management (PIM) ........ 25 Visible ......................................................... 68
Picture Editor ................................................... 45 Width..................................................... 41, 46
popular ............................................................. 25 Wrap.......................................................... 306
poScreenCenter ................................................ 46 puts() .............................................................. 117
programmer...................................................... 50 Q
Programs .......................................................... 13
Projects QuotedStr() .................................................... 131
KaryneResto.............................................. 288
Properties R
Active Control....................................... 42, 67 rectangle........................................................... 30
ActiveControl.............................................. 67 rectangular ....................................................... 28
Align ....................................... 42, 80, 81, 410 Regional Settings ................................... 120, 128
AlignButton............................................... 306 restaurant........................................................ 287
Alignment ................................................... 82 Restore ............................................................. 14
Anchors ....................................................... 42 rfReplaceAll................................................... 134
ArrowKeys ................................................ 307 Right-click ....................................................... 10
Associate ................................................... 305 Run................................................................... 18
AutoResize .................................................. 87
AutoScroll ................................................... 62 S
AutoSelect................................................... 94
BevelOuter ................................................ 408 SameText()..................................................... 124
BorderIcons................................................. 42 Save All.............................................. 22, 87, 287
BorderStyle ........................................... 42, 82 screen ......................................................... 25, 27
Cancel ......................................................... 67 Set .................................................................... 69
Caption............................................ 40, 66, 82 Shift.................................................................. 34
CharCase ..................................................... 93 shortcut............................................................. 16
Color ..................................................... 44, 94 Shortcuts
Constraints .................................................. 45 Alt + Shift + Space...................................... 35
Default................................................. 67, 142 Shift + F12 .................................................. 34
Definition .................................................... 38 spin................................................................. 305
DockSite...................................................... 83 Splitter............................................................ 411
DragKind..................................................... 83 standard .......................................................... 144
dkDock..................................................... 83 Standard ........................................................... 18
DragMode ................................................... 83 Standard Dialog (Vertical) ............................. 288
Enabled ................................................. 69, 98 static ................................................................. 66
FocusControl............................................... 93 subs ................................................................ 287
Glyph......................................................... 411 substring......................................................... 132
GroupIndex ............................................... 412 system icon ...................................................... 14
Height.................................................... 41, 46
T
Hint ............................................................. 94
Increment .................................................. 306 TBorderStyle.................................................... 42
Left.............................................................. 41 TControl
Max ........................................................... 305 Methods

461 © FunctionX, Inc.


Variables and Data Types Borland C++ Builder

BeginDrag................................................ 83 U
TCustomEdit .................................................. 95
TfrmMain......................................................... 53 unit ................................................................. 287
this ................................................................... 58 Unit1 ................................................................ 26
title bar ............................................................. 14 UpperCase() ................................................... 119
TLabel user................................................................... 49
Methods
TLabel ..................................................... 91 V
TListColumn.................................................. 408 VCL ............................................................... 131
TListItem ....................................................... 408 VertScrollBar ................................................... 78
tool tip.............................................................. 17 Views
toolbars ............................................................ 16 design .......................................................... 25
Toolbars visual design..................................................... 25
buttons......................................................... 17 vsReport ................................................. 404, 406
list................................................................ 17
Standard ................................................ 25, 26 W
View............................................................ 26
treeview.......................................................... 393 Width ............................................................. 394
TReplaceFlags ............................................... 134 Win32....................................................... 18, 394
TSizeConstraints.............................................. 45 Win95............................................................... 13
TTreeNode..................................................... 400 Windows .................................................. 25, 144
TTreeNodes ................................................... 400 Code Editor ........................................... 52, 70
TWinControl.................................................... 76 wsNormal......................................................... 43
SetFocus................................................... 76

462 © FunctionX, Inc.

You might also like