When Borland released Delphi 1 a few years ago, it was a huge success. Now on version 4, Delphi continues to be a huge success today. Sometime after Delphi 2, Borland decided to leverage the success of Delphi by creating a RAD development environment for C++. Borland leveraged that success in more ways than one. One way was by reusing parts of Delphi in C++Builder. In this chapter you learn about how Delphi and C++Builder are similar and how they are different. You also learn how to exchange code between Delphi and C++Builder and how to convert code from C++Builder to Delphi.
Delphi and C++Builder are more similar than they are different. Let's look at those similarities in the following sections.
If you have used both Delphi and C++Builder, you might have been struck by how similar their Integrated Development Environments (IDEs) are. Those of you who haven't used both Delphi and C++Builder (and even those who have), take a look at Figures 21.1 and 21.2. One of these figures is a screen shot of Delphi 3 and the other is a screen shot of C++Builder 3. I have removed the icons and program name from the title bars so that it isn't immediately apparent which is which. Can you tell the difference?
FIGURE 21.1. Delphi or C++Builder?
FIGURE 21.2. Delphi or C++Builder?
Do you give up? Figure 21.1 shows the Delphi IDE and Figure 21.2 shows the C++Builder
IDE. If you have used both Delphi and C++Builder, you might have recognized from
the Object Inspector which figure shows the Delphi IDE and which shows the C++Builder
IDE. The Delphi Object Inspector shows properties with values of True and False,
whereas the C++Builder Object Inspector shows true and false.
The point of this exercise is that the IDEs of C++Builder 3 and Delphi 3 are nearly identical. (You might have noticed I used Delphi 3 for this illustration rather than Delphi 4. I used Delphi 3 because I wanted to compare it with C++Builder 3, the latest version of C++Builder at the time of this writing, and the version that corresponds to Delphi 3.)
When you start examining the menus, you will see some differences, naturally, but for the most part the IDEs are so similar that if you know how to use one of these development environments, you know how to use the other. This has obvious benefits. For example, let's say your company has been using Delphi and now wants to add C++ to its toolset. Using C++Builder as your C++ development tool saves you time and money because your programmers don't have to learn a new development environment. That leads to another similarity between Delphi and C++Builder: the Visual Component Library.
Not only are the IDEs of Delphi and C++Builder nearly identical, but they also share the exact same component library in the VCL. The VCL is written in Object Pascal, but both Delphi and C++Builder share the same VCL (with some minor differences that I address later in the section, "VCL Enhancements").
NOTE: There has been a fair amount of discussion on the Borland newsgroups among C++ programmers on the subject of a Pascal component library in a C++ development environment. Some C++ programmers can't get over the fact that the VCL is written in Object Pascal. Most programmers, though, take the sensible approach of not caring what language the VCL is written in. They just want to get their work done on time and within budget. For these programmers, the added productivity of C++Builder far outweighs the language issue.
The fact that both Delphi and C++Builder use the same framework is again a huge benefit if you use both Delphi and C++Builder. Other than the syntactical differences between Object Pascal and C++, the VCL components are used identically in the two IDEs. Take the following Delphi code:
if OpenDialog1.Execute then Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
Now look at the C++Builder equivalent:
if (OpenDialog1->Execute()) Memo1->Lines->LoadFromFile(OpenDialog1->FileName);
As you can see, there is no difference in the use of VCL. The only differences are the differences between C++ syntax and Object Pascal syntax. This means that you don't have to learn a new framework if you want to switch between Delphi and C++Builder, or vice versa. For a company with a large number of programmers, this means that you can leverage your programmers' knowledge to the maximum. Even if you are a single programmer, knowing both Delphi and C++Builder is very valuable.
The form files used in Delphi and C++Builder are also identical. You can create a form in Delphi and reuse that form in C++Builder. Later I will explain exactly how to do that in the section "Reusing Forms." Although creating forms in Delphi and C++Builder is easy, it still takes time to design and create complex forms. By reusing your forms, you don't have to repeat work that has already been done.
Both Delphi and C++Builder use packages. In almost all cases, packages created for Delphi can be used in C++Builder. They will probably have to be recompiled in C++Builder, but that is a trivial task. The capability of C++Builder to use Delphi packages means that you have a wealth of commercial, shareware, and freeware VCL components available to you. These components are almost always written with Delphi, so they can be used in both Delphi and C++Builder. At this time you cannot use packages written for C++Builder in Delphi, but that might change with the later versions of these two products.
Although Delphi and C++Builder have many similarities, they also have many differences. Most of the differences are a result of the variations in the Object Pascal and C++ languages.
Other differences are due to what I like to call the "leapfrog effect." In the beginning there was Delphi 1. After that, naturally, came Delphi 2. After Delphi 2 was released, Borland began working on C++Builder. C++Builder 1 was patterned after Delphi 2 (which was released about a year before C++Builder 1). As such, C++Builder 1 acquired most of its features from Delphi 2. C++Builder 1 didn't add anything significant to what Delphi 2 offered--it was primarily a copycat. Shortly after C++Builder 1 was released, Borland released Delphi 3.
C++Builder 3 followed (Borland skipped version 2 of C++Builder to match Delphi's version number). C++Builder 3 is patterned after Delphi 3, just as C++Builder 1 was patterned after Delphi 2. However, C++Builder 3 added several features not found in Delphi 3 (the Project Manager, for example). Delphi 4 inherited the features introduced in C++Builder 3 and, of course, added a number of new features. C++Builder 4 will likely contain the new features of Delphi 4, will add more new features, and so on. This leapfrogging will likely continue for some time, with each release (whether it be Delphi or C++Builder) gaining the benefit of the previous release and adding new features of its own.
Now let's look at the differences between Delphi and C++Builder.
The most obvious difference between Delphi and C++Builder is that C++Builder generates C++ code and Delphi generates Object Pascal code, which leads to variations in the IDEs of the two products. For example, Delphi has a menu item under the File menu called Use Unit. C++ uses header files (.H or .HPP files) for each unit, so that menu item in C++Builder is called Include Unit Hdr. These types of differences abound throughout the two IDEs for obvious reasons.
Delphi and C++Builder use different filename extensions for project and support files. This is partly a result of the language differences between the two products. The contrasting filename extensions enable you to easily distinguish a Delphi file from a C++Builder file. Table 21.1 lists the various project elements and their respective file extensions for both Delphi and C++Builder.
Element | Delphi | C++Builder |
Project file | .DPR | .BPR |
Project group file | .BPG | .BPG |
Source file | .PAS | .CPP |
Header file | None | .H or .HPP |
Form file | .DFM | .DFM |
Compiled binary file | .DCU | .OBJ |
Compiled resources | .RES or .DCR | .RES |
Saved desktop settings | .DSK | .DSK |
Project options | .DOF | None |
Package source files | .DPK | .BPK |
Compiled package | .BPL | .BPL |
Notice that in some cases the filename extensions used by Delphi and C++Builder are the same.
The Delphi 4 IDE is brand new. In particular, the following features are new to the Delphi 4 IDE and are not found in the current version of C++Builder:
Some of the IDE enhancements listed here are cosmetic (hey, it doesn't hurt to give an application a facelift every once in awhile!). Other enhancements, such as the dockable toolbars, menus, and tool windows, are productivity boosters.
The Delphi 4 Code Editor has many features not found in C++Builder. In particular, the following features are found in Delphi 4:
Module navigation is a feature specific to the Object Pascal language, so it's no surprise that C++Builder doesn't have module navigation--but why doesn't C++Builder have code completion and code parameters? Delphi compiles the current unit each time the code completion or code parameters features are invoked. This is possible due to the incredible speed of the Object Pascal compiler. C++ code takes much longer to compile, so it is not feasible to implement code completion and code parameters in C++Builder using this same design. There are alternative means of implementing these features, so future versions of C++Builder might very well have code completion and code parameters.
C++Builder does not have class completion because it is a feature new to Delphi 4. The next version of C++Builder will likely have class completion.
The Code Explorer is also new to Delphi 4, so it is not found in any version of C++Builder. This is also a feature I expect to see in future versions of C++Builder.
The Delphi 4 VCL includes a few enhancements to VCL not yet found in C++Builder. In particular, these classes are new to VCL in Delphi 4:
As with many of the additions to Delphi 4, these new VCL components will almost certainly be added to the next version of C++Builder.
C++Builder can compile Pascal units just as easily as it can compile C++ units. This means that you can add a Pascal source file directly to a C++Builder project and C++Builder will compile the unit and link that unit's code into the project's EXE. You can add a Delphi form and unit to a C++Builder project and that form will be called just like a native C++Builder form. C++Builder has the capability to compile Pascal units, but Delphi can't compile C++Builder source files. Delphi 4 can, however, create C++ object files (.obj) from Object Pascal source.
Support for creating ActiveX controls is slightly different in C++Builder than in Delphi. Primarily, C++Builder ActiveX controls make use of the ActiveX Template Library (ATL), a C++ framework for ActiveX creation.
Delphi programs will always compile faster than C++Builder programs. Pascal compiles much faster than C++ because it isn't as complex. C++Builder's use of pre-compiled headers and the incremental linker helps reduce the effects by speeding up compile and link times, but Delphi programs still compile much faster than C++Builder programs.
Along the same lines, Delphi programs are always smaller than C++Builder programs. This is because of a number of factors, but primarily because the VCL is written in Object Pascal. Because the VCL is written in Object Pascal, a C++Builder program has to include both the C++ Runtime Library and the Object Pascal Runtime Library. Both C++ and Pascal use different exception handling and runtime type information code, which results in extra code in a C++Builder application.
At some point you might need to convert an application from Delphi to C++Builder or from C++Builder to Delphi. I have done dozens of such conversions and, although time-consuming, they are not difficult. (By the way, when converting a project, I run Delphi and C++Builder simultaneously.) In the following section I discuss converting only from Delphi to C++Builder. Converting the other way is simply a variation of the same concepts.
NOTE: Why discuss converting a Delphi application to C++Builder and not the other way around? Primarily because Delphi has a larger installed base (it's been on the market longer) and the most likely conversion is from Delphi to C++Builder. That does not necessarily mean that developers are switching to C++Builder from Delphi. I have done nearly 200 such conversions for TurboPower Software (my employer). In that case, I was converting our products' example programs, which were written in Delphi, to C++Builder. This was necessary when we began supporting our components for use in C++Builder.
Converting a project from Delphi to C++Builder involves two basic steps. The first step is to copy the Delphi application's forms to the C++Builder project. The second step is to modify the Delphi code. Let's look at these two steps in more detail.
The first thing you need to do is copy the Delphi forms to the C++Builder application. A C++Builder form and a Delphi form use the same basic format, but there is at least one significant difference that you should be aware of.
It is obvious that a form file contains the size and position of the form itself and of every component on the form. What might not be obvious, however, is that the form file also contains information about events and event handlers. Specifically, the form file includes a description of any event handlers that have been created for the form and for any components on the form. In a Delphi form file, the events contain references to event handlers in Pascal.
In a C++Builder form file, the events point to C++ event handlers. Naturally, you will have to remove the Pascal references in order to use the form in C++Builder. It isn't important that you understand this in detail, but it is a factor you will have to deal with when converting a Delphi form to C++Builder.
Here are the steps required to copy a Delphi main form:
At this point you need to be certain that all references to the Delphi event handlers are removed from the C++Builder form file. Doing this is simple, as follows:
FIGURE 21.3. Removing event handlers from the form.
At this point, you are done copying the form itself. Now you can move on to converting the code.
NOTE: You need to repeat this form-copying process for every form in the Delphi application.
Converting the code from Delphi to C++Builder is much more difficult than copying the form. There are many ways to proceed, but I'll explain the method that I use. First, look for any variables and methods that were created by the programmer and not by Delphi, as follows:
private { Private declarations } DrawColor : TColor; procedure DoDrawing; function SetDrawColor : Integer;
private: // User declarations TColor DrawColor; void DoDrawing(); int SetDrawColor();
The next step is to copy the code for the event handlers in the Delphi unit to the C++Builder unit. The best way I have found to do this is to start at the top of the implementation section in the Delphi unit and work down. Here are the steps to take when you encounter an event handler in the Delphi code:
Repeat steps 1 through 4 for every event handler in the Delphi unit. When you are done, you will have several event handlers in your C++Builder project.
The event handlers in the Delphi form file contain Pascal code, so you need to convert that code to C++. Fortunately, you can do a lot of the conversion with C++Builder's Replace Text dialog box. Table 21.2 lists the Pascal syntax you are searching for and the C++ syntax that is the replacement text. Spaces in the search or replace text are denoted by a small dot. In most cases, you will want to perform the Find and Replace operations in the order listed in Table 21.2.
Description | Find Text | Replace Text |
Equality operator | [lozenge]=[lozenge] | [lozenge]==[lozenge] |
Assignment operator | := | = |
Inequality operator | <> | != |
Membership operator | . | -> |
String quote | ` | " |
Begin comment | { | // |
End comment | } | (Nothing) |
Pascal True keyword | True | true |
Pascal False keyword | False | false |
if statement | if[lozenge] | if[lozenge]( |
Start of block | begin | { |
End of block | end; | } |
End of block (form 2) | end | } |
Pascal then statement | then | )[lozenge] |
Pascal do statement | [lozenge]do[lozenge] | (Nothing) |
Pascal not statement | not[lozenge] | ! |
Pascal nil keyword | nil | NULL |
Pascal case statement | case[lozenge] | switch[lozenge]( |
Pascal case statement | [lozenge]of[lozenge] | )[lozenge]{ |
Pascal Self keyword | Self | this |
When performing the Find and Replace, you should use the Replace All option, but you need to take care when doing so. For example, you don't want to replace all occurrences of a period with -> starting at the top of the file because the first several lines of every C++Builder source unit contain include statements with filenames.
Make sure that if you replace Pascal comments (which begin with { and end with }) with C++ comments, you do so before replacing the begin and end statements. Also, when replacing words such as end, you should turn on the Whole Words Only option in the Replace Text dialog box. This ensures that you don't accidentally replace individual characters within longer words. Be aware that some of your Find and Replace operations could have undesirable side effects (such as replacing the period that separates a filename and its extension with ->).
TIP: Consider writing a Microsoft Word macro that performs the Find and Replace operations shown in Table 21.2. It can save you a great deal of time if you have a lot of units to convert.
After you have performed the Find and Replace operations, you will have a file that is a mixture of Pascal and C++. The easy part is finished, and now you must go to work converting the rest of the file by hand. You have to know enough about each language to know how to convert Pascal syntax to C++ syntax. You're on your own from this point on, but I can point out a few issues to be aware of as you convert the rest of the file.
First, there is no C++ equivalent to the Pascal with statement. Take this code, for example:
with MyForm do begin Width := 200; Height := 500; Caption := `Hello there'; end;
When you convert this code to C++Builder, you have to specifically reference each property:
MyForm->Width = 200; MyForm->Height = 500; MyForm->Caption = "Hello there";
Another Pascal statement that requires some work to convert is the as statement. You frequently see code like this in Delphi programs:
with Sender as TButton do Click;
In C++Builder, this code is translated as follows:
TButton* button = dynamic_cast<TButton*>(Sender); if (button) button->Click();
Another area that requires special attention is string handling. Pascal has string manipulation functions that operate on the string data type. C++Builder, on the other hand, has the AnsiString class, which has its own string manipulation functions. Take, for example, this Pascal code:
This code is translated to C++Builder code like this:
X = Edit->Text.ToInt();
As with strings, the C++Builder equivalent to Pascal sets is a C++ class. In the case of sets, the C++ class is called Set. The following code examples illustrate conversion of Pascal set syntax to C++Builder's Set class. I used the Font property's Style member to illustrate. First look at the Pascal code:
{Clear the set.} Font.Style := []; { Add the bold and italics styles. } Font.Style := Font.Style + [fsBold, fsItalic]; { Remove the italics style. } Font.Style := Font.Style - [fsItalic]; { See if the set contains the fsBold style. } if fsBold in Font.Style then { Code here if the font is bold. }
Here's the C++Builder equivalent to this code:
// Clear the set.
Font->Style.Clear(); // Add the bold and italics styles. Font->Style = Font->Style << fsBold << fsItalic; // Remove the italics style. Font->Style = Font->Style >> fsItalic; // See if the set contains the fsBold style. if (Font->Style.Contains(fsBold)) // Code here if the font is bold.
I can't explain every difference between Object Pascal and C++ in this chapter, but these few examples should be enough to get you started. If you are using C++Builder, you should check out my C++Builder book, Sams Teach Yourself Borland C++Builder 3 in 21 Days (ISBN 0-672-31266-2). That book explains some of the differences between Object Pascal and C++ in detail.
You don't have to convert Delphi forms to C++ at all if you don't want to. You can use Delphi forms in C++Builder just as they are. Simply add the .PAS file for the form directly to your C++Builder project. C++Builder will create a header for the Delphi unit that you can use in any C++Builder units that reference the Delphi form.
NOTE: Although you can add a Delphi form to a C++Builder project, you cannot edit the form with the C++Builder Form Designer. Any modifications that you want to make to the form visually must be made from the Delphi IDE. You can, however, edit the form as text from within the C++Builder IDE. Choose the View As Text option from the C++Builder Form Designer's context menu to edit the form in text format.
Delphi and C++Builder are not so much competing products as they are complementary products. If you know how to program with C++Builder, learning Delphi is relatively easy. Moving from Delphi to C++Builder isn't quite as easy because of the complexity of the C++ language, but if you decide to move from Delphi to C++Builder, you can at least be assured that you won't have to learn a new framework. Without question, being proficient in both Delphi and C++Builder makes you a more valuable programmer.
The Workshop contains quiz questions to help you solidify your understanding of the material covered and exercises to provide you with experience using what you have learned. You can find the answers in Appendix A, "Answers to the Quiz Questions."
This was a pretty productive week, wasn't it? Unlike Visual Component Library (VCL) components, COM and ActiveX controls can be used by a wide variety of programming environments. The good news is that Delphi gives you the fastest route to ActiveX creation of any programming environment available today.
You probably had no idea that database operations could be so easy. Easy is a relative thing. I wouldn't go so far as to say that database programming is ever simple, but Delphi certainly makes it easier than it would be in other programming environments.
On Day 19, you learned about dynamic link libraries (DLLs). Regardless of whether you decide to use DLLs right away, you can at least see their benefits and can make an informed decision regarding their use in your programs. If you plan on calling Delphi forms from programs not written in Delphi, you will have to use DLLs. DLLs are not difficult, but here again, a little experience goes a long way.
On Day 20, you learned about creating your own components. You either loved it or you were left scratching your head. If the latter is the case, don't worry about it. You might never have to write your own components. There are plenty of sources for good, commercial-quality components. (See Appendix B, "Delphi Internet Resources," for a few.) Plus, you can always go back and tackle Day 20 again after you've accumulated some time in your Delphi log book. If you enjoyed learning about writing components, it was probably difficult for you to read the last chapter! I'd be willing to bet that at some time during Day 20 you could have been overheard saying, "Wow!" Writing your own components is rewarding--no question. I had time only to scratch the surface of covering how to write components. There is a lot more to learn, and much of that can be learned by experience only. This chapter gives you enough to get you started.
Finally, you learned about Delphi and C++Builder and how they can work together. Delphi and C++Builder are two great products. If you know how to use one of these programming environments, learning the other is very easy. The more you know, the more valuable you are as a programmer.
© Copyright, Macmillan Computer Publishing. All rights reserved.