Basic Facts About C++Builder

Basic Facts About C++Builder

This chapter and the next five cover the basic facts that everyone needs to know about BCB. Important subjects included in this chapter are as follows:

  • The IDE
  • Projects
  • The VCL
  • Core VCL Technologies: Components, Properties, and Events
  • Stepping into the Pascal source for the VCL
  • The syntax of the VCL
  • An overview of the component architecture
  • A brief look at Run Time Type Information (RTTI)

This introduction to BCB continues in the next chapter, where I cover the new Borland additions to the C++ language and introduce several key BCB classes such as AnsiStrings and Sets. These special classes emulate features of Object Pascal. Then, in Chapter 4 you will have a look at events. Chapter 5 focuses on exceptions, Chapter 6 on using Delphi code in BCB, and Chapter 7 on graphics programming with the VCL. The latter chapter will complete my introduction to the VCL and to the syntax that is common to almost all BCB programs.

When reading this chapter, you need to remember the basic philosophy of this book. My goal here is not to plumb the depths of C++, the VCL, the Windows API, or any other hardcore technical syntax. Instead, I want to show you how to quickly build real-world applications without losing touch with the underlying Windows architecture. In these chapters there are many times when I make a pass over very complicated subjects such as C++ constructors, templates, rules of precedence, the GDI, and so on. I am, of course, aware that these are sticky subjects that take many pages to cover appropriately. However, you will not find in-depth discussions of these subjects in this book, for there are many other volumes dedicated to those topics. Furthermore, the goal of this book is to show how to use RAD tools and high-level objects to perform complicated tasks quickly, easily, and safely.

C++ is already at least 10 times faster than interpreted languages such as Visual Basic, Java, or PowerBuilder. If slowing down performance by five percent yields a 10- or 20-fold increase in reliability or ease of use, I think it is worth it to play a somewhat more cautious game. In my opinion, it is better to be nine times faster and nearly as safe as an interpreted tool than it is to be 10 times faster and 10 times more dangerous than an interpreted tool. That last 5 or 10 percent that you can eke out of the language by using every imaginable trick just isn’t worth it, except in a few unusual circumstances such as compilers, operating systems, and game engines. Even in those cases, it is still probably best to use the relatively small and fast OOP-based techniques outlined in this book.

This particular chapter is unique in that it covers a number of technical subjects that are not very complex. Everything in this chapter is here because I either

  • Think that you have to know it in order to complete BCB programs.
  • Think that you have to know it in order to feel at all comfortable inside the BCB programming environment.

Don’t worry if you find most of the material in this chapter a bit too simplistic. There is some basic material that almost has to be covered in a book of this type, and once I get it out of the way, I will move on to more interesting subject matter in the next chapters.

It’s time now to get started with an overview of the BCB environment, project management, the VCL, and the basic syntax used by BCB programmers. When you have completed this and the next five chapters, you should have all the knowledge you need to begin a robust, broad exploration of the all the exciting features found in BCB.

Creating C++Builder Projects

C++Builder has a project manager that you can access from the View menu. You can use this tool to add files to a project or to remove files from a project.

You can add files with the following extensions to your project, and C++Builder will compile and/or link them automatically, as shown in Table 2.1:

Table 2.1. Files you can add to a BCB project.

Type of File Description
CPP C++ Source module. OWL and MFC are treated in the appendices.
C C Source module.
PAS Any Pascal module that will compile in Delphi 2.01.
RC Resource script.
RES Resource file.
OBJ Compiled C++, C, or PAS file.
LIB C or C++ Library file.
DEF Module Definition file.

You can use the IDE to produce Windows executables, DLLs, or console applications:

  • To create a 32-bit Windows executable, you need do nothing. The default behavior of the IDE is to generate this type of executable.
  • To create a DLL, go to File | New and select DLL from the Object Repository. Click OK. Everything else is automatic. I discuss exporting functions from a DLL in several later chapters of the book, including Chapter 26, “Extending an Internet Server with ISAPI.” In a word, the key to exporting a method from a DLL is to use __declspec(dllexport), as described in Chapter 26 and in the comments at the top of the file ISAPI1.CPPfrom Chapter 26.
  • To create a console application, go to the Options | Project | Linker option from the menu and select Console Application. If you want to create a console application as a quick way to produce text output, you should consider using the BCB TMemo, TListBox, and TEdit controls instead. I can output text to these controls at least as quickly as I can use printf or cout. I find these components are more useful than outputting text to the command line, because they support concepts like scrolling and saving their contents to a file or the clipboard.

NOTE: Delphi programmers need to remember that it is not enough merely to #include a C, CPP, or PAS file in a module of an existing project. You also have to add the file itself to the project using the Project Manager or the Add to Project menu choices or speed buttons. Delphi’s linker assumed that you would not reference a file from your uses clause unless you wanted it to be part of your project. C++Builder, for better or worse, makes no such assumption. You must incorporate the new file into your makefile listing, or it will not be linked into your project.

BCB projects are managed in a standard C++ makefile. The easiest way to get something into your makefile is through the project manager. Editing the makefile itself is not recommended, but C++ experts will find there are some changes to your project that can only be made by editing the makefile.

Most of the important changes which can be made to a makefile are configurable through the Options | Project or Options | Environment menu choices. The developers of BCB do not expect you to find many occasions when you will need to edit the makefile. I believe the primary reason the makefile exists is that the team grew tired of trying to manage a binary project file.

The Microsoft C++ team, on the other hand, recently grew tired of trying to manage a text-based project file! This is probably one of those cases where developers have a choice between two evils.

If you are trying to manage projects that consist of multiple executables and DLLs, you will almost certainly find the current BCB project manager inadequate. Borland C++ 5.02 will support compiling C++Builder projects. You will therefore want to consider using the advanced tools in BC 5.02 for managing huge projects.

BC5 also supports a powerful scripting language not available in BCB. As a result, I think some programmers will find a combination of BC5 and BCB to produce the ultimate C++ programming environment.

Having made my pitch to that special group of programmers who are managing massive projects, I want to end this section by stating that I find BCB includes everything I need and considerably more. The goal of this book is to talk about completing high quality projects as quickly and efficiently as possible. If that is your goal, stick with BCB and with third-party tools tailored for this environment. BCB is the ideal tool for creating C++ applications. It is state of the art and leagues ahead of any other C++ environment that is planned or available at the time of this writing.

BCB File Extensions

In the last section, in Table 2.1, I list the types of files you can include in C++Builder. Most of these files will be generated automatically for you by the compiler, and I list them here just so you will know why they exist and what they do. In this section, I will talk about all the important files that become part of your project. Table 2.2 lists the key extensions in BCB projects.

Table 2.2. File types used in a BCB project.

File extension Description File type
RC Source for resource file. Text
RES Resource file. There will usually be
one RES file with the same name
as your project that contains only an icon.
It’s best to leave this file alone.
CPP, C C++ source file. Text
PAS Delphi 2.01 source file. Text
H or HPP C++ header file. Text
DSK The location of files on the desktop. Text
DFM Binary file containing form definition. Use
CONVERT.EXE to translate into text.
MAK The project makefile in text format. Text
TDS Turbo debugger symbols. Binary
ILX Incremental linker symbols. Binary

When browsing this table, take special notice of the incremental linker files. These four files, all of which begin with ILX, are huge. They are the key files needed to produce BCB’s incredibly fast link times. If you turn incremental linking off, as explained later in this chapter, these files will disappear. Turning incremental linking off means that your compilation and link times will be from 5 to 10 times slower than they are with incremental linking turned on.

The include and lib Directory Paths Issue

There are, confusingly enough, two places where you can designate the paths to your include and lib files. One is located in the Options | Project | Directories/Conditionals menu choice, and the second is located in the Options | Environment | Library section. These pages are shown below in Figures 2.1, 2.2, and 2.3. There is also a Path for Source option in the Options | Environment | Preferences page.

FIGURE 2.1.The Options menu leads to the Project dialog where you can set paths for your project.

FIGURE 2.2.The Options menu is also the gateway to the Environment dialog where you can find the Library page.

FIGURE 2.3.The Options | Environment | Preferences page gives you a place to add the path to modules you include in your projects.

The BCB macro shown in the Path statements from Figures 2.1 through 2.3 resolves into the path that points to your current installation of BCB. This kind of information is stored in the Registry under HKEY_CURRENT_USER/Software and HKEY_LOCAL_MACHINE/Software. For instance, see the RootDir entry in HKEY_LOCAL_MACHINE/Software/C++Builder/1.0. To view the Registry, select Run from the Windows Start menu, type in the word RegEdit, and press the Enter key.

As a rule, you make changes specific to one project in the Options | Project dialog, and make global changes that you want reflected in all programs in the Options | Environment dialog. Use the Path for Source to include any directories that contain utility code that you use frequently.

As a rule, additions to these various path statements are made automatically when you add modules to your project through the Project Manager. However, there are times when I need to go in and explicitly edit one of these options.

Remember that if you are adding a component to the Component Palette, you have to add the path to that component in the Options Environment dialog or the Component Palette will not load. This addition to the Path statement will be made automatically if you add a component from inside the IDE. If you add the component from the command line by recompiling CMPLIB32.CCL, you need to update the Library path statement yourself. If you are using DLLs from inside a component, make sure the DLL is in a directory that is on your global DOS/Windows path. For instance, you might consider putting it in the Windows or Windows/System directory.

NOTE: The question of whether to call a C module used in a BCB program a unit or a module is something of an open matter in BCB. My inclination is to call it a module, because that is traditional C usage, but BCB seems to refer to them as units. To be utterly frank, this is the kind of issue that doesn’t really grip me all that deeply. In particular, I’m sure you will have no trouble understanding me regardless of which term I use. As a result, you will hear me referring to C modules as either modules or units, depending more on whim than on any clearly defined practice.

Working in the IDE

Here are some tips for working inside the IDE. I’ll make this section brief, because I don’t want to waste time on issues like this in a book that is clearly aimed at experienced programmers. However, this is a new environment, so it might help to share a few tips.

Whatever you do, be sure that you understand that this tool is meant to be used from inside its IDE. This is not a command-line environment!

NOTE: I’m sure that most programmers who investigate the matter will see that the command-line approach makes no sense with BCB. If that sentence strikes a sour note with you, all I ask is that you don’t develop contempt prior to investigation. In my opinion, this IDE has something so powerful to offer that it finally makes command-line programming obsolete. With BC5, and even with MSVC, I usually worked from the command line. I was one of the last of the hardcore C++ command-line junkies. With BCB, however, I have changed my ways. I’m totally sold on this environment, and would never consider going back to the command line except for a few rare situations.

Tips on Manipulating Controls

Here are a few tips for using the visual tools. If you are new to the environment, you should boot up BCB and follow along when reading these time-saving tips.

When dropping controls on a form, do the following:

  • Use the Control key plus the arrow keys to move the location of a component one pixel at a time. In particular, drop a component such as a button on a form. Select it with the mouse. Hold down the Control key and press the left arrow key.
  • Repeat the previous steps, only this time use Shift plus the arrow keys to resize a component one pixel at a time.
  • Hold down the Shift key when selecting a component from the Component Palette if you want to drop multiple copies of it on a form without having to go back to the palette. Click the “arrow” icon at the far left of the Component Palette to break out of this process.
  • Become familiar with the Align and Size options from the Edit menu. Quickly drop down five buttons on a form, each one below the last, without taking the time to carefully align their right and left sides. Hold down the Shift key, then select the five buttons with the mouse by clicking on each one. Now use the Align dialog from the Edit menu to align the tops or sides of all the selected controls.
  • A second technique for selecting a large group of components is to click on the main form and hold down the left mouse button while dragging over several components. When you let up the mouse, you will find the components are selected. If the components you want to select are resting on top of another control such as a panel, then you will need to hold the control button down before and during the process of dragging the mouse.
  • When designing a form, make it as large as you want. Then, when you have everything in place, use the Scale option from the Edit menu to make your form as small as you want, while still keeping each item on the form in proportion.
  • Right-click a component, as shown in Figure 2.4, to bring up a menu that lets you change the size, alignment, tab order, scaling, or creation order.

FIGURE 2.4.Right-clicking a TTable object to bring up a list of custom options.

Making the Most of the IDE

Here are some tips on using the IDE:

  • Right-click almost anything in the IDE to bring up a menu to configure the component or tool you are currently using. For instance, right-click the colorful toolbar at the top left of the environment. Select Properties from the popup menu to bring up the Toolbar editor. Now drag a colorful button from the toolbar onto the Toolbar editor and grab another button from the ToolBar editor and drag it back onto the toolbar. I sometimes delete the Trace, Trace Into, and Pause buttons from the extreme right of the toolbar and replace them with Copy, Cut, and Paste buttons or with compiler buttons such as Make, Build All, and Compile Unit.
  • Notice that you can view the Project Source and Project Makefile from the View menu. The project source contains the WinMain() or main()block for your code. You rarely will need to edit this code. Its contents are usually configurable from the Options | Project menu. For instance, you can change the code in the Project Source from Forms page of the Options | Project menu.
  • Check out the Project Manager, which is also available from the View menu.
  • You can lock the controls on a form by selecting the Lock Controls option from the Edit menu. If you have spent some time working on a form and want to be sure that it does not accidentally get changed, select Lock Controls, and it will not be possible to move the controls on that form, or any other, until you deselect this option.
  • If you want to set the text on the editor page to read only, right-click the editor page and select Read Only.
  • Watch out for the AutoScroll property of a form. This is set to true by default, but it can bite back if you leave it set to true and then move your form to a different resolution. For instance, if you move from 640×480 to 800×600, you generally should not have AutoScroll set to true, especially if your form is populated with a large number of controls.
  • Use the Positionproperty of a form to decide whether the form should first appear in the screen center, at the place where you positioned it at design time, or at a default location defined by Windows.
  • Use the WindowStateproperty of a form to decide if the form should first be shown minimized, maximized, or at normal size.
  • Before releasing a project to the public, check out its appearance in at least three different resolutions and make sure at least one of them toggles the font from Small Fonts to Big Fonts, or vice versa. (You can change Windows’ resolution by right-clicking the desktop, selecting Properties, and going to the settings page. Make sure you change between Big Fonts and Small Fonts during your testing!)

