Teach Yourself Borland Delphi 4 in 21 Days

Previous chapterNext chapterContents


- 21 -

Delphi and C++Builder


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.

Similarities Between Delphi and C++Builder

Delphi and C++Builder are more similar than they are different. Let's look at those similarities in the following sections.

The IDE

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.

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.

Form Files

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.

Packages

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.

Differences Between Delphi and C++Builder

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.

Language

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.

Filename Extensions

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.

TABLE 21.1. DELPHI AND C++BUILDER FILE EXTENSIONS.

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.

IDE

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.

Code Editor

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.

Code Explorer

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.

VCL Enhancements

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

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.


ActiveX Support

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 Compiles Faster and Produces Smaller EXEs

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.

Converting from Delphi to C++Builder

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.


Copying the Delphi Forms

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:

1. Open the project in Delphi and make note of the main form's filename and its Name property.

2. Switch to C++Builder and select the main form. Change the Name property to the same name as the Delphi project's main form.

3. Save the C++Builder project. Save the main form's unit with the same filename the form had in Delphi (minus the .PAS extension, of course). Save the project with the same project name as the Delphi project.

4. Switch to Windows Explorer. Copy the main form's form file (the .DFM file) from the Delphi project's directory to the C++Builder project's directory. Make sure that you copy the file, not move it. Explorer will warn you that a file with the same filename exists in the destination directory. Click Yes to overwrite the form file in the C++Builder directory. If you don't get this warning, you have done something wrong in saving the C++Builder unit.

5. Switch back to C++Builder. A dialog box will be displayed that says Module XXX.CPP's time/date has changed. Reload?. Click Yes to reload the form. When the form reloads, it will contain the components found on the Delphi form.

6. Make sure that the form is selected and then choose Edit|Select All from the C++Builder main menu to select all the form's components. Now choose Edit|Cut from the main menu, immediately followed by Edit|Paste. This step ensures that all the declarations for the individual components are placed in the main form's header file.

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:

1. Choose File|Save from the C++Builder main menu or click the Save File button on the toolbar.
2. C++Builder will display a message box for each event handler associated with the form, as shown in Figure 21.3. Click Yes each time the dialog box is displayed to remove all event handlers. Be aware that you might have to click Yes dozens of times to remove all the event handlers. (I've had to remove as many as 100 event handlers for a single form!)

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

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:

1. Locate the main form's class declaration in the Delphi unit.

2. Make note of any variables or methods declared in the private or public sections.

3. Copy any such declarations to the Clipboard. For example, part of the Delphi class declaration might look like this:

private
  { Private declarations } 
  DrawColor : TColor;
  procedure DoDrawing;
  function  SetDrawColor : Integer;


In this case you would copy the declarations for DrawColor, DoDrawing, and SetDrawColor.
4. Switch back to C++Builder. Display the main form's header in the Code Editor. Locate the private section and paste the code from the Clipboard.

5. Convert the declarations you pasted to C++ syntax. For example, the declarations in the example in step 3 would look like this after being converted:

private:  // User declarations
  TColor DrawColor;
  void DoDrawing();
  int SetDrawColor();


6. Switch back to Delphi. In the implementation section of the Delphi unit, locate any methods declared in the class declaration (DoDrawing and SetDrawColor in this example). Copy the methods in the Delphi unit to the Clipboard.

7. Switch to C++Builder. Paste the methods copied in step 6 from the Clipboard to the form's source unit. Convert the first line of the methods (the method header) from Pascal syntax to C++ syntax. Don't worry about the function bodies or the begin and end statements. You'll fix that later.

Copying the Event Handlers

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:

1. Make note of the event handler's name. If the name is Button1Click, you know that the event handler is for the OnClick event of the component named Button1.

2. Copy the code inside the event handler to the Clipboard.

3. Switch to C++Builder. Generate an event handler that matches the event handler from which you copied the code.

4. Paste the Delphi code from the Clipboard into the event handler.

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.

Using the Replace Text Dialog Box

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.


TABLE 21.2. FIND AND REPLACE TEXT WHEN CONVERTING FROM DELPHI TO C++BUILDER.

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.

The Pascal with Statement

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";

The Pascal as Statement

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();

Dealing with Strings

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:

X := STRTOINT(EDIT.TEXT);

This code is translated to C++Builder code like this:

X = Edit->Text.ToInt();

Converting Sets

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.

Reusing Forms

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.

Summary

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.

Workshop

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."

Q&A

Q Can I use Pascal units in a C++Builder project?

A Yes. Add the Pascal unit to your project just as you would add a C++ unit. Be sure to put the Pascal units above any C++ units that reference code in the Pascal units in the Project Manager.

Q Can I use C++ units in my Delphi projects?

A No. You can use Pascal units in C++Builder but not the other way around.

Q As a programmer, I'm curious about something: Are the Delphi and C++Builder IDEs built from the same code base?

A Yes. Although Delphi and C++Builder have obvious differences, they have many similarities, so Borland uses a single code base for both IDEs.

Q Why do my Delphi projects compile so much faster than my C++Builder projects?

A Because Object Pascal is less complex than C++ and thus compiles faster.

Q I have heard that if I know C++Builder, learning Delphi is simple. Is that true?

A Not exactly, no. Despite stereotypes regarding Pascal, Delphi's Object Pascal is relatively complex. Although going from C++Builder to Delphi is easier than the reverse, it is still not something that should be approached lightly.

Quiz

1. Do Delphi and C++Builder project files have the same filename extension?

2. Do Delphi and C++Builder form files have the same filename extension?

3. Can you use packages from third-party component vendors in both Delphi and C++Builder?

4. Can you open a Delphi form file in C++Builder?

5. Can you edit a Delphi form file using the C++Builder Form Designer?

6. Can you use a C++Builder source unit in Delphi?

7. Which is better, Delphi or C++Builder?

Exercises

1. If you have C++Builder, take an example from the Delphi Demos directory and convert it to C++Builder.

2. Take an example in the C++Builder Examples directory and convert it to Delphi.

3. Take a break, you've finished your 21st day!

In Review

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.


Previous chapterNext chapterContents

© Copyright, Macmillan Computer Publishing. All rights reserved.