Project Options

Other than the path-related issues covered in the last section, there are only a few options that you need to know about when programming BCB. The rest of the setup-related issues are handled for you automatically by the environment.

All the options you choose in the Project and Environment dialogs are written to the Registry. If you want to write custom programs that change these settings, you can learn how to proceed by reading the sections on the Registry in Chapter 13, “Flat-File, Real-World Databases.”

The Options | Project menu has six pages in it:

Forms: This page is discussed in depth later in the chapter when I discuss the Project Source file for the ShapeDem program in the section called “Creating Forms.” The core functionality on this page addresses the question of which unit will be the main module for your application–that is, which will come up first when you start the program. A secondary issue addressed in this page is whether a form will have memory allocated for it automatically at startup, or whether you want to create it explicitly at some point during your application’s runtime. Forms listed in the left-hand list box shown on this form are created automatically; those on the right-hand list box must be created explicitly by the developer. The following code will create a form, show it to the user, and delete it:

Form2 = new TForm2(this); Form2->ShowModal(); delete Form2; 

This code would not work unless the header for Form2 was included in the module that wanted to call the code quoted here:

#include "unit2.h" 

Application: This is where you can set up the icon or help file for your project. This is an intuitive process; click Help in the dialog if you have questions.

C++: This is where you can set the Debug and Release compiler options. You can also do a small amount of fine-tuning here, but this book hardly ever steps beyond recommending that you use the Debug option in development and the Release version when you ship. I almost never have occasion to do more than choose the simple binary Debug or Release option, except for occasionally toggling the precompiled headers option.

Pascal: Here is where Pascal aficionados can fine-tune their code. I would recommend leaving all these options untouched unless you have a specific reason to change them. If you want to get involved in this page, the first level of advice is to turn Range and Stack checking on only during debug cycles, and to turn Optimizations on only when you ship.

Linker: This is where you can decide to produce a Windows or console application, an EXE, or a DLL. This is also the place where you can toggle the incremental linker on and off. In development, you probably want the incremental linker on to speed compilation; when you ship, you should test the size of your executables when it is off and when it is on, and ship the smallest version.

Directories / Conditionals:
The key features of this page were covered earlier in this chapter. Note that this is also where you can define conditionals. The whole subject of unit aliases is an Object Pascal-specific issue that enables you to create an alias for the name of a unit. For instance, the 16-bit version of Delphi kept all the Windows API calls in a unit called WinProcs.pas, and all the Windows types in a unit called WinTypes.pas. When the big segment sizes of 32-bit Windows became available, the two units were consolidated into one called Windows.pas. To remove the burden of having to change the uses (#include) statements in a Pascal file, the developers enabled you to create aliases. The most common alias told the compiler to use Windows.pas whenever it saw a request to include the WinTypes or WinProcs units.
As you can see, I don’t put a lot of weight on fine-tuning the settings for your project. If you flip through these pages and see the small number of options available, you can see that the developers were not very concerned about this issue either. One of the major goals of BCB is to make C++ once again a mainstream language. The programming world used to be much simpler than it is today. Now we are all expected to know about OLE, MAPI, the Internet, multimedia, or other cutting-edge technologies. I invest my time in learning these valuable new technologies, and ask little more of my compiler than that it link quickly and easily and automatically produce small, tight code.

Environment Options

There are six pages in the Options | Environment menu choice. I play with many of these options all the time because they do nothing more than tweak the appearance or feel of the IDE. You aren’t going to accidentally mess up the link process in your program or add 500KB to the size of an executable by tweaking one of these options. Feel free to set them as you please. Following is a list of the options I often play with during development.

There are some choices that are listed in both the Environment Options pages and the Project Options pages. If you make a change in the Project pages, you are changing an option for just that one project, while if you make the change in the Environment page, you are changing things globally for the entire environment. Local options always override global options.

Preferences: In the preferences page I always set Show Compiler Progress to true so that I can tell how far along I am in the compile cycle. I set AutoSave to true for Desktop files so that the environment will remember which project I was working on and which files I had open in the IDE. I also frequently tweak Break On Exception, depending on whether or not I want to catch problems in my code (turn it on) or just test to see if exceptions are popping up as expected at runtime (turn it off). This is also where you can turn integrated debugging on and off and change the path, as described above in the section on setting the project path.

Library: This is where you can set the path for include and lib files, as described previously. You can also globally decide for all projects whether or not to use the incremental linker. If you are adding components to the Component Palette, you should set Save Library source code to true so that you can build the Component Palette from the command line to save time or to repair a damaged Component library.

Editor: I discuss this page in a later section called “Feeling at Home in the IDE.” It is here you can customize the behavior of the editor. All the major third-party editors (CodeWright, SlickEdit, MultiEdit) have some customizations for BCB, but none of them can get into the environment to the degree to which you, I, and they would like. Hopefully, improvements will come in this area in later releases.

Display: I discuss this page in a later section called “Feeling at Home in the IDE.” It is here you can choose the keystroke emulation and font for the editor.

Colors: I discuss this page in a later section called “Feeling at Home in the IDE.” It is here you can customize the colors of the editor. It particular, it enables you to switch between different color schemes or customize the colors for each element in the language, such as string, identifiers, integers, and so on. Like all the settings mentioned in these pages, the results of your decisions are written to the Registry. The Address2 program from Chapter 13 shows how you could write custom programs that tweak the Registry. For instance, you could write a program that automatically switched between four or five additional color schemes.

: If you want to change the order in which components appear in the Component Palette, this is the place to make your changes. You can also reach this page by right-clicking the Component Palette and choosing Properties. It is pretty hard to do any serious damage to the environment using this page, but if you feel you need help, just press the Help button on the dialog itself.
As you can see, most of the options on these pages address only aesthetic or habit-based preferences regarding how the IDE works. From a development point of view, the key issues involve incremental linking, paths, and saving the source for the Component Palette. Make sure you understand those important issues before moving on to the next topic of discussion.

Feeling at Home in the IDE

To help make the IDE comfortable, you might go to the Options | Environment | Editor page, shown in Figure 2.5.

FIGURE 2.5.The Options menu gives you access to the Environments dialog where you find the Editor page.

From the Editor page you can make the following changes:

  • Turn the Use tab character option on or off, depending on your liking. (I prefer to turn it off, so I always know exactly what my code will look like regardless of the editor or tab settings I happen to use.)
  • Decide what tab stops you want to use. I set mine to 3 and 5.
  • Choose the Editor speed setting you want. You can choose between the Default keymapping, IDE Classic, Brief, or Epsilon emulations.
  • Go to the Colors page and set the colors you want to use in the editor.
  • Consider setting Undo after save to true so that you can keep a buffer of changes you make, even after you save.
  • There are third-party tools such as SlickEdit, MultiEdit, and CodeWright that have some degree of integration with C++Builder. However, none of these products is able to work as closely with the IDE as one would like, due to limitations in the current Tools API for BCB.

Converting Forms to Text and Back

Everything you can do in BCB through the visual tools you can also do in code. The visual tools are just a means of expediting the programming process. They do not supplant code, they complement it. This is what the Borland marketing department means when they talk about “two way tools.” The are two different ways to approach some parts of a BCB project: in code or by using the RAD tools.

If you right-click a form, you can select the View as Text menu item to convert a form to text. To convert back, just right-click the text version of the form.

BCB also ships with a command-line utility called Convert that will convert DFM files to text, or text to DFM files. At the command line type either

convert MyForm.dfm 


convert MyForm.txt 

The first example converts a binary form to a text form with the extension TXT, and the second example reverses the process.

If you have 4DOS on your system, you can use the following command to convert all the DFM files in a branch of subdirectories from DFM to text files:

global /I convert *.dfm 

This command will iterate through all the subdirectories below your current position and convert all the files in those directories to text. If you are concerned about archiving files, this is a good way to proceed. In particular, a text file is a much more robust storage medium than a binary file. If you lose one byte of a binary file, it may become worthless. Losing one byte from a text file rarely causes any serious mischief.

If you have one form and want to paste all or part of it into a second form, you can select multiple objects from the first form, choose Edit | Copy, focus the second form, and then paste the selections from the first form into it. If you want, you can have an intermediate step where you paste the items from the first form into a text editor such as Notepad, edit them, and then paste them onto a form.

NOTE: If you are a Delphi programmer and want to port a form from Delphi to BCB, you might consider using the technique outlined in the last paragraph as a way to proceed. Of course, you can compile your Delphi forms directly in BCB, but if you want to port them, just cutting and pasting to the clipboard is a good way to proceed.

Here is a what a BCB button looks like in text form:

object Button1: TButton Left = 96 Top = 16 Width = 75 Height = 25 Caption = `Button1' TabOrder = 0 end 

To get this code, I Alt+Tabbed out of my word processor over to BCB, selected a button on a form, and chose Edit | Copy from the menu. I then Alt+Tabbed back to my word processor, and chose Edit | Paste. During the process the Windows button was automatically converted to text.

Here is a second version of the button code that has been slightly modified:

object MyButton: TButton Left = 1 Top = 16 Width = 75 Height = 25 Caption = `My Button' TabOrder = 0 end 

As you can see, I have changed the name of the button from Button1 to MyButton, and I have changed the Caption and Left properties. Now I can select this text in my word processor, Alt+Tab over to BCB, select and form, and choose Edit | Paste to paste it back into the form. However, this time it has a new name, a new location, and new caption.

This is what is meant by a two-way tool. I can edit the form using the visual tools, or I can edit it in a word processor. It works in two different ways, depending on my current needs.

NOTE: When working with forms, remember that the currently selected component will be the target for a Paste operation. For instance, if I have selected a TButton object, and I chose Paste, BCB will attempt to make the control currently in the clipboard into a child of the button. In most cases, this is not what I want. Instead, I should first select a form or a panel, and then paste the controls onto that object. You also want to make sure the object you are pasting into is big enough to receive the control or controls you are about to dump from the Clipboard.

You have now made it through the first section of this chapter. In the next section I am going to switch my approach from a “hot tips” format to a more discursive style. If you want more information of the type you have seen so far in this chapter, you should look in the online help or pick up a book aimed at introductory BCB programming issues. Everyone has to know the kind of information I have been ladling out in the last few pages, and indeed it is vital information, but it is not the subject matter of this book. I have included this much only because I feel many of the issues addressed here are not immediately obvious when you first open BCB, and yet you absolutely have to know these facts in order to get any serious work done in the environment.

Core Technology: Components, Properties, Delegation

Many people are confused about Borland C++Builder. They are not used to the idea of having a RAD tool that works with C++, and they don’t know quite what to make of it when they see it.

Some people think they are seeing a code generator; others think this is a visual tool meant for programmers who don’t want to write code. Some people think they have found a great tool for building databases, and others a tool for prototyping applications.

There is some truth to all of these ideas, yet they all miss the mark if your aim is to find the essence of Borland C++. The core pieces of the technology are threefold:

  • Right up front you have components and properties.
  • Buried a little deeper you have the delegation model, which involves events and method pointers.
  • Tying the whole picture together are exceptions and a very sophisticated RTTI system located in a file called TYPINFO.HPP. Most programmers rarely have to deal with this side of the product, but it is part and parcel of what makes the tool possible in its current form.

These are things that lie at the core of C++Builder. Don’t let anyone else lead you astray with tales about prototyping or about BCB being a replacement for PowerBuilder. This tool may in fact perform those roles at times, but that’s not what it is all about.

NOTE: It may be that from a commercial perspective the majority of programmers will find the database support to be the most valuable aspect of this tool. Indeed, I spend a large portion of this book covering that subject. However, the emphasis on databases is market-driven, while the technological core of the product lies elsewhere.

To get at the heart of BCB, you have to understand components, you have to understand the delegation model, and you have to understand RTTI. In particular, the first two points are essential to an understanding of how this product works, while the third helps you understand why it works.

You have, no doubt, either already noticed or have heard talk about the fact that BCB has some proprietary extensions to C++. These extensions are there to support the creation and use of components as well as the associated concepts of properties and events that make components so powerful.

There was no way to create a product like BCB without extending C++ to support components, properties, and the delegation model. This is a better way to program, and there is no force in the world that can suppress it. I have no problem at all asserting that in five years time, all compilers will support these features and most programmers will use them by two years from now (1999).

Let me say it one more time, because this is so crucially important: What’s key is the component model, and its reliance on properties and events. Components, properties, the delegation model. Those are the things that stand at the heart of this technology. The three tools make it easy to build databases or multimedia applications. To say that the tool is primarily about building games or databases or Web sites is putting the cart before the horse. The tool is primarily about components, properties, and the delegation model. The other strengths of the tool fall out more or less automatically once the ground work has been laid.

Why the VCL?

Now that you know something about the environment in which BCB exists, it’s time to dig a little deeper and start examining the VCL object model used by BCB. The VCL (Visual Component Library) is an object-oriented library designed to ease the process of creating visual components.

NOTE: When I say that BCB uses the VCL, I mean for the phrase to be taken in at least two distinct ways. BCB uses the VCL in the sense that the physical IDE is literally built into VCL, and also in the sense that we, as BCB programmers, use the VCL as the object model of choice when creating applications. Borland is not asking you to do anything they wouldn’t do. Delphi is built into the VCL. BCB is built into the VCL, and much of Latte, the new Java product, is built into the VCL. The VCL is the tool of choice for people who have a choice.

Many C++ programmers who come to C++Builder find themselves wondering why the VCL exists in the first place. What was wrong with OWL or with MFC? Why should there be yet another object framework?

The simple answer is that visual programming, RAD, needed a whole new framework with new features. RAD relied on new concepts such as event handlers, properties, property editors, components, component editors, experts, forms, and a slew of other features. The language that implemented these new syntactical elements also desperately needed improvements in the areas of streaming, string handling, object initialization, and referencing.

These features simply were not available in either the C++ or Object Pascal versions of OWL. As a result, a new framework was created that supported these features; it is called the VCL, or Visual Component Library. The name goes a long way toward explaining why OWL could never do this job correctly. This is an object-oriented library built around visual components, and visual components do not have even the most oblique reference anywhere in OWL or MFC. They are a completely new entity and required their own object-oriented framework.

Having said that, I should add that VCL is closely related to OWL, just as the current version of OWL is closely related to the 16-bit version of OWL from which it grew. If you know OWL, you will find much in VCL that is familiar. Indeed, even MFC is a good background for understanding VCL. However, this is a fundamentally different kind of beast, one that is built around a new concept called a visual component.

NOTE: I am aware, of course, that ActiveX is another specification for building visual components. The difference between ActiveX and the VCL is that the VCL is specifically designed to be used with advanced programming languages such as C++ or Object Pascal. ActiveX was designed to be used in a broader context featuring a wide variety of languages and operating systems. ActiveX is more powerful than VCL, but it is also much bigger, much more complex, and slower.

Come on Charlie, Tell Us What You Really Think!

To conclude this brief introduction to the long discussion of the VCL found in this chapter, I feel it is important to explicitly state that I am aware that many hardcore C++ programmers will not automatically greet the VCL and its occasional bits of nonstandard C++ syntax with open arms. When writing this chapter, I am conscious of the need both to explain the VCL and also explain exactly why the VCL exists.

I want to make it absolutely clear that I am one hundred and ten percent committed to the VCL, and have absolutely no doubt that it represents the correct model for programming at this point in the ongoing development of programming tools and languages. I will occasionally make statements that explicitly justify some part of the VCL in the face of possible criticisms. These statements do not in any sense represent doubts in my own mind about the VCL. I prefer the VCL to OWL or MFC, and I am absolutely certain that all of the extensions to the C++ language that it introduces are necessary and represent significant advances for the language.

I am aware that some readers have large quantities of legacy OWL and MFC code that they want to preserve. I do not take those needs lightly and feel it is my obligation to state explicitly why changes have been made to the C++ object model.

BCB enables you to use MFC and OWL code, but the only reason this feature exists is to support legacy code. I personally do not think either MFC or OWL is the best choice any longer for large programming projects. The introduction of the component, property, delegation model offers such vast improvements in our ability to write code, that I don’t think it’s advisable to use OWL or MFC simply because of the poignant weight of all that legacy code. This is not a criticism of these two excellent object frameworks. The point is simply that they do not support components, properties, or events, and without that support they don’t meet my current needs. I simply cannot imagine that anyone else who works with BCB for any significant length of time could possibly come to any other conclusion.

I am aware, however, that this is a controversial subject. Over the last four years I have been using the VCL almost every day. Most of that experience is on the Delphi side, but I have also been using BCB every day for about five months at the time of this writing. During the last four years, I have had many occasions to also use MFC and OWL. After my first six months with the VCL, there was never one single time that I went back to MFC or OWL without the feeling that I was using a much loved but outdated system that lacked fundamental features that have become a necessary part of what I believe to be the best contemporary programming model. This doesn’t mean that I won’t use OWL or MFC if it has an existing object in it that I find appealing, but only that I prefer to use the VCL if that is an option. Indeed, in most cases, the VCL provides for all my needs.

If a language or programming model does not support properties, components, and delegation, I personally find it lacking, no matter how many other fine features it may present to the user. VCL is the right way to go, and it would be absurd to read my occasional arguments on its behalf as representative of doubts in my own mind about this programming model.

In a sense, my job would be easier if the VCL were harder to use. It was very frustrating for me to realize that I had to start leaving behind all that detailed knowledge about OWL in order to use a system that was so much simpler to use. Wasn’t there something that the VCL was missing? Didn’t there have to be a catch? How could the solution to so many long-term problems turn out to be so simple?

Well, I believe that there isn’t a catch, and that the VCL does everything that OWL or MFC did, but does it better. Of course, OWL and VCL have tremendous depth in terms of the number of objects in the existing hierarchy, which is one reason why BCB supports them. You will find, however, the VCL has great depth itself, and that it supports all the features, if not all the objects, found in MFC and OWL. In other words, if you find that a particular object you used in OWL is not part of VCL, you could either use the existing object or create a new one that does the same thing in the VCL. The VCL supports all the features of OWL, but may not at this time have duplicates of all its objects. Furthermore, there is tremendous existing third-party support for the VCL that helps fill in some of the gaps.

For good measure, the VCL adds some new tricks regarding components, properties, and events that can’t be found in either OWL or MFC. The kicker, of course, is that the VCL produces code that is at least as fast and small as OWL or MFC, but it is literally about ten times easier to use.

Let me give it to you straight. Back in the old days I loved OWL and thought it was the greatest thing I had ever seen. I used it all the time and was a fanatical adherent of that programming model. I now use VCL for everything, and go back to OWL or MFC only when I absolutely must. To my eyes, the support for components, properties, and events makes VCL clearly better than OWL or MFC in the same sense that OWL was clearly better than structured programming. If you love OWL, it is sad to hear this kind of thing, but components, properties, and events simply bring something new to the table that OWL and MFC simply can’t emulate.

It is hard to accept the rate at which programming languages are evolving at this time. The burden this places on programmers is immense. The size of this burden is one of the key reasons I advocate, again and again, doing things the simplest, easiest, safest way. You have enough to worry about without trying to figure out the last picayune details of constantly changing standards!

The learning curve associated with the onrush of progress, our attachment to legacy code, a sentimental attachment to the ANSI committee (of all things!)–none of these represent a reason to stick with an outdated technology when a clear advancement in programming tools appears. I obviously have a involvement with Object Pascal. But I am also a long-term (10 years) C++ programmer, and I know about the deep attachment we all feel to the rules of this language, and I know what a huge improvement OWL and MFC represent over structured programming. However, things have changed again, and personally, I love it! VCL is wonderful. I never waste two seconds thinking about going back to the old way of doing things.

NOTE: One final note on this subject ought to go out to readers of my Teach Yourself Windows and Teach Yourself Windows 95 Programming books. Those books talk about straight C Windows API programming (a la Petzold) without the aid of any object framework. I do not believe there is anything in this book that makes the material in those books obsolete.

To be a good Windows programmer you still have to know the Windows API, and you still have to know about message loops and window procedures. Indeed, in Delphi 2 Unleashed, I went on for several hundred pages about material of that sort. I do not include any of that kind of material in this book because there are many C++ programming books that cover that material. (There were not any, as far as I knew, Pascal books that covered that material, which is why I included it in Delphi 2 Unleashed.)

Needless to say, I think you ought to use the VCL to write contemporary Windows programs. However, if you also know the Windows API, you can become a great VCL programmer. If you don’t know the Windows API, you will always be at a loss when using some features of the VCL, at least until such time as Windows becomes a true object-oriented operating system. Do you have to know OWL or MFC to become a great VCL programmer? No.

Do you have to know the Windows API in order become a great VCL programmer? Absolutely! The Windows API material found in my Teach Yourself… books has a very long life from a technical, if not a commercial, point of view. Assuming that Java does not take over the world, a knowledge of the Windows API is always invaluable to a contemporary programmer.

Remember, however, that even the glorious VCL has a shadow over it, in the form of Java. I never get too bogged down in the details of the VCL or any other framework, because I never know when this rapidly changing programming world is going to enter another period of mind-numbing change in which the slow ones get left behind!

The Windows API is the only really complex programming paradigm that is worth learning in depth, because all the others are likely to change over time. The fact that the VCL is easy to use is not just a nice feature, it’s a necessity in this contemporary programming world where the only constant is change. I should perhaps add that the reason you use the VCL instead of the raw Windows API is because you get your work done in about one-tenth the time. If you use OWL or MFC, your code will be much bigger than if you use raw Windows API code, but you will also have a better chance of getting your work done on time. If you want another four- or five-fold increase in productivity, use the VCL.

Using the VCL

Now that you have heard an advertisement for the VCL, it might help to provide a few more basic examples illustrating some of the virtues of this programming system. These are very simple examples that are a bit atypical of the type of code you will see in this book, or even in the latter portions of this chapter. I feel, however, that these basic examples are useful when illustrating some of the key features of RAD programming with the VCL. Their presence ensures that everyone understands the benefits of visual programming with the VCL.

I will, however, use these basic examples to explore some fairly complex aspects of the VCL, and especially of the code that executes just before and after the main form of your application is made visible. In particular, I will look at the code in the project source file for a typical BCB application that uses the VCL.

The first program I want to discuss uses a standard Delphi component called TShape. If you open up BCB and drop the TShape component on a form, you will see that it draws a simple white rectangle on the screen.

Of course, the TShape object can perform more than this one simple trick. For instance, if you pull down the list associated with the Shape property in the Object Inspector, you see that you can easily work with ellipses, circles, squares, and other assorted shapes. Furthermore, if you expand the Brush property, you can change the shape’s color. The pen property enables you to change the width and color of the outline of a TShape object.

NOTE: Don’t forget that you can expand properties that have a plus sign (+) next to them by double-clicking the property’s name. A Color property always has a dialog associated with it. To bring up the dialog, double-click the area to the right of the Color property. This area is called the property editor. (Later in the book I will show how to create your own property editors and how to use existing property editors.) Select a color from the dialog, click the OK button, and the color you chose automatically takes effect.

As just described, it’s trivial to change the major characteristics of a TShape object at design time. However, I spoke earlier about BCB supporting two-way tools. Anything that you do with the visual tools you can also do in code. It is, of course, a little more work to make the same changes at runtime that you made at design time, but the basic principles are still simple. The SHAPEDEM and SHAPEDEM2 programs on the CD that accompanies this book show you how to proceed.

NOTE: I try to avoid it, but you might find a few places in the sample programs where I hard-code in the path to a file. You will probably have to edit these paths to get the program to run on your system.

I go to a great deal of effort to ensure that the code that accompanies this book works correctly. If you are having trouble running any particular program, check the readme files found on the CD that accompanies this book. If you still can’t get the program running, go to my Web site and see if there is an update, hint, or bug report available. My Web site is

At its core, the SHAPEDEM program consists of nothing more than a TShape object placed on a form, along with two scroll bars and a menu. What’s interesting about the program is the ease with which you can change the size, color, and shape of the TShape object at runtime.

You can find the code for the program in Listings 2.1 through 2.3. Remember that if you want to view the source for the project file in your application, you can select the View | Project Source menu item.

Listing 2.1. The code for SHAPEDEM.CPP.

#include <vcl.h> #pragma hdrstop USEFORM("Main.cpp", Form1); USERES("ShapeDem.res"); WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->Run(); return 0; } 

Listing 2.2. The header for the main unit in SHAPEDEM.

#ifndef MainH #define MainH #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <ExtCtrls.hpp> #include <Dialogs.hpp> #include <Menus.hpp> class TForm1 : public TForm { __published: TShape *Shape1; TScrollBar *ScrollBar1; TScrollBar *ScrollBar2; TColorDialog *ColorDialog1; TMainMenu *MainMenu1; TMenuItem *Shapes1; TMenuItem *ShapeColor1; TMenuItem *FormColor1; TMenuItem *Shapes2; TMenuItem *Rectangle1; TMenuItem *Square1; TMenuItem *RoundRect1; TMenuItem *RoundSquare1; TMenuItem *Ellipes1; TMenuItem *Circle1; void __fastcall ShapeColor1Click(TObject *Sender); void __fastcall FormColor1Click(TObject *Sender); void __fastcall Rectangle1Click(TObject *Sender); void __fastcall ScrollBar1Change(TObject *Sender); void __fastcall ScrollBar2Change(TObject *Sender); void __fastcall FormResize(TObject *Sender); private: public: virtual __fastcall TForm1(TComponent* Owner); }; extern TForm1 *Form1; #endif 

Listing 2.3. The code for the main unit in SHAPEDEM.

#include <vcl.h> #pragma hdrstop #include "Main.h" #pragma resource "*.dfm" TForm1 *Form1; __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { Shape1->Left = 0; Shape1->Top = 0; } void __fastcall TForm1::ShapeColor1Click(TObject *Sender) { if (ColorDialog1->Execute()) Shape1->Brush->Color = ColorDialog1->Color; } void __fastcall TForm1::FormColor1Click(TObject *Sender) { if (ColorDialog1->Execute()) Form1->Color = ColorDialog1->Color; } void __fastcall TForm1::Rectangle1Click(TObject *Sender) { Shape1->Shape = TShapeType(dynamic_cast<TMenuItem*>(Sender)->Tag); } void __fastcall TForm1::ScrollBar1Change(TObject *Sender) { Shape1->Width = ScrollBar1->Position; } void __fastcall TForm1::ScrollBar2Change(TObject *Sender) { Shape1->Height = ScrollBar2->Position; } void __fastcall TForm1::FormResize(TObject *Sender) { ScrollBar1->Max = ClientWidth - (ScrollBar2->Width + 1); ScrollBar2->Max = ClientHeight - (ScrollBar1->Height + 1); ScrollBar1->Left = 0; ScrollBar2->Top = 0; ScrollBar2->Left = ClientWidth - ScrollBar2->Width; ScrollBar2->Height = ClientHeight; ScrollBar1->Top = ClientHeight - ScrollBar1->Height; ScrollBar1->Width = ClientWidth - ScrollBar2->Width; } 

In the next few paragraphs, you’ll hear a discussion of how to change the color of the form, the shape shown on the form, and the size and shape of the object itself.

When you run the SHAPEDEM program, it looks like the screen shot shown in Figure 2.6. Use the program’s scrollbars to change the size of the figure in the middle of the screen. Use the menu to select a new shape for the object and to bring up a dialog that enables you to change the color of either the form or the shape.

FIGURE 2.6.You can use the scrollbars and buttons to change the appearance of the SHAPEDEM program’s form.

The Project Source: Where Pascal Meets the C

Before getting into any details about how the ShapeDem program works, it might be helpful to take one moment to look at the project source. You can access the project source from the View menu.

This is the place in the book I have chosen to give you a close look at how Borland blended its Pascal and C++ technology into one product. I will not show much Object Pascal code in this book, but you will see quite a bit in the next few pages.

At the top of the project source you see code that brings in the VCL:

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

In many programs, you will not have to add any other include statements to your program other than this one, except when you want to include other units from your current project, and even that can be automated through the File Include Unit Hdr menu option. That’s not a hard and fast statement; I only mean to imply that you don’t tend to spend a lot of time adding include statements unless you want to access obscure features of the Windows API. Many other include statements will be added to your header files, however, when you drop components down on a form.

The pragma statement shown here tells the compiler that you only want to have the VCL in your precompiled headers. Any additional files should be recompiled each time you do a build or a make. This is done for the sake of efficiency, because your own header files are likely to change on a regular basis.

The next few lines tell the project manager to bring in forms or resources:

USEFORM("Main.cpp", Form1); USERES("ShapeDem.res"); 

You would not normally add this kind of code yourself, but would ask the visual tools to insert it for you. In this case, the tool you would use is the Project Manager from the View menu. However, you don’t have to use the Project Manager; you can make this changes manually if you wish, and the Project Manager will pick up on your work.

Here is the WinMain block for your program:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->Run(); return 0; } 

As you can see, BCB assumes you won’t be using any of the parameters passed to it. In particular, the VCL provides a global variable called HInstance, which provides the HInstance for your application. The HPrevInstance variable is never used in Win32 programming. Parameters passed to your program are available in the form of a VCL function called ParamStr, and a variable called ParamCount. To get at the name and path of your executable, access ParamStr(0), to get at the first parameter passed to it, access ParamStr(1), and so on. ParamCount contains the number of parameters passed to your executable. For instance, the following code pops up a message box showing the name and path of your executable:

void __fastcall TForm1::Open1Click(TObject *Sender) { ShowMessage(ParamStr(0)); } 

NOTE: Wary C++ programmers may be concerned about the fact that the VCL has gotten at the HInstance and program parameters before they reached WinMain. Don’t worry, there is no huge subsystem underlying your entire program! However, a few things do happen before WinMain is called, just as a few things happen in all C++ compilers before WinMain is called.

This is a case where it might help to talk about how Object Pascal handles program startup. Object Pascal simply did not support WinMain on the grounds that it was faster and more convenient to perform processing of HInstance and the program parameters without setting up a stack frame for a function call. The Object Pascal system is faster and more efficient because you don’t have to push things on the stack before calling a function named WinMain. On the other hand, the overhead of calling WinMain with four parameters is hardly significant in the face of the time it takes to load a contemporary Windows program into memory. Of course, BCB provides a WinMain for you so you will be able to compile standard C++ programs without modification.

The key point to notice here is that the VCL provides extra support for you without affecting the performance of your program and without changing the way that C++, or standard Windows programs, operate. This is the right way to handle the interface between C++ and Object Pascal. No changes to C++, no impact on performance, no changes to the standard Windows programming model, and yet additional features are provided for the programmer in terms of ParamStr and the global HInstance.

After getting to WinMain, the program uses the pre-initialized Application object to get your program up and running:

 Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->Run(); 

I will discuss each of these calls in their own sections of this chapter. Brace yourself, because I am going to step you through the Object Pascal code that underlies each of these calls.

Initializing the Application

The first call in WinMain performs some initialization:


The two most important tasks performed by this code involve OLE and database code. If there is database programming in your application, the database code starts an object called TSession. If there is OLE code in your program, the program may call a method that updates the Registry automatically so that your program is a properly registered automation server. If the code uses neither technology, nothing happens in the call to initialize.

Here is the code for the Initialize method of TApplication as it appears in Forms.pas:

procedure TApplication.Initialize; begin if InitProc <> nil then TProcedure(InitProc); end; 

If you want to step through this code, simply copy Forms.pas, Controls.pas, Classes.pas, and VCL.INC from the BCB\SOURCE\VCL subdirectory into your project directory and add Forms.pas, Controls.pas, and Classes.pas to your C++ project. To add the files, bring up the Project Manager from the View menu, click the plus button, and use the drop-down list from the Files of Type section to browse for files with a .pas extension. Next, select Forms.pas, Classes.pas, and Controls.pas, and close the Project Manager. This technique is probably preferable to bringing in the source to the whole VCL by adding the CBuilder\SOURCE\VCL to the include or library path for your project.

When you step through this Object Pascal code in the BCB integrated debugger, you will find that InitProc is never called, because it is set to NULL unless you bring in database code or OLE automation code. Needless, to say, it takes one line of assembly code to test for NULL, so there is no significant overhead involved here other than the call to the Initialize method itself.

Here is the code at the bottom of the OLEAuto unit that would initialize InitProc if you used OLEAutomation in your program:

initialization begin OleInitialize(nil); VarDispProc := @VarDispInvoke; Automation := TAutomation.Create; SaveInitProc := InitProc; InitProc := @InitAutomation; end; finalization begin Automation.Free; OleUninitialize; end; end. 

This call starts by initializing OLE and then setting up a dispatch point for use when making calls into IDispatch. Next, it allocates memory for the Automation object, calls its constructor, and finally points InitProc at the proper method after saving the previous value of the function pointer. Of course, none of this code will be called unless you are using OLE Automation in your program through the routines found in the OleAuto unit.

Creating Forms

The second call in WinMain creates the MainForm for your application:

Application->CreateForm(__classid(TForm1), &Form1); 

You already have the Forms unit linked into the project, so you can step into this code without any further work. However, if you want to get into more detail here, you can also add Classes.pas and Controls.pas to your project. However, there are very few users of the VCL who really need to know what happens in either controls or classes.

Here is the call to CreateForm:

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference); var Instance: TComponent; begin Instance := TComponent(InstanceClass.NewInstance); TComponent(Reference) := Instance; try Instance.Create(Self); except TComponent(Reference) := nil; raise; end; if (FMainForm = nil) and (Instance is TForm) then begin TForm(Instance).HandleNeeded; FMainForm := TForm(Instance); end; end; 

The vast majority of this code does nothing but initialize variables or check for errors.

The base VCL object is called TObject. All VCL objects descend from TObject by definition. It is impossible to create a VCL object that does not descend from TObject, because any object that does not descend from TObject is not part of the VCL. The call to TObject.NewInstance does nothing more than allocate memory for an object and return a pointer to it, as you can see from viewing this call in System.pas:

class function TObject.NewInstance:TObject; asm PUSH EDI PUSH EAX MOV EAX,[EAX].vtInstanceSize CALL _GetMem MOV EDI,EAX MOV EDX,EAX POP EAX STOSD { Set VMT pointer } MOV ECX,[EAX].vtInstanceSize{ Clear object } XOR EAX,EAX PUSH ECX SHR ECX,2 DEC ECX REP STOSD POP ECX AND ECX,3 REP STOSB MOV EAX,EDX POP EDI end; 

Needless to say, this is probably the only place you will ever see anyone allocate memory for an object by calling NewInstance. As a rule, the constructor for an object will call NewInstance automatically. Here is the standard code for creating an object:

TMyObject *MyObject = new TMyObject(); 

This will call NewInstance for you automatically, and it would be madness to proceed in any other fashion.

NOTE: TObject.NewInstance is what is called in Object Pascal a class method and what C++ implements as a static method. Class methods and static methods can be called without an object instance; that is, they can be called before you allocate memory for an object or call its constructor. Class methods could have been implemented as functions that are associated with a class, and indeed, there is no significant difference between a function associated with a class and a class method. However, it is syntactically useful from the user’s point of view to include them in a class declaration, because it makes the association between the class and the method obvious. In other words, class methods are aesthetically pleasing, and they help you create logical, easy-to-read code. Besides NewInstance, the following methods of TObject are all class methods: ClassName, ClassNameIs, ClassParent, ClassInfo, InstanceSize, InheritsFrom, MethodAddress, and MethodName.

These methods are segregated out of the BCB declaration for TObject and declared as a class with the somewhat intriguing name TMetaClass. This metaclass is a trick that allows C++ to get along with the VCL and its associated RTTI. TMetaClass plays no significant role in standard BCB programming and is designed primarily for the use of the compiler team itself. You may have occasion to use this metaclass when working with RTTI, but as a rule, it lies outside the realm of standard BCB programming. If you have the time and inclination to pursue this matter, the whole class is declared and implemented in SYSDEFS.H.

For instance, the ClassType method of TObject returns a variable of type TClass, and TClass is defined as a pointer to TMetaClass. You can use variables of this type to perform the same kinds of comparisons you would perform on standard C++ classes with typeid.

The most important call in TApplication CreateForm is to Instance.Create(Self). It is the call that ends up calling the constructor for the main form, as well as calling the Windows API CreateWindowEx function. If you step into this code with the debugger, you will find that it ends up stepping right into the constructor for your main form:

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } 

The last few lines of code in the CreateForm method set the variable FMainForm to the current form if it has not already been assigned.

The main form for your application will be the one that appears first when someone launches your executable. As you can see from examining the code in CreateForm, the first object passed to CreateForm will be the main form for that application:

 if (FMainForm = nil) and (Instance is TForm) then begin TForm(Instance).HandleNeeded; FMainForm := TForm(Instance); end; 

Each project that you create can have zero, one, or more forms. You can add forms to a project from the File menu or from the File | New menu choice. If you add three forms to a project, this is what the project source looks like:

Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->CreateForm(__classid(TForm2), &Form2); Application->CreateForm(__classid(TForm3), &Form3); Application->Run(); 

In this case, Form1 will be the main form for the application. If you change the order of these statements, another form could become the main form:

Application->Initialize(); Application->CreateForm(__classid(TForm3), &Form3); Application->CreateForm(__classid(TForm1), &Form1); Application->CreateForm(__classid(TForm2), &Form2); Application->Run(); 

In the preceding code, Form3 is now the main form for the application.

Normally, I do not edit the project source for my application directly. Instead, I go to the Options | Project menu item and use the Forms page from the Project Options dialog to make these kinds of changes. Once again, this is a two-way tool, and you can do things visually via the Project Options dialog or you can do things manually in code. It’s up to you to make the decision.

Calling Run: Finding the Message Loop

The last call in WinMain is to the Run method:


TApplication.Run does a few initialization chores, and then calls a method called HandleMessage that in turn calls ProcessMessage:

function TApplication.ProcessMessage: Boolean; var Handled: Boolean; Msg: TMsg; begin Result := False; if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin Result := True; if Msg.Message <> WM_QUIT then begin Handled := False; if Assigned(FOnMessage) then FOnMessage(Msg, Handled); if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then begin TranslateMessage(Msg); DispatchMessage(Msg); end; end else FTerminate := True; end; end; 

This is the standard message loop that lies at the bottom of all Windows applications. As you can see, it calls TranslateMessage and DispatchMessage just like every other message loop in every other Windows application.

The HandleMessage routine that calls ProcessMessage also ends up calling a method named Idle. If you hook the OnIdle handler to TApplication, you can get a chance to perform background tasks while your application is running. It is generally not a good idea to respond to OnIdle events unless you are absolutely positive you know what you are doing. On the other hand, I would not suggest starting up a second PeekMessage loop in your application, so if you have to do background processing, I would indeed do it in response to OnIdle.

You now know what happens when a VCL application is first launched. I’ve shown it to you in such depth for two reasons:

  • You need to know this information if you are going to use BCB for serious work. You have to understand how your application is launched, where the message loop is, and how forms are allocated.
  • There has to be some time when you actually see the place where C++ and Object Pascal meet. So now you’ve seen it. The point I hope you take home from this is that there just plain isn’t any real difference between C++ and Object Pascal. There may be a difference between ANSI C and ANSI Pascal, but C++ and Object Pascal are the same. Certainly there is no significant difference in the way the two languages perform or in the capabilities of the two languages. It should also now be obvious that the compiler just doesn’t care which language you use. I mix and match C++ and Object Pascal all the time. I know both languages well enough so half the time I am not even conscious of which language I’m using. You can find a language bigot on every street corner. What’s rare is to find someone who can look beneath the surface and see that at bottom the two languages are virtually identical. The differences are almost all superficial, and they tend to cancel each other out. C++ does some things better than Object Pascal, and Object Pascal does some things better than C++. Who cares? The point is they are both great languages. Now you can use them both together without penalty, so you can take the best from both worlds.

Creating the ShapeDem Program

It’s time now to come back to the original purpose of this section of the chapter, which is to examine the ShapeDem program. To create the program yourself, start by dropping down a TMainMenu and a TColorDialog. The TColorDialog is found on the Dialogs page of the Component Palette, while the TMenu is on the Standards page. Now create a menu heading called Options and beneath it two menu items with captions that read Shape Color and Form Color.

NOTE: I briefly introduced using the Menu Designer in Chapter 1. Remember that you can get help on most (in a perfect world it would be all) BCB components, code elements, or tools by selecting the item in question and pressing F1.

After closing the menu designer, double-click the menu item you made called Form Color to create a method in the editor that looks like this:

void __fastcall TForm1::FormColor1Click(TObject *Sender) { if (ColorDialog1->Execute()) Form1->Color = ColorDialog1->Color; } 

When you run the program, the code shown here pops up the ColorDialog, as shown in Figure 2.7.

FIGURE 2.7.The Color Dialog gives the user an easy way to select a valid color at runtime.
If the user clicks the OK button in the form, the following line of code is executed:

Form1->Color = ColorDialog1->Color; 

This line of code sets the Color property for Form1 to the color that was selected by the user inside of ColorDialog1.

The technique just shown can be used to change the color of the TShape object. All you need to do is drop down a TShape object from the additional page, and then associate some code with the Shape Color menu item:

void __fastcall TForm1::ShapeColor1Click(TObject *Sender) { if (ColorDialog1->Execute()) Shape1->Brush->Color = ColorDialog1->Color; } 

What could be simpler?

You should now run the SHAPEDEM program so that you can see how easy it is to change the color of the elements on the form. Of course, you don’t have to give the user the exclusive right to control all the elements of your program. Sometimes you can take the initiative. For instance, you could change the color of your form or of an element on your form in order to focus the user’s attention on a particular part of the screen.

Notice that the code written here is all but self-documenting. Anyone with even the slightest acquaintance with programming can just glance at this procedure and determine what it does. Assuming you have more than a passing acquaintance with programming, here is how to translate the code into English: “If the user clicks on a visual element on Form1 that is called ShapeColor1, that visual element will delegate an activity to Form1. That activity consists of popping up a color dialog and asking the user to make a selection. If the user chooses the OK button, the color of Shape1 is set to the color selected in the TColorDialog object.”

What do I mean when I say that the ShapeColor menu item “delegates” an activity to Form1? Well, this means that the ShapeColor TMenuItem object does not itself handle being clicked, but instead allows the form to decide what happens when someone clicks it. It delegates the job to the main form.

The delegation model works through events, which are listed in the Object Inspector on the page sitting next to the properties for an object. Some people call events closures, though I regard that as a very technical term with certain platform-specific ramifications that I have never fully explored. As a result, I will usually play it safe and call events nothing more than events and leave it at that. The delegation model is implemented through events, and events are explored in depth in Chapter 3, “Events,” and Chapter 4, “Exceptions.”

In the beginning, it is probably simplest to think of events as being similar to standard Windows messages, such as WM_CREATE, WM_COMMAND, or WM_VSCROLL. Indeed, handling standard Windows messages is one of the functions of events. However, you will see that events can also delegate to another control tasks that you usually could not handle unless you subclassed a component such as an edit control, or else descended from an object that wrapped a control, as you would in OWL or MFC.

Perhaps an acceptable first crack at defining events would be to say that: “Events allow you to delegate tasks from one component to another component so that you do not have to subclass the first component, nor respond inside a window procedure to messages that the first control generates. In particular, events are usually delegated by the controls on a form to the form itself.”

The advantages of the delegation model are threefold:

  • They do not force you to subclass a control, nor inherit from a class in order to override one of its properties. For instance, you can change an edit control’s behavior without subclassing the control or descending from an OWL or MFC type object that wraps the control.
  • They enable you to forgo the ugly, lengthy, and confusing switchstatement found in standard window procedures.
  • It provides for contract-free programming. You can do whatever you want in an event handler. There are no rules binding what you can and cannot do inside an event handler. Any code you can write legally elsewhere in a program you can also write in an event handler.

It makes sense that it should not be very difficult to change the color of an object found on one of the forms you create. But using scrollbars to change its shape at least appears to be a more difficult task. In fact, experienced Windows programmers know that using scrollbars in a Windows program can be a fairly difficult task, one that requires you to trap and parse a number of messages in a complex switch statement. BCB, however, reduces the entire task of responding to a scrollbar to a single line of code.

To get started, first drop two scrollbars on the screen and set the Kind property of one of them to sbHorizontal, and the Kind property of the other to sbVertical. Now, turn to the events page of the Object Inspector and create a method for the OnChange event of each scrollbar. Fill in the methods with two lines of code so that they look like this:

void __fastcall TForm1::ScrollBar1Change(TObject *Sender) { Shape1->Width = ScrollBar1->Position; } void __fastcall TForm1::ScrollBar2Change(TObject *Sender) { Shape1->Height = ScrollBar2->Position; } 

The code shown here sets the Width and Height of the TShape object to the current position of the thumb on the scrollbar. Clearly it is extremely easy to write BCB code that performs a task, which would be relatively complex to execute if you had to work directly with the Windows API. The VCL always makes you feel as though you are working directly with an object, and tries to hide the complexities that are introduced by the Windows API or by standard object frameworks.

NOTE: Note in particular that you don’t have to first set a property of a control and then ask it to redraw itself! This magic is the result of the set method associated with the Height property of Shape1. I will explore the Set and Get methods of properties later in this chapter.

You use the program’s menu to change the shape of the TShape component. In particular, a portion of the main menu for the program should have the following items on it:

Rectangle1: TMenuItem Tag = 0 Caption = `Rectangle' Square1: TMenuItem Tag = 1 Caption = `Square' RoundRect1: TMenuItem Tag = 2 Caption = `RoundRect' RoundSquare1: TMenuItem Tag = 3 Caption = `RoundSquare' Ellipes1: TMenuItem Tag = 4 Caption = `Ellipse' Circle1: TMenuItem Tag = 5 Caption = `Circle' 

The Tag field is a special field associated with all components that can be set to an integer value. The VCL has no use for this field; it is designed explicitly for you to use as you wish, for whatever purpose you want.

All six menu items should be associated with the same event handler through their OnClick method. You can create the original handler by open up the Menu Designer, turning to the Events page in the Object Inspector, and double-clicking the OnChange event. If you then select the OnChange event for the other menu items, you will see that it opens up into a combo box from which you can select all the compatible events. For each of the other five menu items, select the event you created for the first menu item. The event itself should look like this:

void __fastcall TForm1::Rectangle1Click(TObject *Sender) { Shape1->Shape = TShapeType(dynamic_cast<TMenuItem*>(Sender)->Tag); } 

I will explain what this code means over the course of the next few paragraphs.

NOTE: Just now I said that the events that appear in the drop-down combo for the Events page of the Object Inspector must be compatible with a particular event. This means that they must have the same signature, which is yet another term that needs explanation! The signature of an event is found in the header for the method handler associated with a particular event, and in particular it is represented by the parameters passed to the handler. For instance, the signature for the Rectangle1Click method is represented by the fact that it is a method that returns nothing and which accepts a single parameter of type TObject *. Methods that look like this are of type TNotifyEvent. Here is the declaration for TNotifyEvent as it appears in CLASSES.HPP:

typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender);

When you see this signature for an event, you can assume that Sender contains an instance of the object that sent the event. For instance, in the case currently under consideration, it is a TMenuItem that sent the event, and the specific TMenuItem that sent the message is passed in the Sender parameter.

The items in the menu designate each of the possible shapes the TShape component can assume. You can find these words listed in the online help under the listing for TShapeType. Or, if you want to go back to the original source code, you find the following enumerated type:

enum TShapeType { stRectangle, stSquare, stRoundRect, stRoundSquare, stEllipse, stCircle } 

NOTE: You can also access the names of the members of enumerated type by using the GetEnumName and GetEnumValue functions from the TypInfo unit, which is pronounced “tip-info.”

In this particular case, you need to write only one line of code in response to the event that occurs when a user clicks a TMenuItem:

Shape1->Shape = TShapeType(dynamic_cast<TMenuItem*>(Sender)->Tag); 

This line of code sets the Shape1->Shape property to the shape that the user has selected in the combo box. The code works because of the correspondence between the ordinal members of an enumerated type and the numerical value you assigned to the tag property of a menu. In other words, the first element in an enumerated type has the value zero, as does the first tag property.

You know, and I know, that the Sender variable contains an instance of the TMenuItem item class. However, the wonders of polymorphism allow BCB to declare this variable to be of type TObject. That way, a TNotifyEvent can accept objects of any type. (Polymorphism will be addressed later in the book in Chapter 21, “Polymorphism.”)

The programmer’s knowledge of the Sender parameter needs to be shared with the compiler. In other words, you and I need to have some way of telling the compiler that the object is not really of type TObject, but that it is a just a polymorphic disguise for a TMenuItem. This is an important step because the TObject class does not have a Tag field, and the TMenuItem class does have a Tag field. In this case, it is absolutely necessary to get at the Tag field because it contains the code information about the shape the user wants to select.

To cast a TObject as a TMenuItem you can use the dynamic_cast syntax. This syntax can be used as part of RTTI to test whether a component is of a particular type, or it can be used to actually make the cast. In this case I am daring and make the cast without bother to test it first. This is safe in this case because I know the only object that can be passed here is a TMenuItem. However, if I wanted to be extra careful, I could write the following:

if (dynamic_cast<TMenuItem*>(Sender)) Shape1->Shape = TShapeType(dynamic_cast<TMenuItem*>(Sender)->Tag); 

This would ensure that no exceptions were raised if the cast should happen to fail, which it won’t in this particular case.

The final part of the ShapeDem program that is worthy of discussion involves making sure that the scrollbars cling to the bottom and right edges of the control. To do this, you need to respond to WM_SIZE messages, which come to BCB programmers under the friendly guise of an OnResize event:

void __fastcall TForm1::FormResize(TObject *Sender) { ScrollBar1->Max = ClientWidth - (ScrollBar2->Width + 1); ScrollBar2->Max = ClientHeight - (ScrollBar1->Height + 1); ScrollBar1->Left = 0; ScrollBar2->Top = 0; ScrollBar2->Left = ClientWidth - ScrollBar2->Width; ScrollBar2->Height = ClientHeight; ScrollBar1->Top = ClientHeight - ScrollBar1->Height; ScrollBar1->Width = ClientWidth - ScrollBar2->Width; } 

This code uses third grade math (the only kind I ever understood!) to ensure that the scrollbars are allowed as tall or as wide as the form, no matter how it is stretched or pulled by the user. Furthermore, it ensures that the Min and Max property for the control ranges from zero to the exact size of the current client window. This ensures that you can use the OnChange event for the scrollbar to make the TShape object as large as the client window, but no larger.

Notice also that the TForm object has properties called ClientWidth and ClientHeight. These properties calculated the client size of the current window; that is, the size of the window minus the menu, caption, and frame. If this was done for you, you would have to write code that looked something like this:

int Menu, Caption, Frame; Caption = GetSystemMetrics(SM_CYCAPTION); Frame = GetSystemMetrics(SM_CXFRAME) * 2; Menu = GetSystemMetrics(SM_CYMENU); ScrollBar1->Left = 0; ScrollBar2->Top = 0; ScrollBar1->Max = Width; ScrollBar2->Max = Height; ScrollBar2->Left = Width - Frame - ScrollBar2->Width; ScrollBar2->Height = Height - Frame - Caption- Menu; ScrollBar1->Top = Height - ScrollBar2->Width - Frame - Caption - Menu; ScrollBar1->Width = Width - ScrollBar2->Width - Frame; 

The point here is that without having to know about GetSystemMetrics and all its associated constants, you can still write code that calculates the size of the TShape object down to the last pixel.

A First Look at RTTI and TypInfo

If you look on the disk, you will find a second copy of the ShapeDem program, called ShapeDem2, that uses a combo box as well as a menu to let the user select the current shape of the object. For instance, you can drop down the combo box and pick a shape such as stCircle or stSquare. These shapes have funny-looking Hungarian squiggles prefixed to them because they are taken directly from the source code of the program at runtime rather than typed in by the programmer at design time. In the next few paragraphs I explain how to use that control, primarily because it also contains an interesting description of how to use Run Time Type Information.

You would think that you need to explicitly type in the names of the shapes that appear in the combo box. For instance, you might assume you need to manually type in the words stCircle and stSquare, and so on. These are the same names you see listed in the Object Inspector for the Shape1 object under the property called Shape, and they are the same words that appear in the combo box at runtime. In other words, if you highlight Shape1 on the form and look at the Shape property in the Object Inspector, you find a list of the possible shapes that can be associated with this object. These are the same shapes you should list in the combo box.

As I said earlier, it’s not possible to get access to the Object Inspector at runtime. As a result, if you wanted to explicitly type in the names, you would need to first pop open the Property editor for the Items property, and then manually type these names. To get started, first highlight the combo box on the form by clicking it. Then, double-click the right side of the Items property in the Object Inspector, or you can click the […] button on the Strings property once. This pops up a String list editor, as shown in Figure 2.8.\

FIGURE 2.8.The String list editor enables you to type in a set of default names that appear in a combo box.

NOTE: In the bottom-left corner of the String list editor is a button that says “Code Editor.” If you press this button you can edit your list inside the regular editor for the IDE. This can be especially useful with SQL query statements, which actually provide syntax highlighting. You access the SQL list editor from inside a TQuery component as explained in Chapter 10, “SQL and the TQuery Object.”

The actual items that you would type into the String list editor are shown next. Be sure to type them in exactly as shown, and in the identical order.

stRectangle stSquare stRoundRect stRoundSquare stEllipse stCircle 

Now when you run the program, the user can drop down this list and select a shape. Here is the code associated with the OnClick event for the combo box:

void __fastcall TForm1::ComboBox1Change(TObject *Sender) { Shape1->Shape = TShapeType(ComboBox1->ItemIndex); } 

As you can see, there is no significant difference between this code and the code written in response to a click on the shapes listed in the menu. Of course, in this case you don’t have to perform a dynamic cast, but that is a mere bagatelle.

The interesting thing about this second version of the ShapeDem program is the code that appears in the constructor for the form:

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { int i; PPropInfo PropInfo = GetPropInfo(PTypeInfo(ClassInfo(__classid(TShape))),"Shape"); for (i = 0; i < 6; i++) ComboBox1->Items->Add(GetEnumName(PropInfo->PropType, i)); ... // Code irrelevant to this example omitted here. } 

This code uses RTTI to retrieve the names of the enumerated type that underlies the Shape property for the TShape object.

All VCL classes are illuminated with type information. You can find out virtually anything you want about these published properties of a class at runtime merely by asking through one or more of the functions in the TypInfo unit.

RTTI is an essential part of RAD programming because there must be a way for the Object Inspector to query an object about its published properties. For instance, the Object Inspector has to list the names of the TShapeType so that you can select them from the Property editor for the Shape property. The code shown in the constructor for the main form of this application uses the same technique to retrieve this information that the Object Inspector uses. It would not do to have BCB developers type in this information manually before releasing the project because the Object Inspector must be able to retrieve this information for any component, including the ones that you create or find after purchasing the product.

Are classes illuminated with RTTI larger than non-illuminated classes? You bet! RTTI is bought at a price. However, it is a price that I am willing to pay for two reasons:

  • It makes RAD possible, as described previously in the text that explains how the property types are listed in the Property editor.
  • It enables me to query objects at runtime. Querying objects at runtime gives me the ability to create generic code that will work automatically, regardless of the type of object I pass to it. For instance, the RTTI example using dynamic_cast shown previously explains how you can safely test the type of an object before performing an action on it. You will see many examples of that type of code in this book, including cases where you can pass an entire form to a routine, and ask that routine to perform some function on all the controls of a certain type on that form. Generic code of that type can be tested once and then used over and over again with multiple objects. The ability to talk to an object and ask it its type gives us the ability to manage objects automatically. This can be especially useful in Ole Automation, and particularly in DCOM. For instance, you can start wandering about on a network, looking for objects. If you find one, you can use RTTI to ask it questions about itself, and to query its capabilities!

Using the RGB Function

In this section I take a very quick look at a second program that uses many of the same controls from the first program. This is just an example, but it is interesting in that it involves using at least one simple Windows API function, or rather, macro. It’s important to understand that you can, of course, call the Windows API whenever you want.

Whenever a TShape component is painted, its interior and border are drawn in particular, predefined colors. By default, these colors are white and black, respectively. More specifically, the interior of the ellipse is filled with the color of the currently selected brush. You can change this color by making an assignment of the following type:

Shape1->Brush->Color = MyNewColor; 

The RGBSHAPE program on your disk shows how you can get very specific control over the colors of an object that you paint to the screen. The letters RGB stand for red, green, and blue; each of the these colors makes up one of the colors passed to the Windows API RGB macro itself:

COLORREF RGB( BYTE bRed, // red component of color BYTE bGreen, // green component of color BYTE bBlue // blue component of color ); 

The parameters passed to this function describe an intensity to be assigned to one of these three colors. These numbers always exist within a range between 0 and 255.

If you pass the RGB function the following parameters, it will return a long integer representing the color red:

void __fastcall TForm1::Button1Click(TObject *Sender) { int Red; Red = RGB(255, 0, 0); Shape1->Brush->Color = TColor(Red); } 

The Color property of a TBrush object is of type TColor, but TColor is nothing but an enumerated type ranging over all the possible values that can be returned by the RGB macro.

NOTE: You can call the entire Windows API from inside BCB. However, most of the time your calls to the Windows API will be mapped through WINDOWS.HPP, which is a wrapper around the Pascal version of these calls. The Object Pascal team did not translate all the headers for the Windows API. As a result, when you call some of the more obscure or some of the most recent Windows API functions, you may have to explicitly include the header files for these calls. For instance, there is no Pascal translation of the headers for DirectX. As a result, you must include DDRAW.H, and so on in your project if you want to make calls to DirectDraw or other DirectX functions. The vast majority of Windows API calls are in WINDOWS.HPP, however, and that unit is included in all your projects automatically, so you don’t have to #include anything in your projects. Needless to say, all Windows API calls are just mappings into a DLL, and it doesn’t matter one wit whether you are mapped into the call through Pascal or C++. The compiler does the exact same thing in both cases, and there is no difference in performance, size, and so on.

Here’s how you get the colors green and blue:

Green = RGB(0, 255, 0); Blue = RGB(0, 0, 255); 

If you combine these three colors in various ways, you can produce particular shades. For instance, if you drop a button into a form and respond to a click on the button with the following code, you draw a bright yellow ellipse on the screen:

Shape1->Brush->Color = RGB(255, 255, 0); Shape1->Shape = stEllipse; 

To achieve the color gray, pass in the following parameters:

Gray = RGB(127, 127, 127); 

To get a fleshlike color, enter

Skin = RGB(255, 127, 127); 

You see how it works. Remember that the first parameter controls the amount of red in the final color, the second the amount of green, and the third the amount of blue. RGB: red, green, blue!

The RGBSHAPE program has a TShape component, three labels, three scrollbars, and three edit controls.

The RGBSHAPE program has only one method:

void __fastcall TForm1::ScrollBar1Change(TObject *Sender) { Shape1->Brush->Color = RGB(ScrollBar1->Position, ScrollBar2->Position, ScrollBar3->Position); Edit1->Text = IntToStr(ScrollBar1->Position); Edit2->Text = IntToStr(ScrollBar2->Position); Edit3->Text = IntToStr(ScrollBar3->Position); } 

This method first uses the current positions of the scrollbars to assign a color the TShape objects brush. To make this work correctly, I set the Max property for each scrollbar to 255. When the color has been drawn on the screen, I show the actual numbers passed to the scrollbar in the edit components.

The point of the RGB program is to give you a graphical representation of the way the RGB function works. You might also find that this program helps you choose colors that you want to use in your own programs.

NOTE: When working with the RGBSHAPE program, some users may find that Windows cannot create pure tones for some colors, but instead creates a kind of patchwork that approximates the shade described by the parameters passed to the RGB function. However, you can generally get pure tones if you set each of the parameters to 0, 128, or 255. Numbers halfway between 0 and 128 also usually produce pure tones. Of course, the actual results you see depend on whether you are using a 16-color card, 256-color card, or some video card that offers many thousands of colors. You also need to have the correct video drivers in place. For instance, you don’t want to be using a powerful video card and get only 16 colors from it simply for want of the right driver! If you suspect your card is not performing correctly, get on the Web, visit the home page of the company that makes your video card or computer, and download the latest drivers. In Windows 95, you can usually simply unzip the drivers into a temporary directory, right click the desktop, and select Properties | Settings | Change Display Type. When Windows asks for your new drivers, simply point it at the directory where you unzipped the files and it will add them to the system automatically. Be sure to test your work before you restart Windows!

Listing 2.4. The code for the main unit in the RGBSHAPE program.

#include <vcl.h> #pragma hdrstop #include "Main.h" #pragma resource "*.dfm" TForm1 *Form1; __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } void __fastcall TForm1::ScrollBar1Change(TObject *Sender) { Shape1->Brush->Color = RGB(ScrollBar1->Position, ScrollBar2->Position, ScrollBar3->Position); Edit1->Text = IntToStr(ScrollBar1->Position); Edit2->Text = IntToStr(ScrollBar2->Position); Edit3->Text = IntToStr(ScrollBar3->Position); } 


In this chapter you have been introduced to the basic facts about Borland C++Builder. In particular, you learned about the environment, manipulating components, and some of the basic tricks of RAD programming. You also had a brief introduction to some advanced topics such as RTTI.

By now the boards are clear to head into some more technical subject matter, such as the examination of extensions to the language featured in the next chapter. After that you will look at events, exceptions, graphics, and sharing code with Delphi. By the time you have finished all these sections, you will have a solid base from which you can launch an exploration of how to use BCB to create cutting-edge Windows applications.

There is so much information to give out in a book like this that I sometimes forget to mention how much I love this programming environment. All the information I am presenting here adds up to a tool that is more powerful, more flexible, and easier to use than any other C++ compiler on the market. Furthermore, this is just the 1.0 version of a product that should become the environment of choice for serious programmers during the next few years.

Về vdhungbg
Tin tuc cap nhat - moi luc - moi noi

15 Responses to Basic Facts About C++Builder

  1. Đại Học nói:

    good discussion regarding this piece of writing here at this blog, I have
    read all that, so at this time me also commenting here.

    I am sure this article has touched all the
    internet people, its really really pleasant
    article on building up new web site.|
    Wow, this paragraph is nice, my sister is analyzing such things, so I am going to let
    know her.|
    bookmarked!!, I love your site!|
    Way cool! Some extremely valid points! I appreciate you writing this article and
    the rest of the site is extremely good.|
    Hi, I do believe this is an excellent web site. I stumbledupon it😉
    I’m going to return yet again since i have bookmarked it. Money and freedom is the greatest way to change, may you be rich and continue to guide others.|
    Woah! I’m really enjoying the template/theme
    of this site. It’s simple, yet effective. A lot of times it’s hard to get that “perfect balance” between user friendliness and appearance.
    I must say you’ve done a superb job with this. Additionally, the blog loads very fast for me on Chrome. Outstanding Blog!|
    These are actually enormous ideas in about blogging. You have touched some good things here. Any way keep up wrinting.|
    I like what you guys are usually up too. This kind of clever work and reporting! Keep up the amazing works guys I’ve incorporated you guys to
    my personal blogroll.|
    Hi there! Someone in my Myspace group shared this website with us so I came to give it a look.
    I’m definitely loving the information. I’m book-marking and will be tweeting this to my followers!
    Fantastic blog and excellent style and design.
    I love what you guys are up too. This sort of
    clever work and reporting! Keep up the awesome works guys I’ve incorporated you guys to my blogroll.|
    Hello would you mind stating which blog platform you’re using?
    I’m planning to start my own blog soon but I’m having a
    tough time deciding between BlogEngine/Wordpress/B2evolution and
    Drupal. The reason I ask is because your design
    seems different then most blogs and I’m looking for something unique. P.S My apologies for getting off-topic but I had to ask!|
    Hey there would you mind letting me know which webhost you’re using?
    I’ve loaded your blog in 3 completely different browsers and I must say this blog loads a lot faster then most. Can you recommend a good web hosting provider at a fair price? Many thanks, I appreciate it!|
    Everyone loves it when individuals get together and share ideas. Great blog, stick with it!|
    Thank you for the good writeup. It in fact was a amusement account it. Look advanced to more added agreeable from you! However, how could we communicate?|
    Hey just wanted to give you a quick heads up. The text in your article seem to be running off the screen in Internet explorer. I’m not sure if this is a format
    issue or something to do with web browser compatibility but
    I thought I’d post to let you know. The style and design look great though! Hope you get the problem fixed soon. Thanks|
    This is a topic that is near to my heart… Best wishes! Exactly where are your contact details though?|
    It’s very easy to find out any topic on net as compared to books, as I
    found this post at this web page.|
    Does your website have a contact page? I’m having a tough time locating it but, I’d like to send you an e-mail.
    I’ve got some suggestions for your blog you might be interested in hearing. Either way, great blog and I look forward to seeing it improve over time.|
    Hey there! I’ve been reading your website for a
    while now and finally got the bravery to go ahead and give
    you a shout out from Porter Texas! Just wanted to say keep up the fantastic
    Greetings from Ohio! I’m bored at work so I decided to browse your site on my iphone during lunch break. I really like the info you provide here and can’t wait to take a look when I get home.
    I’m surprised at how fast your blog loaded on my phone .. I’m not even using WIFI, just 3G .
    . Anyways, good site!|
    Its such as you read my mind! You appear to grasp a lot
    approximately this, such as you wrote the ebook in it or something.
    I feel that you just can do with a few percent to drive the
    message home a bit, however other than that, this is magnificent blog.
    An excellent read. I’ll certainly be back.|
    I visited various websites but the audio feature for audio songs current at this web site is in fact excellent.|
    Howdy, i read your blog from time to time and i own a similar one and i was just wondering if you get a lot of spam responses? If so how do you reduce it, any plugin or anything you can advise? I get so much lately it’s driving me mad so any help is very much appreciated.
    Greetings! Very useful advice in this particular article!
    It’s the little changes that produce the most important changes. Thanks for sharing!|
    I truly love your blog.. Very nice colors & theme. Did you develop this site yourself? Please reply back as I’m wanting to create my very
    own website and would like to learn where you got this from
    or just what the theme is named. Many thanks!|
    Hello there! This article could not be written any better!
    Going through this article reminds me of my previous roommate!

    He always kept talking about this. I’ll forward this information to him. Pretty sure he’ll have a good read.
    Many thanks for sharing!|
    Whoa! This blog looks exactly like my old one!
    It’s on a entirely different subject but it has pretty much the same layout and design. Excellent choice of colors!|
    There is definately a lot to know about this topic. I really like all the points you have made.|
    You have made some really good points there. I checked on the web for more information about the issue and found most people will go along with your views on this website.|
    What’s up, I log on to your blogs on a regular basis.
    Your story-telling style is witty, keep it up!|
    I just couldn’t leave your site prior to suggesting that I extremely enjoyed the standard information an individual supply to your guests? Is going to be back frequently to investigate cross-check new posts|
    I want to to thank you for this great read!! I absolutely loved every little bit of it. I have got you saved as a favorite to check out new things you post…|
    Hi there, just wanted to say, I loved this blog post. It was funny. Keep on posting!|
    I comment each time I especially enjoy a article on a website or I have something to add to the conversation. It is a result of the sincerness communicated in the post I looked at. And on this article Basic Facts About C++Builder Phuongthengocdtt’s Blog.
    I was moved enough to post a comment😛 I do have a couple
    of questions for you if it’s okay. Could it be simply me or does it look like some of these remarks come across as if they are coming from brain dead individuals?😛 And, if you are posting on additional sites, I would like to follow you. Would you list every one of your communal sites like your linkedin profile, Facebook page or twitter feed?|
    Hello, I enjoy reading through your article. I wanted to write a little comment to support you.|
    I always spent my half an hour to read this web site’s content all the time along with a mug of coffee.
    I constantly emailed this weblog post page to all my contacts, for
    the reason that if like to read it afterward my contacts will too.
    My developer is trying to convince me to move to .net from PHP.

    I have always disliked the idea because of the expenses.
    But he’s tryiong none the less. I’ve been using WordPress on several websites for about a year
    and am anxious about switching to another platform.
    I have heard great things about
    Is there a way I can import all my wordpress content into it?

    Any help would be greatly appreciated!|
    Hi there! I could have sworn I’ve visited this website before but after looking at some of the articles I realized it’s
    new to me. Anyhow, I’m certainly delighted I discovered it and I’ll be book-marking it and checking back often!
    Terrific work! That is the kind of info that are supposed to
    be shared across the net. Disgrace on Google for not positioning this put up higher!

    Come on over and seek advice from my website . Thank you
    Heya i am for the first time here. I found this board
    and I find It truly useful & it helped me out a
    lot. I hope to give something back and aid others like you helped
    Hi, I believe your blog could be having browser
    compatibility issues. When I take a look at your website in Safari, it looks fine however, if opening in I.

    E., it has some overlapping issues. I just wanted to give you a quick
    heads up! Aside from that, wonderful site!|
    A person necessarily assist to make significantly posts
    I might state. This is the first time I frequented your website page and thus far?
    I surprised with the research you made to make
    this actual submit extraordinary. Great activity!|
    Heya i am for the first time here. I came across this board
    and I find It really useful & it helped me
    out much. I’m hoping to provide something back and aid others like you aided me.|
    Hi! I simply want to offer you a big thumbs up for your excellent information you have here on this post. I will be coming back to your web site for more soon.|
    I always used to read paragraph in news papers but now as I am a user of net thus from now I am using net for posts, thanks to web.|
    Your way of telling all in this piece of writing is truly good, all can easily understand it, Thanks a lot.|
    Hello there, I found your blog by means of Google while looking for a similar topic, your website came up, it seems to be good. I have bookmarked it in my google bookmarks.
    Hi there, simply changed into alert to your weblog via Google, and located that it’s truly informative.
    I’m gonna be careful for brussels. I’ll appreciate in the event you proceed this in future.
    Numerous folks will be benefited from your writing.
    I’m curious to find out what blog platform you are using? I’m
    experiencing some small security issues with my latest blog and I would like to find
    something more safe. Do you have any recommendations?|
    I’m really impressed with your writing skills as well as with the layout on your blog. Is this a paid theme or did you customize it yourself? Either way keep up the excellent quality writing, it is rare to see a nice blog like this one these days.|
    I’m really impressed together with your writing talents as smartly as with the structure on your blog.
    Is this a paid subject or did you customize it yourself?

    Either way stay up the excellent high quality writing, it is uncommon to peer a great weblog like this one nowadays.
    Hi, Neat post. There is a problem along with your website in web explorer,
    would check this? IE nonetheless is the marketplace chief and a huge component of people will
    leave out your wonderful writing due to this problem.|
    I am not sure where you’re getting your information, but great topic. I needs to spend some time learning more or understanding more. Thanks for excellent info I was looking for this information for my mission.|
    Hi, i think that i saw you visited my web site thus i came to “return the favor”.I am trying to find things to enhance my web site!I suppose its ok to use some of your ideas!!|
    Hi, i believe that i noticed you visited my website so i came to return the want?.I am attempting to in finding issues to enhance my web site!I guess its adequate to make use of some of your concepts!!|
    Hello there, just became alert to your blog through Google, and found that it is truly informative. I am going to watch out for brussels. I will appreciate if you continue this in future. Lots of people will be benefited from your writing. Cheers!|
    I’m now not certain where you’re getting your information, however great topic. I must spend some time studying more or working out more. Thanks for excellent info I was looking for this info for my mission.|
    Hi my friend! I want to say that this post is awesome, great written and include almost all important infos. I would like to see more posts like this .|
    hi!,I love your writing very so much! share we be in contact extra about your post on AOL? I require a specialist in this space to solve my problem. May be that’s you!

    Taking a look ahead to see you. |
    I am really loving the theme/design of your website.
    Do you ever run into any internet browser compatibility problems?
    A small number of my blog visitors have complained about my blog not working correctly in Explorer but looks great in Opera.
    Do you have any solutions to help fix this issue?
    Great information. Lucky me I found your site by accident (stumbleupon).
    I have bookmarked it for later!|
    It’s great that you are getting ideas from this post as well as from our dialogue made at this time.|
    If you wish for to increase your know-how just keep visiting this web site and be updated with the hottest news posted here.|
    What’s Going down i am new to this, I stumbled upon this I have discovered It
    positively helpful and it has helped me out loads.
    I hope to give a contribution & aid different customers like
    its aided me. Great job.|
    Hurrah, that’s what I was seeking for, what a data! present here at this weblog, thanks admin of this web site.|
    If you would like to get much from this post then you have to apply these methods to your won blog.|
    It’s an amazing article in support of all the web users;
    they will obtain benefit from it I am sure.|
    I’ve read some good stuff here. Certainly price bookmarking for revisiting. I wonder how a lot attempt you put to create this kind of wonderful informative site.|
    That is a good tip particularly to those new to the blogosphere. Short but very accurate information… Appreciate your sharing this one. A must read article!|
    I have been exploring for a little bit for any high-quality articles or weblog posts in this kind of house . Exploring in Yahoo I at last stumbled upon this website. Studying this information So i’m happy to convey that I have a very just
    right uncanny feeling I found out exactly what I needed.
    I so much certainly will make sure to do not disregard this web site
    and give it a glance regularly.|
    Having read this I believed it was rather enlightening. I appreciate you taking the time and effort to put this article together.

    I once again find myself spending a lot of time both reading and posting comments.

    But so what, it was still worthwhile!|
    Quality posts is the important to invite the users to go
    to see the web site, that’s what this web site is providing.|
    Link exchange is nothing else except it is simply placing the other person’s weblog link
    on your page at appropriate place and other person
    will also do same in support of you.|
    I have read so many articles or reviews concerning the blogger lovers
    however this paragraph is truly a pleasant paragraph, keep it up.
    Truly no matter if someone doesn’t understand after that its up to other visitors that they will assist, so here it occurs.|
    You can certainly see your expertise in the work you write. The arena hopes for even more passionate writers like you who are not afraid to say how they believe. Always go after your heart.|
    Good article. I’m experiencing many of these issues as well.
    Good site you have here.. It’s difficult to find good quality writing like yours nowadays. I honestly appreciate individuals like you! Take care!!|
    I was recommended this website by my cousin. I’m not sure whether this post is written by him as no one else know such detailed about my problem.
    You are incredible! Thanks!|
    Very good article! We are linking to this particularly great post on our website.
    Keep up the great writing.|
    Oh my goodness! Incredible article dude! Many thanks,
    However I am going through issues with your RSS. I don’t understand the reason why I can’t join it.
    Is there anybody getting identical RSS issues?
    Anybody who knows the answer will you kindly respond?
    Awesome blog! Do you have any tips and hints for aspiring writers?

    I’m planning to start my own site soon but I’m a little lost on everything.
    Would you recommend starting with a free platform like WordPress or
    go for a paid option? There are so many options
    out there that I’m totally confused .. Any suggestions? Appreciate it!|
    It’s nearly impossible to find well-informed people for this subject, however,
    you sound like you know what you’re talking about! Thanks|
    I do not even know how I ended up here, but I believed this publish used to be great. I do not recognise who you’re however certainly you are going to a well-known blogger if you
    happen to aren’t already. Cheers!|
    Good answer back in return of this difficulty with firm arguments and telling everything concerning that.|
    I don’t even know how I ended up here, but I thought this post was great.
    I don’t know who you are but definitely you are going to a famous blogger if you aren’t
    already😉 Cheers!|
    We are a group of volunteers and starting a new scheme in our community.

    Your web site offered us with helpful information to work
    on. You’ve done a formidable process and our whole community might be thankful to you.|
    Excellent way of describing, and fastidious post to get information on the topic of my presentation topic, which i am going to convey in school.|
    Great blog right here! Additionally your website lots up very fast! What web host are you using? Can I get your affiliate hyperlink to your host? I desire my web site loaded up as quickly as yours lol|
    I love your blog.. very nice colors & theme. Did you design this website yourself or did you hire someone to do it for you? Plz reply as I’m looking to construct my own blog
    and would like to know where u got this from. thank
    We are a group of volunteers and opening a new scheme in our community.
    Your web site provided us with valuable information to work
    on. You have done an impressive job and our whole community will be thankful to you.
    Appreciate the recommendation. Will try it out.|
    Asking questions are truly pleasant thing if you are not understanding something totally, however
    this piece of writing presents nice understanding even.|
    Have you ever thought about including a little bit more than just your articles?
    I mean, what you say is important and everything. However
    imagine if you added some great graphics or videos to give your posts more, “pop”!
    Your content is excellent but with images
    and clips, this site could definitely be one of the
    most beneficial in its niche. Excellent blog!|
    Your style is really unique in comparison to other folks I’ve read stuff from. I appreciate you for posting when you’ve got the opportunity,
    Guess I’ll just bookmark this web site.|
    Pretty great post. I just stumbled upon your weblog and wanted to mention that I have truly enjoyed surfing around your weblog posts. In any case I’ll
    be subscribing for your rss feed and I’m hoping you write once more very soon!|
    I’m impressed, I have to admit. Rarely do I encounter a blog that’s both educative and interesting, and let me tell you, you’ve hit the
    nail on the head. The issue is something that not enough folks are
    speaking intelligently about. Now i’m very happy I found this during my search for something relating to this.|
    Hmm it looks like your blog ate my first comment (it was extremely long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog. I as well am an aspiring blog blogger but I’m still new to everything.
    Do you have any tips for first-time blog writers? I’d really appreciate it.|
    Very nice post. I just stumbled upon your blog and wished to say that I’ve
    really enjoyed browsing your blog posts. After all I’ll be subscribing to your feed and I hope you write again very soon!|
    I like the helpful info you provide in your articles. I will bookmark your blog and check again here frequently. I am quite certain I will learn a lot of new stuff right here! Good luck for the next!|
    If you are going for best contents like I do, just pay a quick visit this site daily for the reason that it gives quality contents, thanks|
    Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point. You obviously know what youre talking about, why throw away your intelligence on just posting videos to your weblog when you could be giving us something enlightening to read?|
    Highly descriptive post, I loved that bit. Will there be a part 2?|
    Great post. I used to be checking continuously this weblog and I am inspired! Very helpful information particularly the last section🙂 I care for such info much. I used to be looking for this certain information for a long time. Thanks and good luck. |
    Excellent post. I was checking constantly this blog and I am impressed! Extremely helpful info particularly the last part🙂 I care for such info much. I was seeking this certain information for a long time. Thank you and good luck.|
    Awesome post.|
    After going over a handful of the articles on your site, I truly appreciate your way of blogging. I book marked it to my bookmark site list and will be checking back soon. Take a look at my website as well and let me know your opinion.|
    An intriguing discussion is worth comment. I think that you need to write more about this subject, it may not be a taboo subject but typically people don’t speak about such issues.
    To the next! Cheers!!|
    certainly like your web site however you need
    to test the spelling on quite a few of your posts. Several
    of them are rife with spelling problems and I find it very
    bothersome to inform the truth then again I will definitely come again again.

    I do accept as true with all of the concepts you’ve introduced to your post. They are really convincing and can definitely work. Still, the posts are too short for newbies. Could you please prolong them a little from next time? Thank you for the post.|
    My partner and I stumbled over here different web address and thought I might check things out. I like what I see so i am just following you. Look forward to exploring your web page repeatedly.|
    Very nice blog post. I absolutely love this site. Keep writing!|
    Have you ever considered creating an e-book or guest authoring on other blogs? I have a blog based on the same topics you discuss and would really like to have you share some stories/information. I know my readers would enjoy your work. If you’re even
    remotely interested, feel free to shoot me an email.
    We stumbled over here different web page and thought I may as well check
    things out. I like what I see so i am just following you.
    Look forward to finding out about your web page for a second time.

    Excellent blog here! Also your web site loads up fast! What web host are you using?
    Can I get your affiliate link to your host? I wish my web
    site loaded up as fast as yours lol|
    Hey there! I know this is kinda off topic but I was wondering which blog
    platform are you using for this website? I’m getting tired of WordPress because I’ve had
    issues with hackers and I’m looking at options for another platform. I would be great if you could point me in the direction of a good platform.|
    Hey there! I know this is kind of off topic but I was wondering if you knew where I could get a captcha plugin for my comment form? I’m using the same blog platform as yours and I’m having trouble finding one? Thanks a lot!|
    Hello there! This is my first visit to your blog! We are a team of volunteers and starting a new initiative in a community in the same niche. Your blog provided us beneficial information to work on. You have done a outstanding job!|
    After I initially left a comment I seem to have clicked on the -Notify me when new comments are added- checkbox and now whenever a comment is added I get four emails with the exact same comment. Perhaps there is a means you can remove me from that service? Many thanks!|
    First of all I want to say awesome blog! I had a quick question which I’d like to ask if you do
    not mind. I was interested to find out how you center yourself and clear your head prior to writing.
    I’ve had trouble clearing my mind in getting my ideas out there. I truly do enjoy writing however it just seems like the first 10 to 15 minutes are lost simply just trying to figure out how to begin. Any ideas or tips? Thank you!|
    This site was… how do you say it? Relevant!! Finally I have found something which helped me. Thanks a lot!|
    Everything is very open with a really clear description of the issues. It was definitely informative. Your website is useful. Thank you for sharing!|
    This design is incredible! You obviously know how to keep a reader amused. Between your wit and your videos, I was almost moved to start my own blog (well, almost…HaHa!) Fantastic job. I really enjoyed what you had to say, and more than that, how you presented it. Too cool!|
    It’s going to be ending of mine day, except before end I am reading this impressive paragraph to increase my experience.
    I pay a quick visit day-to-day some web sites and websites
    to read articles or reviews, but this weblog presents feature based articles.

    Hey there! I just wanted to ask if you ever have any issues with
    hackers? My last blog (wordpress) was hacked and I ended
    up losing a few months of hard work due to no backup.

    Do you have any methods to stop hackers?|
    I think the admin of this website is truly working hard in support of his website,
    because here every stuff is quality based information.|
    At this moment I am going away to do my breakfast, later than having my breakfast
    coming again to read more news.|
    I just like the helpful info you supply for your articles.
    I’ll bookmark your weblog and take a look at once more right here regularly. I’m reasonably sure
    I’ll be told many new stuff proper right here! Good luck for the next!|
    I think this is among the most vital information for me. And i’m glad reading your article.

    But wanna remark on some general things,
    The website style is great, the articles is really great : D.

    Good job, cheers|
    It’s a shame you don’t have a donate button! I’d certainly donate to this fantastic blog! I guess for now i’ll settle for book-marking and adding your RSS feed to
    my Google account. I look forward to fresh updates and will share this site with
    my Facebook group. Chat soon!|
    I’m not that much of a internet reader to be honest but your sites
    really nice, keep it up! I’ll go ahead and bookmark your website to come back later on. All the best|
    This piece of writing is genuinely a nice one it assists new internet users, who are wishing for blogging.|
    It’s truly a great and useful piece of info. I’m satisfied that you shared this useful information with us. Please stay us informed like this. Thank you for sharing.|
    This post provides clear idea in favor of the new visitors of blogging, that really how to do running a blog.|
    Greetings! Quick question that’s totally off topic. Do you know how to make your site mobile friendly?
    My weblog looks weird when browsing from my apple iphone.

    I’m trying to find a template or plugin that might be able to resolve this problem. If you have any suggestions, please share. Cheers!|
    Its not my first time to pay a quick visit this web page, i am browsing this site dailly and get nice facts from here daily.|
    Great blog! Is your theme custom made or did you download it from somewhere? A design like yours with a few simple adjustements would really make my blog jump out. Please let me know where you got your design. Cheers|
    This article will assist the internet people for creating new blog or even a blog from start to end.|
    I know this if off topic but I’m looking into starting
    my own blog and was wondering what all is required
    to get setup? I’m assuming having a blog like yours would cost a pretty penny? I’m
    not very internet savvy so I’m not 100% positive. Any tips or advice would be greatly appreciated. Thanks|
    My family members always say that I am killing my time here at web, however I know I am getting experience every day by reading such nice articles or reviews.|
    Spot on with this write-up, I honestly feel this amazing site needs a great deal more attention. I’ll probably
    be back again to read more, thanks for the info!|
    I know this web site gives quality depending articles and other material, is there any other site
    which provides these kinds of data in quality?
    I read this piece of writing fully on the topic of the difference of newest
    and preceding technologies, it’s remarkable article.|
    I feel that is among the most significant information for me. And i’m satisfied reading your article.
    However wanna observation on some common issues, The website style is
    perfect, the articles is really excellent : D.

    Excellent activity, cheers|
    I like reading through a post that can make people
    think. Also, thanks for allowing me to comment!
    Thanks very interesting blog!|
    Every weekend i used to go to see this site, for the reason that i wish for enjoyment, for the reason that this this web site conations truly nice funny information
    I don’t know if it’s just me or if everyone else experiencing problems with your site.
    It appears as though some of the text within your
    posts are running off the screen. Can somebody else please provide feedback and let me
    know if this is happening to them too? This may be a problem
    with my browser because I’ve had this happen previously. Cheers|
    You actually make it seem so easy with your presentation but I find this matter to be actually something which I think I would never understand. It seems too complicated and extremely broad for me. I’m looking forward for your next post, I’ll try to get the hang of it!|
    I must thank you for the efforts you’ve put in writing this website.
    I am hoping to view the same high-grade content by you
    later on as well. In fact, your creative writing abilities has encouraged me
    to get my very own website now ;)|
    It’s genuinely very complicated in this busy life to listen news on Television, therefore I simply use web for that reason, and obtain the latest information.|
    I am truly grateful to the holder of this web site who has shared this enormous paragraph at at this time.|
    I am regular reader, how are you everybody? This post posted at this site is genuinely pleasant.|
    It’s really a great and helpful piece of info.

    I am happy that you just shared this useful information with us.
    Please keep us informed like this. Thank you
    for sharing.|
    Yes! Finally someone writes about Toán Cấp Ba.

    Definitely imagine that which you stated. Your favourite justification appeared to be on the net
    the easiest factor to be aware of. I say to you, I definitely get annoyed whilst people consider worries that they just
    do not understand about. You controlled to hit the nail upon the top and defined out the whole thing with no need side effect , people can take a signal.
    Will likely be again to get more. Thanks|
    Definitely believe that which you said. Your favorite reason seemed to be
    on the net the easiest thing to be aware of.
    I say to you, I certainly get irked while people think about worries that they plainly do not know about.
    You managed to hit the nail upon the top and also defined out the whole thing without
    having side-effects , people could take a signal.
    Will probably be back to get more. Thanks|
    I am actually glad to read this webpage posts which consists of lots of useful facts, thanks for providing these kinds of
    You really make it appear really easy along with your
    presentation however I to find this matter to be actually one thing
    which I believe I would by no means understand. It kind of feels too complex and very
    huge for me. I’m taking a look ahead on your subsequent put up, I’ll attempt to get the hold of it!
    Touche. Sound arguments. Keep up the amazing
    I’m truly enjoying the design and layout of your site. It’s a very easy on the eyes which makes it much more enjoyable for me
    to come here and visit more often. Did you hire out a designer to create your theme?
    Great work!|
    Stunning quest there. What occurred after? Thanks!|
    always i used to read smaller content that also clear their motive,
    and that is also happening with this post which I am reading at this
    You ought to be a part of a contest for one of the highest quality blogs online.
    I most certainly will highly recommend this blog!|
    I’m more than happy to uncover this page. I need to to thank you for your time just for this wonderful read!! I definitely liked every part of it and i also have you book marked to look at new information in your blog.|
    Wonderful blog! I found it while browsing on Yahoo News. Do you have any suggestions on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there!
    Thank you|
    Fantastic site. Lots of helpful info here. I am sending it to several pals ans additionally sharing in delicious.
    And naturally, thanks for your effort!|
    excellent submit, very informative. I ponder why the opposite specialists
    of this sector don’t understand this. You must continue your writing. I am confident, you’ve a huge readers’ base already!|
    Excellent beat ! I would like to apprentice while you amend your web site, how can i subscribe for a blog site? The account aided me a acceptable deal. I had been tiny bit acquainted of this your broadcast offered bright clear idea|
    great points altogether, you just gained a new reader. What may you recommend in regards to your post that you simply made a few days in the past? Any certain?|
    Do you mind if I quote a couple of your articles as long as I provide credit and sources back to your website? My blog is in the exact same area of interest as yours and my users would genuinely benefit from some of the information you provide here. Please let me know if this alright with you. Cheers!|
    With havin so much content do you ever run into any problems of plagorism or copyright violation? My site has a lot of unique content I’ve
    either authored myself or outsourced but it looks like a lot of
    it is popping it up all over the web without my agreement.
    Do you know any techniques to help prevent content from being stolen?

    I’d truly appreciate it.|
    Wonderful items from you, man. I have keep in mind your stuff previous to and you’re simply extremely
    great. I actually like what you have got right here, really like
    what you’re saying and the way by which you are saying it. You’re making it entertaining and
    you continue to take care of to keep it sensible.
    I can’t wait to learn far more from you. This is really a tremendous site.|
    If some one desires to be updated with most up-to-date technologies after that he must be go to see this web page and be up to date daily.|
    I was wondering if you ever considered changing the layout of your blog? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having 1 or two pictures. Maybe you could space it out better?|
    Very quickly this web page will be famous among all blog viewers, due to it’s pleasant articles or reviews|
    If some one wishes expert view about running a blog then i advise him/her to go to see this blog, Keep up the fastidious work.
    Excellent goods from you, man. I’ve understand your stuff previous to and you are just extremely great. I really like what you’ve acquired here, really like what you’re saying and the way in which you say it. You make it enjoyable and you still care for to keep it smart. I can’t wait
    to read much more from you. This is actually a terrific website.
    Magnificent beat ! I would like to apprentice even as you amend your website, how can
    i subscribe for a weblog website? The account helped me a acceptable deal.
    I have been a little bit acquainted of this your broadcast
    provided brilliant clear concept|
    Generally I do not read article on blogs, but I wish to say that this write-up very pressured me to try and do it!
    Your writing taste has been amazed me. Thank you, quite great post.
    I was recommended this web site by way of my cousin.
    I’m not positive whether or not this put up is written by way of him as nobody else recognise such designated approximately my problem. You’re incredible!

    Thank you!|
    Hey There. I found your blog using msn. This is a really well written article.
    I’ll make sure to bookmark it and return to read more of your useful information. Thanks for the post. I’ll definitely return.
    Hello There. I found your blog the use of msn. This is a very smartly
    written article. I’ll be sure to bookmark it and return to learn extra of your helpful information. Thanks for the post. I will definitely return.|
    Thanks for a marvelous posting! I actually enjoyed reading it, you might be a great author. I will make sure to bookmark your blog and definitely will come back sometime soon. I want to encourage you continue your great work, have a nice morning!|
    Hello! I could have sworn I’ve been to this blog before but after checking through some
    of the post I realized it’s new to me. Anyways, I’m definitely
    glad I found it and I’ll be book-marking and checking back often!|
    Thanks designed for sharing such a fastidious idea, paragraph is pleasant, thats why i have read it fully|
    hello there and thank you for your information – I’ve certainly picked up something new from right here.
    I did however expertise some technical points using this website, as I experienced to reload
    the site lots of times previous to I could get it to load properly.
    I had been wondering if your web hosting is OK? Not that I am complaining, but slow loading instances times will very frequently
    affect your placement in google and can damage
    your high quality score if advertising and marketing with Adwords.
    Well I’m adding this RSS to my email and could look out for much more of your respective exciting content. Ensure that you update this again soon.|
    What i don’t understood is actually how you are now not actually much more smartly-appreciated than you may be now.
    You’re very intelligent. You already know therefore considerably when it comes to this matter, made me in my view believe it from numerous various angles. Its like men and women are not interested except it’s something to do with Woman gaga!
    Your personal stuffs great. All the time handle it up!
    Wow! In the end I got a blog from where I can genuinely obtain valuable data
    regarding my study and knowledge.|
    When someone writes an article he/she maintains the thought of a user in his/her mind that how a user can be aware of it.
    So that’s why this article is amazing. Thanks!|
    You’re so cool! I don’t think I’ve truly read through anything like this before.
    So nice to find somebody with some unique thoughts on this issue.
    Seriously.. thank you for starting this up.
    This website is one thing that is required on the web, someone with a bit of originality!
    Thanks for one’s marvelous posting! I really enjoyed reading it, you may be a great author.I will make certain to bookmark your blog and will often come back at some point. I want to encourage continue your great work, have a nice morning!|
    Appreciation to my father who informed me about this weblog, this weblog is actually amazing.|
    Article writing is also a fun, if you be acquainted with afterward you can write otherwise it is complicated to write.|
    No matter if some one searches for his essential thing, therefore he/she wishes to be available that in detail, therefore that thing is maintained over here.|
    Thanks for finally talking about >Basic Facts About C++Builder Phuongthengocdtt’s Blog

  2. Karri nói:

    Undeniably imagine that which you said. Your favorite reason appeared
    to be on the net the easiest factor to be mindful
    of. I say to you, I definitely get irked while other people think about issues that
    they plainly do not recognize about. You controlled to hit
    the nail upon the top as smartly as defined out the whole
    thing with no need side effect , folks could take a signal.
    Will probably be back to get more. Thank you

  3. Everything is very open with a very clear clarification of the challenges.
    It was truly informative. Your site is useful. Many thanks for sharing!

  4. Pingback: 長財布

  5. whatsapp nói:

    Thanks for finally writing about >Basic Facts About C++Builder | Phuongthengocdtt’s Blog <Loved it!

  6. Micheline nói:

    Hі my friend! I ѡish tto saʏ that tɦis article
    iѕ amazing, ǥreat written ɑnd include almost all ѕignificant infos.
    І’d liκe to peer morе posts likе tɦіs .

  7. It’s enormous that you are getting thoughts from this article as well as from our argument made at this time.

  8. Bret nói:

    What’s up colleagues, its fantastic article on the topic of educationand
    completely defined, keep it up all the time.

  9. Piece of writing writing is also a excitement, if you be acquainted with
    after that you can write or else it is complicated
    to write.

  10. My brother recommended I may like this blog. He was totally right.
    This put up truly made my day. You can not believe just how so much time I had spent
    for this info! Thanks!

  11. Thankfulness to my father who stated to me regarding this blog, this web
    site is truly remarkable.

  12. It’s hard to find well-informed people in this particular
    topic, but you sound like you know what you’re talking about!

  13. Hi, Neat post. There’s an issue along with your site in web explorer, may
    test this? IE nonetheless is the marketplace
    leader and a huge part of other people will
    omit your fantastic writing due to this problem.

  14. What’s Happening i’m new to this, I stumbled upon this I have found It absolutely useful and it has helped me out loads.
    I am hoping to contribute & help different users
    like its helped me. Good job.

  15. Appreciating the commitment you put into your site and in depth
    information you present. It’s great to come across a blog
    every once in a while that isn’t the same old rehashed material.

    Wonderful read! I’ve bookmarked your site and I’m including your RSS feeds to my Google account.

Gửi phản hồi

Please log in using one of these methods to post your comment: Logo

Bạn đang bình luận bằng tài khoản Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s

%d bloggers like this: